| layout | default |
|---|---|
| title | Aider Tutorial - Chapter 5: Advanced Prompting |
| nav_order | 5 |
| has_children | false |
| parent | Aider Tutorial |
Welcome to Chapter 5: Advanced Prompting. In this part of Aider Tutorial: AI Pair Programming in Your Terminal, you will build an intuitive mental model first, then move into concrete implementation details and practical production tradeoffs.
Master advanced prompting techniques to get better results from AI, including context provision, specificity, and iterative refinement.
The quality of your prompts directly affects the quality of Aider's responses. This chapter covers advanced prompting techniques to communicate effectively with AI and get the results you want.
# ❌ Vague
> Add error handling
# ✅ Specific
> Add try-catch blocks to the database connection methods in db.py that raise ConnectionError with descriptive messages when connections fail# ❌ No context
> Add validation
# ✅ With context
> Add input validation to the user registration API endpoint that checks email format using regex and password strength (minimum 8 characters, at least one uppercase, one lowercase, one number)# ❌ Implementation not specified
> Add caching
# ✅ Implementation specified
> Add Redis caching to the get_user_profile function with 5-minute TTL, using the redis-py library and connection pooling# AI is great at:
# - Code generation from specifications
# - Understanding patterns and conventions
# - Bug detection and fixing
# - Documentation writing
# - Refactoring and restructuring
# - Following established patterns
> Create a REST API endpoint for user management that follows REST conventions, includes proper HTTP status codes, and validates input data# AI needs guidance for:
# - Business logic decisions
# - Performance vs simplicity trade-offs
# - Security considerations
# - Integration with existing systems
> Implement user authentication, but use JWT tokens instead of sessions, and ensure the tokens expire after 24 hours. Also, make sure to hash passwords with bcrypt before storing them.# Break complex tasks into steps
> Step 1: Create a User model class with fields for id, username, email, and password_hash
> Step 2: Add methods for password hashing and verification
> Step 3: Create a database migration for the users table
> Step 4: Add the model to the SQLAlchemy configuration# Reference similar patterns in your codebase
> Create an Order model similar to the existing Product model, but with customer_id, total_amount, and status fields# Be explicit about constraints
> Create a function to validate credit card numbers that:
> - Accepts Visa, MasterCard, and American Express
> - Uses the Luhn algorithm for validation
> - Returns a boolean and an error message
> - Does not store or log the card number anywhere# First iteration: Basic functionality
> Create a simple function that sends an email
# Second iteration: Add features
> Add email templates and HTML support to the email function
# Third iteration: Add reliability
> Add retry logic and error handling to the email function# After AI generates code
> /diff # Review the changes
# Request improvements
> The error handling could be more specific. Catch SMTP-specific exceptions separately from network errors.
# Or ask for alternatives
> Instead of using smtplib directly, use a library like Flask-Mail for better integration with Flask applications# Include relevant files
> /add models.py routes/auth.py
# Explain the current architecture
> We're using Flask with SQLAlchemy ORM and Flask-Login for session management. Add user registration functionality.# Aider remembers the conversation, so build upon previous work
> Add user login functionality that works with the registration system we just created
# Reference previous decisions
> Use the same password hashing approach we implemented in the User model# Start fresh for unrelated tasks
> /clear
# Or be explicit about scope
> Create a new utility module for data processing that doesn't depend on the existing authentication code# Reference common patterns
> Implement the Repository pattern for data access, with separate repositories for User, Product, and Order entities
# Follow framework conventions
> Create a Django REST framework viewset for the User model with standard CRUD operations and proper serialization# Specify coding standards
> Write the code following PEP 8 style guidelines, with type hints, and comprehensive docstrings in Google style
# Follow project conventions
> Use the same logging and error handling patterns as the existing codebase in utils/logging.py# Break down complex features
> Implement user authentication with the following components:
> 1. User model with password hashing
> 2. Registration endpoint with validation
> 3. Login endpoint with JWT token generation
> 4. Protected route decorator
> 5. Password reset via email# Specify integrations clearly
> Integrate with our existing PostgreSQL database using SQLAlchemy, and add proper indexes for the email and username fields# Include performance requirements
> Optimize the user search query with database indexes and implement caching with Redis for frequently accessed user profiles# Request comprehensive error handling
> Implement file upload functionality that handles large files, validates file types, prevents directory traversal attacks, and provides proper error messages for all failure cases# Ask AI to help debug
> The user registration is failing with a database error. The error message is "UNIQUE constraint failed: users.email". Help me debug this issue.
# Or provide stack traces
> I'm getting this error when calling the API: [paste error]. The code is in api/users.py. What could be causing this?# Emphasize security
> Implement user authentication with secure password hashing using bcrypt, protection against timing attacks, and proper session management that includes secure cookie settings# Request thorough validation
> Add input sanitization and validation to the user profile update endpoint that prevents XSS attacks, validates email formats, and enforces length limits on all text fields# Specify authorization requirements
> Implement role-based access control where admin users can manage all resources, regular users can only access their own data, and implement proper authorization checks in all API endpoints# Ask for comprehensive testing
> Create unit tests for the user authentication functions, including tests for valid login, invalid credentials, password hashing, and edge cases like empty passwords# Request code reviews
> Review this authentication code for security vulnerabilities, performance issues, and adherence to best practices# Specify OOP patterns
> Refactor this procedural code into classes following the Single Responsibility Principle, with a UserService class for business logic and a UserRepository class for data access# Request functional approaches
> Rewrite this imperative function using functional programming principles with pure functions, immutable data structures, and higher-order functions# Specify async patterns
> Convert these synchronous database operations to async using asyncio and async SQLAlchemy for better concurrency# Django
> Create a Django model for User with proper field validations, model methods, and admin integration
# Flask
> Implement Flask blueprints for API routes with proper error handling and JSON responses
# Express.js
> Create Express middleware for authentication using JWT tokens with refresh token functionality# SQLAlchemy
> Create SQLAlchemy models with proper relationships, indexes, and constraints for a multi-tenant SaaS application
# Django ORM
> Design Django models with foreign keys, many-to-many relationships, and custom managers for complex querying# pytest
> Write pytest test cases with fixtures, parametrization, and mocking for the authentication service
# Jest
> Create Jest tests for React components including user interactions, API calls, and error states# Ask AI to improve your prompts
> I've been asking you to implement features, but the code quality could be better. What questions should I ask to get higher quality code?
# Or create templates
> Create a template for prompts when requesting new API endpoints that includes all the necessary details# Guide AI's reasoning
> To implement user notifications, I need to:
> 1. Define the notification data structure
> 2. Create a service to send notifications
> 3. Add database storage for notification history
> 4. Create API endpoints to manage notifications
> 5. Add real-time delivery mechanism
> Let's start with step 1# ❌ Too broad
> Build a web application
# ✅ Focused
> Create a Flask route for user login with form validation and error handling# ❌ Assumes AI knows your setup
> Add logging
# ✅ Provides context
> Add structured logging using the logging library with JSON format, log levels, and rotation, similar to how it's done in utils/logging.py# ❌ Incomplete
> Create a user model
# ✅ Complete
> Create a SQLAlchemy User model with fields: id (primary key), username (unique, 80 chars), email (unique, 120 chars), password_hash (128 chars), created_at (datetime), is_active (boolean). Include methods for password hashing and verification.In this chapter, we've covered:
- Clear Communication: Being specific and providing context
- Iterative Refinement: Starting simple and improving incrementally
- Context Management: Managing conversation state and scope
- Pattern-Based Prompting: Following established conventions
- Complex Requirements: Breaking down multi-step tasks
- Security and Quality: Requesting secure, well-tested code
- Framework-Specific: Tailoring prompts to different technologies
- Advanced Techniques: Meta-prompting and chain of thought
- Be Specific: Clear, detailed prompts produce better results
- Provide Context: Include relevant files and architectural information
- Iterate: Start simple and refine through multiple interactions
- Follow Patterns: Reference existing code and established conventions
- Break Down Tasks: Divide complex work into manageable steps
- Specify Constraints: Include security, performance, and quality requirements
- Review and Improve: Always review changes and ask for improvements
Now that you can prompt effectively, let's explore model configuration and how to choose the right AI model for different tasks.
Ready for Chapter 6? Model Configuration
Generated for Awesome Code Docs
This chapter is expanded to v1-style depth for production-grade learning and implementation quality.
- tutorial: Aider Tutorial: AI Pair Programming in Your Terminal
- tutorial slug: aider-tutorial
- chapter focus: Chapter 5: Advanced Prompting
- system context: Aider Tutorial
- objective: move from surface-level usage to repeatable engineering operation
- Define the runtime boundary for
Chapter 5: Advanced Prompting. - Separate control-plane decisions from data-plane execution.
- Capture input contracts, transformation points, and output contracts.
- Trace state transitions across request lifecycle stages.
- Identify extension hooks and policy interception points.
- Map ownership boundaries for team and automation workflows.
- Specify rollback and recovery paths for unsafe changes.
- Track observability signals for correctness, latency, and cost.
| Decision Area | Low-Risk Path | High-Control Path | Tradeoff |
|---|---|---|---|
| Runtime mode | managed defaults | explicit policy config | speed vs control |
| State handling | local ephemeral | durable persisted state | simplicity vs auditability |
| Tool integration | direct API use | mediated adapter layer | velocity vs governance |
| Rollout method | manual change | staged + canary rollout | effort vs safety |
| Incident response | best effort logs | runbooks + SLO alerts | cost vs reliability |
| Failure Mode | Early Signal | Root Cause Pattern | Countermeasure |
|---|---|---|---|
| stale context | inconsistent outputs | missing refresh window | enforce context TTL and refresh hooks |
| policy drift | unexpected execution | ad hoc overrides | centralize policy profiles |
| auth mismatch | 401/403 bursts | credential sprawl | rotation schedule + scope minimization |
| schema breakage | parser/validation errors | unmanaged upstream changes | contract tests per release |
| retry storms | queue congestion | no backoff controls | jittered backoff + circuit breakers |
| silent regressions | quality drop without alerts | weak baseline metrics | eval harness with thresholds |
- Establish a reproducible baseline environment.
- Capture chapter-specific success criteria before changes.
- Implement minimal viable path with explicit interfaces.
- Add observability before expanding feature scope.
- Run deterministic tests for happy-path behavior.
- Inject failure scenarios for negative-path validation.
- Compare output quality against baseline snapshots.
- Promote through staged environments with rollback gates.
- Record operational lessons in release notes.
- chapter-level assumptions are explicit and testable
- API/tool boundaries are documented with input/output examples
- failure handling includes retry, timeout, and fallback policy
- security controls include auth scopes and secret rotation plans
- observability includes logs, metrics, traces, and alert thresholds
- deployment guidance includes canary and rollback paths
- docs include links to upstream sources and related tracks
- post-release verification confirms expected behavior under load
- Cline Tutorial
- Roo Code Tutorial
- Continue Tutorial
- Codex Analysis Platform
- Chapter 1: Getting Started
- Build a minimal end-to-end implementation for
Chapter 5: Advanced Prompting. - Add instrumentation and measure baseline latency and error rate.
- Introduce one controlled failure and confirm graceful recovery.
- Add policy constraints and verify they are enforced consistently.
- Run a staged rollout and document rollback decision criteria.
- Which execution boundary matters most for this chapter and why?
- What signal detects regressions earliest in your environment?
- What tradeoff did you make between delivery speed and governance?
- How would you recover from the highest-impact failure mode?
- What must be automated before scaling to team-wide adoption?
- tutorial context: Aider Tutorial: AI Pair Programming in Your Terminal
- trigger condition: incoming request volume spikes after release
- initial hypothesis: identify the smallest reproducible failure boundary
- immediate action: protect user-facing stability before optimization work
- engineering control: introduce adaptive concurrency limits and queue bounds
- verification target: latency p95 and p99 stay within defined SLO windows
- rollback trigger: pre-defined quality gate fails for two consecutive checks
- communication step: publish incident status with owner and ETA
- learning capture: add postmortem and convert findings into automated tests
- tutorial context: Aider Tutorial: AI Pair Programming in Your Terminal
- trigger condition: tool dependency latency increases under concurrency
- initial hypothesis: identify the smallest reproducible failure boundary
- immediate action: protect user-facing stability before optimization work
- engineering control: enable staged retries with jitter and circuit breaker fallback
- verification target: error budget burn rate remains below escalation threshold
- rollback trigger: pre-defined quality gate fails for two consecutive checks
- communication step: publish incident status with owner and ETA
- learning capture: add postmortem and convert findings into automated tests
- tutorial context: Aider Tutorial: AI Pair Programming in Your Terminal
- trigger condition: schema updates introduce incompatible payloads
- initial hypothesis: identify the smallest reproducible failure boundary
- immediate action: protect user-facing stability before optimization work
- engineering control: pin schema versions and add compatibility shims
- verification target: throughput remains stable under target concurrency
- rollback trigger: pre-defined quality gate fails for two consecutive checks
- communication step: publish incident status with owner and ETA
- learning capture: add postmortem and convert findings into automated tests
- tutorial context: Aider Tutorial: AI Pair Programming in Your Terminal
- trigger condition: environment parity drifts between staging and production
- initial hypothesis: identify the smallest reproducible failure boundary
- immediate action: protect user-facing stability before optimization work
- engineering control: restore environment parity via immutable config promotion
- verification target: retry volume stays bounded without feedback loops
- rollback trigger: pre-defined quality gate fails for two consecutive checks
- communication step: publish incident status with owner and ETA
- learning capture: add postmortem and convert findings into automated tests
- tutorial context: Aider Tutorial: AI Pair Programming in Your Terminal
- trigger condition: access policy changes reduce successful execution rates
- initial hypothesis: identify the smallest reproducible failure boundary
- immediate action: protect user-facing stability before optimization work
- engineering control: re-scope credentials and rotate leaked or stale keys
- verification target: data integrity checks pass across write/read cycles
- rollback trigger: pre-defined quality gate fails for two consecutive checks
- communication step: publish incident status with owner and ETA
- learning capture: add postmortem and convert findings into automated tests
Most teams struggle here because the hard part is not writing more code, but deciding clear boundaries for Create, user, error so behavior stays predictable as complexity grows.
In practical terms, this chapter helps you avoid three common failures:
- coupling core logic too tightly to one implementation path
- missing the handoff boundaries between setup, execution, and validation
- shipping changes without clear rollback or observability strategy
After working through this chapter, you should be able to reason about Chapter 5: Advanced Prompting as an operating subsystem inside Aider Tutorial: AI Pair Programming in Your Terminal, with explicit contracts for inputs, state transitions, and outputs.
Use the implementation notes around email, model, using as your checklist when adapting these patterns to your own repository.
Under the hood, Chapter 5: Advanced Prompting usually follows a repeatable control path:
- Context bootstrap: initialize runtime config and prerequisites for
Create. - Input normalization: shape incoming data so
userreceives stable contracts. - Core execution: run the main logic branch and propagate intermediate state through
error. - Policy and safety checks: enforce limits, auth scopes, and failure boundaries.
- Output composition: return canonical result payloads for downstream consumers.
- Operational telemetry: emit logs/metrics needed for debugging and performance tuning.
When debugging, walk this sequence in order and confirm each stage has explicit success/failure conditions.
Use the following upstream sources to verify implementation details while reading this chapter:
- Aider Repository
Why it matters: authoritative reference on
Aider Repository(github.com). - Aider Releases
Why it matters: authoritative reference on
Aider Releases(github.com). - Aider Docs
Why it matters: authoritative reference on
Aider Docs(aider.chat).
Suggested trace strategy:
- search upstream code for
Createanduserto map concrete implementation paths - compare docs claims against actual runtime/config code before reusing patterns in production