Agent Experience: Best Practices for Coding Agent Productivity
More and more developers use coding agents (e.g., Claude Code, GitHub Copilot, or Cursor) in their daily work. But the performance of these agents varies greatly. I’ve seen numerous examples of a negative productivity gain, when using an agent takes longer than doing the task manually. However, some developers do report significant productivity gains, even on large and complex codebases. These codebases seem to be more agent-friendly. How do they differ from other codebases?
Based on my experience and feedback I’ve gathered from fellow developers, I’ve assembled a list of 40+ good practices for optimizing the Agent Experience, or the ability for coding agents to work autonomously on complex tasks.
Coding agents are modeled after developers, so most of the Developer Experience (DX) good practices also apply to Agent Experience. That’s why some of the practices listed below also appear in Software Craftsmanship, Test-Driven Development, Domain-Driven Design, SOLID, and other established guides to good coding practices.
Domain Knowledge
Agents work better when they understand the domain they operate in. In traditional software, domain knowledge is documented outside the codebase (docs, wikis, etc.). Agents work mostly on the codebase, so they perform better if domain knowledge is mixed with the code.
There are several ways to embed domain knowledge in the codebase:
- Add agent instructions A dedicated Markdown file (
AGENTS.md,CLAUDE.md, ideally both) that briefly explains the domain concepts, the personas, the design principles, etc. The Agents.md best practices explain that it should be short and to the point, as coding agents read this file at the beginning of every session. - Comment the code Add code comments to explain complex logic, business rules, and design decisions. Focus on what problem the code is solving rather than how it is solving it.
- Use domain names Use naming conventions that reflect their purpose and domain concepts, not their technical implementation (e.g.,
OrderProcessorinstead ofOrderServiceFactory). - Test corner cases Write comprehensive test suites that cover various scenarios and edge cases. Agents won’t read these tests unless they have to, but they will discover the edge cases when they break them.
- Embed documentation in code Add Markdown files or docstrings within the codebase to provide additional context and explanations for complex modules or components. Mention these files in related code so that the agent can find them easily.
- MCP servers If your domain knowledge lies in an external service like Notion or Confluence, consider using their MCP server to let your agent search there, too. Beware, though, that these connectors may overwhelm the agent context with too much information.
Code SEO
Coding agents don’t need to read or index the entire codebase because they use powerful search tools to find relevant code (mostly find, grep, and ls). However, on large codebases, you often need to make the code easier to find, just like you would carefully choose keywords and meta descriptions for web pages to improve their SEO.
Here are some techniques to help agents find the right code more easily:
- Use synonyms Incorporate synonyms and related terms in comments to help agents recognize concepts even if different terminology is used. For example, if you have a
Customerclass, mentionClientandUserin the comments. - Avoid duplicate names If an agent finds multiple files with the same name (e.g.,
index.ts), it will have to read them all to discover the one it’s looking for. This consumes time and context. - Avoid abbreviations Agents usually search for complete words. Using abbreviations or acronyms may make your code harder for agents to find.
- Use a consistent structure Agents will quickly learn to find their way around a consistently organized codebase. Subsequent searches will be faster and consume less context.
- Use tags and labels In comments, add tags or labels to files, classes, or functions to categorize them based on functionality, domain concepts, or design patterns. This allows agents to filter and find relevant code more easily. Think of these tags as facets in e-commerce sites.
- Include directory descriptions Create documentation files (e.g.,
README.md) in each important folder that summarize the contents and purpose of the folder. When they list the contents of a folder, agents often start by reading such files, so it’s a good way to guide them.
Brevity
LLMs have limited context, and the contributions of coding agents decrease in quality as the context fills up. To maximize useful context, reduce verbosity in the codebase. This can be done in several ways:
- Split large files into smaller, focused modules That way, agents don’t need to read large files to find a single function or class.
- Refactor large functions into smaller, reusable components Agents often read files in chunks. It slows them down to have to read several chunks to understand a single function.
- Avoid obvious comments that do not add value Although coding agents themselves love to over-comment code, these comments often paraphrase the code without adding useful information.
- Limit error traces When logging errors, avoid logging the full stack trace by default. Add a
--verboseflag to log more details when needed. - Remove dead code A half-finished refactoring can actually harm the contributions of coding agents.
Tip: Although you may be tempted to reduce verbosity in variable and function names, I don’t recommend it, as it would make the code less readable for both humans and agents.
Serendipity
We sometimes discover information we didn’t know we needed. This is called serendipity. Although it often happens by chance, we can design our codebases to facilitate serendipity for coding agents.
- Include cross-references Link related modules, functions, or classes together using comments or documentation. This helps agents discover connections between different parts of the codebase.
- Tagging Use tags or labels in comments or documentation to categorize code snippets based on functionality, domain concepts, or design patterns. This is an invitation to explore related code.
- Self-documented commands If your project includes CLI commands or API endpoints that the agent can call, make it easy for the agent to discover their usage. For instance, include basic API usage in error output, support the standard
--helpflag, or provide an OpenAPI specification. You can even use self-documented makefiles. - Embedded technical documentation Store technical documentation alongside the code, especially for external APIs, libraries, or frameworks used in the project. This helps agents quickly understand how to interact with these components without needing to search for external resources (which they often fail to do properly due to versioning).
Testability
When an agent makes a change to the codebase, you need a way to ensure it brings the expected added value. The best way to do so is to have a comprehensive test suite that the agent can run after each change. Otherwise, you’ll have to test manually and report each bug to the agent, which is tedious and error-prone. With a strong test suite, you can let the agent work autonomously on long tasks with confidence.
- Write tests first Without automated tests, the agent will miss important corner cases and regressions, and act with too much confidence. Test-Driven Development (TDD) is even more important when working with coding agents.
- Reproduce bugs with tests Whenever you need to fix a bug, write a test that reproduces it (or ask the agent to do so) before working on the fix.
- Write tests by hand It can be tempting to ask the agent to write tests for you, but these tests are often superficial and don’t cover edge cases. Writing tests by hand ensures that you have understood the requirements properly, and that’s the main role of a developer.
- Plug your browser into the agent Recent agent updates (e.g., Chrome in Claude Code, Antigravity) let them open and control a browser window to test web apps autonomously. This dramatically improves their ability to validate their own code.
- Mock external dependencies Use mocking frameworks to simulate external dependencies (e.g., APIs, databases) in your tests. This allows agents to run tests in isolation without relying on external systems. This probably implies that you’re using the adapter pattern in your codebase.
- Provide fine-grained testing tools Use testing frameworks that allow agents to run specific tests or test suites, rather than the entire test suite. This speeds up the feedback loop and allows agents to focus on relevant areas of the codebase.
Conventions
Agents were trained on a lot of old code and few recent productions. As a result, they are better at manipulating established concepts than new, shiny libraries. They also need more guidance when the code deviates from established conventions.
- Use boring tech Spring, Symfony, or Ruby on Rails may look like old technologies, but they are also very well known, and agents rarely get them wrong. In contrast, using React Server Components is a bit more risky.
- Use design patterns Design patterns are proven solutions to common problems. Agents know them. When you use an Adapter or a Factory, the agent doesn’t have to read its code to understand what it does, so design patterns are a good way to synthesize your code.
- Add Architecture Decision Records (ADRs) When you need to introduce a custom architecture, write down your thought process and the final decision in Markdown files committed with your code. ADRs help agents follow architectural principles when making changes.
- Include schemas Sometimes a picture is worth a thousand words. Agents can read images, too. Use state diagrams, flowcharts, or UML diagrams to illustrate complex workflows, data models, or system architectures. Store these images in the codebase and reference them in relevant code comments or documentation.
- Superpower: Go open source Open-source projects become part of the training sets of LLMs. If you can open-source parts of your code, then coding agents don’t even need to look at the code. We authored the popular react-admin framework and many other open-source libraries, and we don’t need to teach coding agents how to use them.
Guardrails
Sometimes coding agents produce incorrect code. It’s better to catch this early.
- Introduce hooks Some agents allow you to execute custom scripts after they generate a response and before outputting it. For instance, Claude Code has hooks for this purpose. This lets you refuse responses with known problems (e.g., writing to the main branch, inline styles, committing
.env, using certain libraries, etc.), and the agent will try again and return once the problems are fixed. - Plug in specialized MCP servers You can also add third-party tools and ask your agent to systematically call them before committing, using custom instructions. For example, tools like Codacy offer an MCP server that integrates seamlessly into your coding workflow.
- Increase CI checks Consider code pushed by a coding agent as tainted. This means the CI should execute extra security checks (such as CodeQL) to detect vulnerabilities introduced by the agent.
- Require PR reviews Never merge code written by an agent without a human review. Even with all the guardrails in place, agents can still make mistakes that only a human can catch. And no, delegating reviews to another agent won’t solve this.
Usage Instructions
When an agent discovers a method or command that is useful for the current task, it needs to learn how to use it.
- Include usage examples The doc block for a function should contain at least one working example of code calling the function, with sample input and output. This way, agents won’t need to read the function code to use it.
- Use Context7 Third-party libraries publish online documentation, but agents take too much time learning site structures and fetching large pages. Instead, add the Context7 MCP Server to your agent. You can even pinpoint the exact version of each dependency you’re using. No more fetching Stack Overflow.
- Use sensible defaults The best parameter for a function call is no parameter. Design APIs so that default arguments match the most common use case.
- Avoid user interactions Whenever possible, design your code so that agents can run commands without user input. For instance, avoid interactive prompts in CLI commands, and prefer configuration files or command-line arguments instead.
Coding Rules
Coding agents already know best practices, but your company probably has custom coding or formatting rules that deviate from common practices. How can you enforce them?
- Add rule files Coding agents let you document your coding practices in specialized files that they read before every task.
.cursor/rules,copilot-instructions.md, orCLAUDE.mdare ideal places for your coding standards. - Enforce rules with hooks Pre-commit hooks, or even better, agent hooks, let you automatically detect when coding standards aren’t respected and produce feedback that the agent can use to fix the problem. You can also use them to lint or auto-format your code.
- Commit coding standards with the code Don’t use agent memory or user-space agent instructions (e.g.,
~/.claude/settings.json), as other developers won’t use them. Instead, commit the agent instruction files to put everyone on the same footing. - Avoid duplication One of the most annoying habits of coding agents is reinventing the wheel. They usually only search briefly for existing code before writing their own. In my custom instructions, I ask agents to spend extra time looking for similar code before adding a new method or class.
To get you started, there are popular lists of rules for every language or framework that you can pick from.
Tip: Whenever you comment on a pull request opened by an agent, make sure to include your comment in the project rules as well, so the agent can learn from it.
Tooling & Delegation
Given the sheer number of blog posts about AI tooling on the internet, it may come as a surprise that this section comes last. I’ve realized that coding agents are already quite good, and most of the time I don’t need anything special (besides carefully designing the feature and implementation in plan mode) to get them to produce what I want.
For example, if I need to apply a refactoring, I just need to mention Martin Fowler for the agent to understand that I want a step-by-step, always-green process. There’s no need to build a specialized agent for that.
That said, custom tools and specialized agents can sometimes help, especially when you have repetitive tasks that require custom instructions. So feel free to experiment with the practices below.
- Add custom MCP servers The MCP protocol is like a universal plugin system for agents. You can find MCP servers to connect to almost every service, from databases and knowledge bases to monitoring platforms and translation services. Before writing your own MCP server, check the Awesome MCP Servers list.
- Add skills Anthropic recently introduced an alternative to MCP servers called Skills, designed to build specialized agents. It’s also a standard, but adoption lags behind MCP. Follow the skills examples or reuse existing skills to teach your agent frontend design, web app testing, or security audits.
- Add sub-agents For task-specific workflows, and to reduce the context used by the main agent, you can design sub-agents and delegate specific types of tasks to them. This can be useful once you have too many tools and want to limit the number of tools available for certain tasks.
Some web developers encourage using swarms of agents to work on several coding tasks in parallel using Git worktrees. The most extreme example is GasTown, a so-called “multi-agent workspace manager.” In my experience, when the output of agents overwhelms my own cognitive capacity, the quality of the code drops sharply, so I avoid this approach.
Agent Experience Is an Ongoing Process
Agent Experience isn’t an exact science, and agents evolve quickly. Some of the practices listed above may not work in your context or may become useless over time. I recommend testing each practice first and only adopting it if it significantly improves your coding workflow.
Each time you give a task to a coding agent, pay attention to the mistakes it makes and update your codebase and tooling accordingly. Over time, you’ll progressively build an agent-friendly codebase and increase your productivity.
Finally, the best way to detect good practices for coding with an agent is to look at your own prompts. I recommend taking the time to review your coding sessions every once in a while and adding tooling to avoid repeating the same instructions over and over again.
Conclusion
At Marmelab, we use coding agents every day, and we’ve discovered some of these practices the hard way. We’ve noticed that they aren’t necessary when starting a new project, but they become critical as the codebase grows in size and complexity. Just like with strict typing, investing in Agent Experience early can pay off significantly in the long run.
We’re already using these practices in the projects we develop for our customers. We’ve noticed significant improvements in agent understanding and autonomy, as well as a reduction in the number of comments we post on agent pull requests. For public examples of codebases using these practices, check our open-source projects Atomic CRM, Shadcn Admin Kit, and React-Admin.
If you have discovered more ways to improve Agent Experience, please share them with us. I’ll update this list as we learn new tricks.
Authors
Marmelab founder and CEO, passionate about web technologies, agile, sustainability, leadership, and open-source. Lead developer of react-admin, founder of GreenFrame.io, and regular speaker at tech conferences.