Building with AI Coding Agents: Best Practices for Agent Workflows
Over the past year, I’ve been working extensively with AI coding agents — intelligent assistants that go far beyond code autocompletion. These agents can plan, execute, and iterate on entire development tasks. They function like tireless pair programmers who never lose focus or context, dramatically increasing productivity when guided correctly.
However, without clear direction, agents often produce inconsistent or overly complex outputs. After several messy repositories and unfinished code snippets, I learned that the difference between chaos and clarity lies in how you direct your agent, not just what you ask it to do.
In this post, I’ll share the best practices that have consistently helped me when working with coding agents.
What Are AI Coding Agents?
AI coding agents are autonomous systems that use large language models to perform software development tasks. Unlike simple code completion tools, agents can:
- Plan: Break down complex tasks into actionable steps
- Execute: Run commands, edit files, and interact with development environments
- Observe: Read outputs, check test results, and analyze errors
- Iterate: Adjust approach based on feedback and continue working
Agent vs. Assistant: Key Differences
| Feature | AI Assistant | AI Agent |
|---|---|---|
| Autonomy | Waits for prompts | Works independently |
| Memory | Session-limited | Persistent context |
| Tools | Code suggestions | Full IDE/CLI access |
| Feedback loop | Single turn | Multi-step iteration |
| Goal | Help you code | Code for you |
Golden Rules for AI-Assisted Development
After extensive experimentation, I’ve distilled these core principles that consistently lead to better outcomes:
-
Use markdown files to manage the project — Maintain
README.md,PLANNING.md, andTASK.mdfiles for project documentation and task tracking. -
Keep files under 500 lines — Split into modules when files approach this limit to maintain readability and maintainability.
-
Start fresh conversations often — Long chat threads degrade response quality. Restart when conversations get lengthy.
-
Don’t overload the model — One task per message yields more consistent results than bundling multiple requests.
-
Test early, test often — Every new function should have unit tests. Catch bugs early to prevent compounding problems.
-
Be specific in your requests — The more context and examples you provide, the better the output.
-
Write docs and comments as you go — Don’t delay documentation. Update
README.mdand code comments during development. -
Implement environment variables yourself — Never trust the LLM with API keys or sensitive credentials.
Planning and Task Management
Before writing any code, have a conversation with the AI to plan the initial scope and tasks for the project. This upfront investment pays dividends throughout development.
PLANNING.md
The PLANNING.md file captures high-level vision, architecture decisions, constraints, tech stack, and tools.
Purpose:
- Document architectural decisions
- Define tech stack and tools
- Record project constraints and requirements
- Establish coding conventions and patterns
Prompt to AI: “Use the structure and decisions outlined in PLANNING.md.”
Have the AI reference this file at the beginning of any new conversation to maintain context consistency.
TASK.md
The TASK.md file tracks current tasks, backlog items, and sub-tasks throughout the project lifecycle.
Purpose:
- Track active work items
- Record completed milestones
- Capture discoveries made during development
- Maintain a prioritized backlog
Prompt to AI: “Update TASK.md to mark XYZ as done and add ABC as a new task.”
Configure your AI assistant to automatically update TASK.md as it completes work through global rules.
Setting Up Global Rules for AI IDEs
Global rules (or project-level rules) are the most effective way to enforce consistent behavior from AI coding assistants. All major AI IDEs support both global and project-specific rules:
| AI IDE | Documentation |
|---|---|
| Cursor Rules | docs.cursor.com/context/rules-for-ai |
| Windsurf Rules | docs.codeium.com/windsurf/memories#windsurfrules |
| Cline Rules | docs.cline.bot/improving-your-prompting-skills/prompting |
| Roo Code Rules | Works the same as Cline |
Here’s a comprehensive example of global rules you can adapt for your projects:
### 🔄 Project Awareness & Context
- **Always read `PLANNING.md`** at the start of a new conversation to understand
the project's architecture, goals, style, and constraints.
- **Check `TASK.md`** before starting a new task. If the task isn't listed, add
it with a brief description and today's date.
- **Use consistent naming conventions, file structure, and architecture patterns**
as described in `PLANNING.md`.
### 🧱 Code Structure & Modularity
- **Never create a file longer than 500 lines of code.** If a file approaches this
limit, refactor by splitting it into modules or helper files.
- **Organize code into clearly separated modules**, grouped by feature or responsibility.
- **Use clear, consistent imports** (prefer relative imports within packages).
### 🧪 Testing & Reliability
- **Always create unit tests for new features** (functions, classes, routes, etc).
- **After updating any logic**, check whether existing unit tests need to be updated.
If so, do it.
- **Tests should live in a `/tests` folder** mirroring the main app structure.
- Include at least:
- 1 test for expected use
- 1 edge case
- 1 failure case
### ✅ Task Completion
- **Mark completed tasks in `TASK.md`** immediately after finishing them.
- Add new sub-tasks or TODOs discovered during development to `TASK.md` under a
"Discovered During Work" section.
### 📎 Style & Conventions
- **Follow language-specific best practices** (PEP8 for Python, etc.)
- **Use type hints** where applicable.
- **Use appropriate frameworks** for data validation and APIs.
- Write **docstrings for every function** using a consistent style.
### 📚 Documentation & Explainability
- **Update `README.md`** when new features are added, dependencies change, or
setup steps are modified.
- **Comment non-obvious code** and ensure everything is understandable to a
mid-level developer.
- When writing complex logic, **add an inline `# Reason:` comment** explaining
the why, not just the what.
### 🧠 AI Behavior Rules
- **Never assume missing context. Ask questions if uncertain.**
- **Never hallucinate libraries or functions** – only use known, verified packages.
- **Always confirm file paths and module names** exist before referencing them
in code or tests.
- **Never delete or overwrite existing code** unless explicitly instructed or
part of a task from `TASK.md`.
Configuring MCP (Model Context Protocol)
MCP enables your AI assistant to interact with external services, dramatically expanding its capabilities:
Essential MCP Servers:
| Server | Purpose | Repository |
|---|---|---|
| Crawl4AI RAG | Crawl and leverage external documentation | github.com/coleam00/mcp-crawl4ai-rag |
| Supabase MCP | Manage databases, tables, and queries | github.com/supabase-community/supabase-mcp |
| Brave Search | Search the web for documentation | github.com/modelcontextprotocol/servers/tree/main/src/brave-search |
Additional Useful Servers:
| Server | Purpose | Repository |
|---|---|---|
| Filesystem | Read/write, refactor, multi-file edits | github.com/modelcontextprotocol/servers/tree/main/src/filesystem |
| Git | Branching, diffing, committing | github.com/modelcontextprotocol/servers/tree/main/src/git |
| Claude Task Master | Advanced task management | github.com/eyaltoledano/claude-task-master |
MCP Configuration Guides:
| AI IDE | Documentation |
|---|---|
| Cursor MCP | docs.cursor.com/context/model-context-protocol |
| Windsurf MCP | docs.codeium.com/windsurf/mcp |
| Cline MCP | docs.cline.bot/mcp-servers/mcp |
| Roo Code MCP | docs.roocode.com/features/mcp/using-mcp-in-roo |
For a comprehensive list of available MCP servers with installation instructions, visit the Model Context Protocol servers repository.
Crafting the Initial Project Prompt
The first prompt to begin a project is the most critical. Even with comprehensive PLANNING.md, clear tasks in TASK.md, and well-configured global rules, you must provide detailed context about what you want the AI to create.
Three Ways to Provide Examples and Documentation:
-
Use built-in documentation features — Many AI IDEs support referencing documentation directly. For example, typing “@docs” in Windsurf and hitting tab tells the AI to search specific documentation sources.
-
Have the AI use MCP servers — Instruct the AI to search the web using MCP servers like Brave Search: “Search the web to find other Python MCP server implementations.”
-
Manually provide examples — Include code snippets, URLs, or reference materials directly in your prompt.
Example Initial Prompt:
Use @docs:model-context-protocol-docs and @docs:supabase-docs to create an MCP
server written in Python (using FastMCP) to interact with a Supabase database.
The server should use the Stdio transport and have the following tools:
- Read rows in a table
- Create a record (or multiple) in a table
- Update a record (or multiple) in a table
- Delete a record (or multiple) in a table
Be sure to give comprehensive descriptions for each tool so the MCP server can
effectively communicate to the LLM when and how to use each capability.
The environment variables for this MCP server need to be the Supabase project
URL and service role key.
Read this GitHub README to understand best how to create MCP servers with Python:
https://github.com/modelcontextprotocol/python-sdk/tree/main
After creating the MCP server with FastMCP, update README.md and TASK.md since
you now have the initial implementation for the server.
Important: Restart conversations when they get lengthy. You’ll know it’s time when the AI’s responses start frustrating you or losing coherence.
Modular Prompting for Follow-up Tasks
After the initial project setup, handle follow-up fixes and changes one task at a time. It’s tempting to bundle multiple requests, but focused prompts yield consistently better results.
Good Example:
“Now update the list records function to add a parameter for filtering the records.”
Bad Example:
“Update list records to add filtering. Then I’m getting an error for the create row function that says API key not found. Plus I need to add better documentation to the main function and in README.md for how to use this server.”
The key principle: Have the AI focus on updating a single file whenever possible.
Always instruct the AI to update README.md, PLANNING.md, and TASK.md after making changes to keep documentation synchronized with code.
Testing Strategy
Catching bugs early prevents compounding problems. Either configure global rules to mandate unit tests after each feature, or explicitly request tests as a follow-up task.
Best Practices for AI-Generated Tests:
- Create tests in a
/testsdirectory mirroring your main application structure - Mock external service calls — Never make real database or API calls in tests
- Test three scenarios per function:
- One successful/expected use case
- One intentional failure (to verify error handling)
- One edge case
If the AI gets stuck on complex test scenarios and you need to move forward, you can explicitly instruct it to bypass test writing for that specific feature and revisit later.
Containerization and Deployment
When ready to deploy or share your project, containerization with Docker provides the most consistent packaging method. AI assistants excel at Docker configurations, making this an ideal task to delegate.
Benefits of Containerization:
- Consistent deployment across environments
- Supported by virtually all cloud platforms (Render, Railway, Coolify, DigitalOcean, Cloudflare, Netlify)
- Simplifies dependency management
- Easy to version and roll back
Example Dockerfile:
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy the application files
COPY . .
CMD ["python", "server.py"]
Build Command:
docker build -t myapp:latest .
Example Prompt:
Write a Dockerfile for this application using requirements.txt. Give me the
commands to build and run the container.
I containerize all AI agents, API endpoints, and MCP servers as Docker containers—it’s the most reliable deployment method I’ve found.
Conclusion
Working effectively with AI coding agents is a skill that improves with practice. The key takeaways from my experience:
- Invest in setup — Time spent on
PLANNING.md,TASK.md, and global rules pays exponential dividends. - Communicate clearly — Specific, focused prompts with examples produce superior results.
- Test continuously — Catch bugs early before they compound.
- Document as you go — Keep
README.mdand code comments synchronized with changes. - Know when to restart — Fresh conversations beat struggling with context-degraded threads.
AI coding agents are powerful tools that can dramatically accelerate development when guided properly. They’re not replacements for developer judgment—they’re force multipliers that amplify your productivity when directed with clear intent and structured workflows.