There is a lot of debate about which model to choose and how to write a good prompt. In practice, that is not where the difference is made. Two teams using the same model get very different results depending on the state of the project they hand over to it: architecture documentation that is current or missing, tests that are reliable or nonexistent, build commands that are reproducible or known to one person only, secrets that are protected or sitting in a .env file readable by every tool.

This article proposes a method for building that environment: a development harness. It is aimed at experienced developers, Tech Leads, CTOs and engineering managers who want AI-assisted development to stay maintainable, collaborative, safe and vendor-independent.

A word on the nature of the information. I distinguish three levels, flagged in the text:

  • Documented: a feature described in the tool's official documentation, consulted in October 2026. These points change quickly, so check the version you use.
  • Practice: a general engineering good practice, independent of any tool.
  • Opinion: a personal recommendation drawn from experience, and therefore debatable.

1. Understanding the development harness

A working definition

In the context of coding agents, I use harness to mean everything that surrounds the language model to make it useful, controllable and reproducible: instructions, tools, permissions, tests, procedures and verification mechanisms. The term has no normative definition. It is a metaphor (the harness that equips and guides), and other authors propose variants. Opinion: this broad definition is useful because it forces you to look beyond the prompt.

Four layers not to confuse

LayerWhat it isQuestions to ask
The language modelThe system that produces text and code from a contextWhich model for which task? What context window? What cost?
The agentThe loop that plans, calls tools, reads the results and starts againHow far can it act on its own? When does it stop to ask?
The toolsFile read and write, shell, search, browser, MCP serversWhich tools are available? With which permissions?
The execution environmentThe repository, dependencies, tests, CI, secrets, network, workstation or containerCan the project be built and tested reproducibly?

When a result is disappointing, the temptation is to blame the model. More often, the flaw lies in the other three layers: a contradictory context, an overly permissive tool, a project that no single command can test.

The language modelproduces text and code from a contextThe agentplans, calls tools, reads the resultsThe toolsfiles, shell, search, MCP serversThe execution environmentrepository, dependencies, tests, CI, secrets, networkRules and guardrails
Four distinct layers, crossed by rules, permissions and checks. A flaw can sit in any of them.

Why a good model does not compensate for a poorly structured project

A powerful model reasons better, but it cannot guess what is written nowhere: the reason for a convention, the internal dependency not to touch, the test that has been flaky for six months. In a project without tests, the agent has no way to verify its own work: it proposes plausible code, and verification falls back on human review, which becomes the bottleneck. Conversely, a project where scripts/test.sh runs in two minutes and fails clearly gives the agent a feedback loop it can use on its own.

1Read the context2Plan3Call a tool4Read the result5Verify (tests, lint)6Fix or concludeEvery turn: verify, orfail silently
The loop of a coding agent. The quality of the result depends on what the environment returns at each turn, tests in particular.

Practice: the same elements (written rules, tests, tools, guardrails) improve the work of humans and agents alike. Investing in the harness is therefore not a cost reserved for AI. It is engineering debt that AI simply makes more visible and more expensive.

2. Organizing the project context

The principle: one source of truth, several readers

A project's context is what a newcomer, human or agent, needs to know to work without causing damage. The classic risk is that each developer, and each agent, builds their own understanding, with divergences that surface at code review. The remedy is to make the context explicit, versioned and unique.

Source of truthReadersREADME and docs/architecturediagrams, components, flowsDevelopersonboarding and code reviewscripts/one command per actionCI and agentsreproducible build, tests, lintAGENTS.md (short)rules, commands, prohibitionsAgentspoints to docs/ on demand
A single source of truth, read by different readers. Agent instructions point to the documentation instead of copying it.

The useful elements, in approximate order of return on investment:

  • A short README: what the project is for, how to install it, how to run the tests.
  • Architecture documentation: components, their responsibilities, data flows, constraints. A diagram and two pages are worth more than thirty obsolete pages.
  • Architecture decision records (ADRs): a short document per decision (context, options, choice, consequences). This is what avoids endless re-discussion, and prevents an agent from "fixing" a deliberate choice.
  • Code conventions: naming, module structure, error handling, logging. Ideally enforced by a linter rather than merely described.
  • Directory structure: what goes where, including the areas not to modify (generated code, vendored dependencies).
  • Build, test and deployment procedures: as versioned scripts (scripts/), not paragraphs to copy and paste.
  • Dependency and version management: lock files, update policy, expected runtime versions.

Keep instructions short, and point to the rest

Documented: assistants generally load their instruction files into the model's context, and some cap their size. The Codex documentation, for example, states a default limit of 32 KiB for all instruction files combined. Practice: even without a cap, a large instruction file dilutes the model's attention and consumes context on every request.

Two flaws come up often:

  1. The instruction file that becomes a catch-all: at first a few rules, then a decision log, a progress report, migration notes. What is true at a given moment (the state of a migration, for example) has no place in a permanent context: it ages, and the model reads it as truth.
  2. Multiple sources of truth: the same information copied in several places, which drift apart over time. When two documents contradict each other, the agent picks one of them, and nobody knows which.

Opinion: apply a simple rule. The instruction file contains what is always true and always useful: commands, working rules, prohibitions, and links to the detailed documentation that the agent will read on demand. Everything else lives in docs/, with a single owner per topic.

Beware of AI-generated documentation

Having an assistant write the documentation is tempting, and often useful as a first draft. The danger is the loop: an agent rereads documentation that an agent produced without verification, and treats it as established fact. Practice: mark the status of what is generated ("not rechecked"), have a human review whatever serves as a reference, and prefer short, verifiable documents with an owner.

3. Maintainability and collaborative work

Shared conventions for humans and agents

The goal is for a change to look like the rest of the code, whether a person or an agent wrote it. That requires explicit conventions that are, above all, automatically verifiable: formatter, linter, type checking, tests. A written rule that nothing checks is a suggestion. A rule enforced by CI is a fact.

Constraining automatic changes

Agents tend to do too much: reformat an entire file, rename things along the way, "improve" neighboring code. This produces diffs that are hard to review and creates conflicts. A few practices that limit this drift:

  • Define the scope in the request: the files or modules concerned, what is out of scope, what must not change.
  • Ask for a plan before the code on non-trivial tasks, and approve it.
  • Require small, independent changes: one topic per branch, one topic per review.
  • Tolerate zero cosmetic changes outside the scope, or isolate them in a dedicated commit.
  • Keep the diff readable: if a change exceeds what a human can seriously review, that is a signal to split it.

A single, versioned checkpoint that CI and agents call in the same way avoids divergence between "what the agent does locally" and "what CI verifies":

#!/usr/bin/env sh
# scripts/check.sh: the same check for humans, agents and CI
set -eu
scripts/lint.sh          # formatting, style rules, types
scripts/test.sh          # unit and integration tests
scripts/scan-secrets.sh  # secret detection (tool of your choice)

Git, reviews and tests as a safety net

Practice: work on a dedicated branch, never directly on the main branch; go through code review, human for anything that matters; have CI run the tests and checks, out of the agent's reach. That last point is essential: CI is the only guardrail the agent cannot bypass by modifying its own rules.

To avoid conflicts between human and generated changes, the same rules as in a team apply: short-lived branches, frequent rebases or merges, clear ownership of code areas, no long isolated agent session on files that others are modifying.

Ensuring continuity when someone else takes over

An agent has no reliable memory from one session to the next, and a developer may pick up another's work. In both cases, what makes the handover possible is written down: the task description, the progress, the decisions made, what remains to be done. Practice: a short tracking file for each long task (in the merge request or the ticket, rather than in a conversation), with the commands to reproduce the current state. A conversation is not documentation: lasting decisions must land in the repository or in the ticketing tool.

4. Security and protection of sensitive data

An agent is convenient because it reads files, runs commands and talks to services. That is exactly what makes it dangerous if it is poorly constrained. This section is deliberately the strictest.

Secrets

  • Never put a secret in a prompt, an instruction file or a repository. This includes passwords, tokens, API keys, certificates and the contents of .env files. What is sent to an external model leaves your perimeter; what is committed stays in the history.
  • Manage secrets outside the repository: a secrets manager, variables injected by CI or the runtime environment, .env.example files without real values in the repository.
  • Keep on the workstation only what the task needs. A development machine that holds production environment files gives every tool launched on it access to production.
  • Add a secret-detection check in CI and, if possible, before the commit.

Documented: Claude Code can deny reading specific paths through deny rules in its configuration files (for example Read(./.env)). The documentation states that a .claudeignore-type file has no effect, and that these deny rules do not replace operating-system-level isolation, because they do not cover every way of accessing a file (a program launched by the shell, for example). Practice: treat the tool's rules as a first layer, not as a guarantee.

Here is what this type of rule looks like in a project's configuration file. It is an example to adapt: check the exact syntax in the documentation for the version you use.

{
  "permissions": {
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)"
    ]
  }
}

Minimal permissions

Practice: apply the principle of least privilege to agents as you would to any service account.

  • Grant read access only to the directories that are needed, and write access to a narrow scope.
  • List the allowed commands rather than forbidding dangerous ones one by one.
  • Control network access: an agent that can call any URL can also send code or data to it.
  • Separate environments: the agent works against a development environment, never with production credentials.
  • Take irreversible or costly actions out of the agent's reach: production deployment, data deletion, messages sent to customers, payments.

Documented: Claude Code evaluates deny and ask rules regardless of a hook's response, and a hook can tighten the rules but cannot lift a denial. Hooks (for example before a tool runs) allow you to add programmatic checks. Other tools have comparable mechanisms, in a different form: read their documentation rather than assuming equivalence.

AgentToolChecks(permissions,hooks)HumanSystemRequests anaction (command,file)Submits theaction to therulesDeny, confirm or allow dependingon the rulesAsks forapproval(sensitiveoperation)Approves orrefusesExecution allowed only afterapproval
Illustrative path of a sensitive action. The checks sit between the agent and the system, outside the model: the exact detail depends on the tool and its configuration.

Human approval of sensitive operations

Opinion: define in writing the list of operations that require explicit human approval, and enforce it with a technical mechanism (confirmation prompt, permission denied by default), not just a sentence in an instruction file. A typical and frequent example: a production deployment command that exists in the project and that the agent can run without confirmation because nobody thought to forbid it.

MCP, extensions and third-party tools

MCP servers and extensions give the agent new capabilities: access to databases, APIs, browsers. Each one widens the attack surface.

  • Treat an MCP server as code you execute, with the user's rights: check its provenance, the permissions it requests, its maintenance.
  • Version the list of servers allowed for the project, and avoid personal extensions implicitly imposed on colleagues.
  • Keep prompt injection in mind: an agent that reads a web page, a ticket or a third-party file may run into hostile instructions there. The fewer powers it has, the less dangerous those instructions are.

Infrastructure guarantees and declarative guarantees

This is the most important distinction in this section. An infrastructure guarantee is enforced by a system the model does not control: an account without write access to production, a network that blocks outbound traffic, a container without access to secrets, a CI that refuses the merge. A declarative guarantee is a sentence asking the model to behave: "never read .env files", "do not deploy without approval". The latter is useful for steering behavior, but it prevents nothing: a model can ignore it, misinterpret it, or lose it when the context is truncated. For any rule whose violation would be costly, look for the infrastructure version.

Declarative guaranteeA sentence in a prompt or an instructionfileDepends on the model's interpretationCan be ignored or lost when the context istruncatedUseful for steering behaviorInfrastructure guaranteeEnforced by a system the model does notcontrolAccount without write access, filterednetwork, blocking CIDoes not depend on the model's behaviorPreferred for critical rules
Two families of guarantees. For any rule whose violation would be costly, look for the infrastructure version.

Confidential code and external tools

When an external model or tool processes confidential code, the question is first contractual and organizational: where is the data sent, how long is it retained, is it used for training, what is the service level (enterprise or consumer offering)? Practice: classify code and data by sensitivity, define what may leave the organization, use offerings whose terms are documented and validated by your security team, and keep the option of a local or private deployment for the most sensitive content. For data subject to regulation, have compliance officers validate the usage before deployment, not after.

5. Compatibility across LLMs and assistants

The risk: a project locked into a single tool

Each assistant has its own conventions: an instruction file, a configuration directory, a format for commands and rules. A project whose knowledge is entirely locked in one tool's format becomes dependent on it: switching assistants, or having several tools coexist in a single team, forces you to rewrite everything. The remedy is to organize the project around a vendor-independent documentation base, with thin adaptation layers per tool.

What the main tools' conventions say (October 2026)

The table below summarizes what I could verify in the official documentation or, failing that, what remains to be confirmed. File names and their support change regularly.

ToolInstruction fileDirectory or configurationStatus of the information
Claude CodeCLAUDE.md, which can import other files with @path.claude/ including settings.json (permissions, hooks)Documented. According to the documentation consulted, AGENTS.md is read directly only when there is no CLAUDE.md, and in recent versions; otherwise, a CLAUDE.md that imports @AGENTS.md is the recommended solution.
OpenAI Codex (CLI)AGENTS.md (and AGENTS.override.md), one file per directory, merged from the root down to the current directory~/.codex/config.toml, and a project-level .codex/config.toml according to secondary sourcesDocumented for AGENTS.md, per-directory discovery, configurable fallback names and the 32 KiB default limit. To verify for configuration precedence.
Gemini CLIGEMINI.md by default, configurable name, imports with @file.md.gemini/settings.json (project) and ~/.gemini/settings.json (user)Documented for GEMINI.md, its levels (global, workspace and parents, on-demand loading) and imports. To verify: the exact name of the key for declaring other file names differs between versions of the documentation.
Cline.clinerules/ directory (.md and .txt files)Global rules in a system directoryDocumented. The documentation also mentions automatic detection of AGENTS.md.
Roo Code.roo/rules/ directory, with per-mode variants (.roo/rules-<mode>/)Extension settingsPartially verified. AGENTS.md support is attested by secondary sources and a documentation proposal; to be confirmed in the installed version.

The AGENTS.md format is presented by its promoters as an open format intended for several assistants. Several secondary sources cite other tools that use it (Cursor, Aider, Zed, Jules, Devin), but I have not verified each of these claims in the relevant tool's documentation: do not present AGENTS.md as universal in your internal documentation before you have tested every tool you use. A file is not a standard just because it is widespread.

A layered architecture

Here is the architecture I recommend, presented as an illustration to adapt (Opinion):

Validation procedurescode review, definition of done, ADRsAutomated tests and CIthe shared verification loopSecurity controlssecrets, dependencies, minimal permissionsPer-tool configuration.claude/, .codex/, .gemini/, hooks, allowed MCPAdaptation layersCLAUDE.md, GEMINI.md: import the shared instructionsAgent instructionsAGENTS.md: short, sharedShared documentationREADME, docs/architecture, docs/decisionsVersioned in the repository
Layered architecture of the project. Only two layers depend on a vendor: the adaptation and the configuration specific to each tool.
  1. Shared project documentation, independent of any tool: README.md, docs/architecture/, docs/decisions/. This is the source of truth, read by humans and agents alike.
  2. General instructions for agents: a short file (AGENTS.md) that contains the commands, working rules, prohibitions, and links to the documentation.
  3. Per-tool adaptation layers: small files that point to the shared instructions (for example a CLAUDE.md that imports AGENTS.md) and contain only what is specific to the tool.
  4. Tool-specific rules and configuration: permissions, hooks, allowed MCP servers, custom commands, in the tool's directory (.claude/, .codex/, .gemini/, etc.).
  5. Security controls: secret detection, dependency analysis, minimal permissions, human approval of sensitive operations.
  6. Automated tests and CI: the verification loop shared by all tools, the only one that does not depend on the model.
  7. Validation procedures: code review, definition of done, decision log.

Layers 1, 2, 5, 6 and 7 are portable by construction. Layers 3 and 4 are where you accept dependency, but keep it small, documented and replaceable.

The limits of portability

Making a project compatible with several assistants does not guarantee identical results. Each model interprets the same instructions differently, follows long rules more or less faithfully, and handles context and tools differently. Two assistants reading the same AGENTS.md can produce different work. Practice: portability guarantees that the project remains understandable and usable; only an evaluation on your own tasks tells you about the quality you get with each tool (see the next section).

You also have to accept that some features have no equivalent across tools (hooks, subagents, custom commands, permission formats). It is better to document that than to simulate an equivalence that does not exist.

6. Backward compatibility and longevity

A harness is an internal product: it evolves, and its changes can break existing usage. A few practices for evolving it without surprises:

1Change theharnessinstructions,permissions, tools(versioned)2Run the referencetasksrepresentative set,several runs3Compare with theexpected resultsuccess, scoperespected, cost4Roll out or rollbackdocumented fallbackprocedure
Evolving the harness without breaking existing usage: every change goes through the same reference tasks, with a rollback available.
  • Version the instructions and configurations in the repository, with code review and history, like code. A rule change is a system change.
  • Document the dependencies on vendor-specific features: which hook, which command, which minimum tool version. A short list in docs/ is enough.
  • Maintain reference tasks: a small set of representative tasks (fix a bug, add an endpoint, refactor a module, write a test) with the expected result and how to verify it.
  • Test model and tool updates on these tasks before rolling them out to the team. A version change can alter behavior without warning.
  • Verify on a representative sample, not on a single favorable example: variability between runs is real.
  • Keep fallback procedures: know how to go back to a previous version of the tool or the harness, and how to work without an assistant if necessary. A harness whose absence blocks the team is a risk.
  • Avoid implicit dependencies: do not rely on an undocumented proprietary format or capability, or on personal plugins installed on a single workstation. What is not in the repository does not exist for the rest of the team.

7. A concrete example

An illustrative project structure

The following structure is an example for discussion, not a standard. The comments indicate what is a documented convention of the tool and what remains to be verified in the version you use.

project/
├── README.md                  # overview, installation, how to run the tests
├── AGENTS.md                  # general instructions, short, shared
├── CLAUDE.md                  # adapter: imports @AGENTS.md (Claude Code convention)
├── GEMINI.md                  # optional adapter: @AGENTS.md import, verify per version
├── docs/
│   ├── architecture/          # overview, components, flows
│   └── decisions/             # ADRs: one decision per file
├── tests/                     # automated tests
├── scripts/                   # setup.sh, test.sh, lint.sh: single, versioned commands
├── .claude/                   # settings.json: permissions, hooks (Claude Code specific)
├── .codex/                    # Codex project configuration, verify per version
└── .gemini/                   # Gemini CLI settings.json, verify per version

Do not create a configuration directory "just in case": a file that no tool reads gives a false sense of security. Only add an adaptation layer when the corresponding tool is actually used in the team, and test that it picks it up (for example by asking the agent to quote the rules it has loaded).

An AGENTS.md skeleton

Here is a deliberately short starting point. The idea is to point to the scripts and the documentation rather than repeat everything.

# Instructions for agents

## Context
Application X. Architecture: see docs/architecture/overview.md.
Key decisions: see docs/decisions/.

## Commands
- Install: scripts/setup.sh
- Tests: scripts/test.sh (run before any merge request)
- Lint and types: scripts/lint.sh

## Working rules
- One task, one branch. No changes outside the requested scope.
- Propose a plan before modifying more than three files.
- Do not reformat files that are not concerned.
- Every notable architecture decision gets an ADR in docs/decisions/.

## Prohibitions
- Never read, display or write secrets (.env files, keys, tokens).
- Never run a deployment, data migration or deletion without human approval.

This file expresses declarative rules. For the ones that matter (secrets, deployment), back them with a technical mechanism: tool permissions, an account without rights, blocking CI.

An eight-step work cycle

1Understand thecontext2Define the scope3Draw up a plan4Modify the code5Run the checks6Review the diff7Get approval8Document thedecisionsA documented decisionfeeds the next turn
The eight-step work cycle. It loops: a decision documented at step 8 feeds the context of the next step 1.
  1. Understand the context. The agent (or the developer) reads the README, the architecture and the relevant decisions, and summarizes its understanding. A misunderstanding is corrected at this stage, not in the diff.
  2. Define the scope. What is requested, what is out of scope, the acceptance criteria.
  3. Draw up a plan. The files concerned, the steps, the risks, the tests to add. The plan is approved before any code is written.
  4. Modify the code. In small steps, on a dedicated branch, running the tests as you go.
  5. Run the checks. Tests, lint, types, secret detection, through the project's scripts. A failure is read, not bypassed.
  6. Review the diff. Careful reading of everything that changed, including what was not requested. Out-of-scope changes are removed.
  7. Get approval. Human code review, with an explanation of what was done and what was not verified.
  8. Document the useful decisions. An ADR if a structuring choice was made, a documentation update if a behavior changed, a handover note if the work continues.

8. Harness maturity checklist

Tick what is true today in your project, not what is planned. Each section has the same weight: a weakness in security is not offset by good tests.

Context and documentation

  • A README makes it possible to install and test the project without outside help.
  • The architecture is documented and dated, with an identified owner.
  • Key decisions are recorded (ADRs).
  • The agent instruction file is short and points to the documentation, with no log or progress report.
  • Each important piece of information exists in only one place.
  • AI-generated documentation is identified and reviewed by a human before being considered reliable.

Quality and collaboration

  • A single command runs the tests, another runs lint and type checks.
  • CI runs these checks and blocks the merge on failure.
  • Agents work on dedicated branches, never on the main branch.
  • Every change goes through human code review.
  • Out-of-scope changes are spotted and removed at review.
  • A long task leaves a handover note outside the conversation.

Security

  • No secrets in repositories, prompts or instruction files, with automatic detection.
  • Agents have access neither to production secrets nor to the corresponding environment files.
  • Agent permissions are minimal and versioned.
  • Irreversible operations (deployment, deletion, sending) require human approval enforced technically.
  • The list of allowed MCP servers and extensions is known and reviewed.
  • Critical rules rely on an infrastructure guarantee, not only on an instruction.
  • The terms under which external tools process data are validated for confidential code.

Portability and longevity

  • The project documentation does not depend on any proprietary format.
  • Per-tool adaptations are small, documented and listed.
  • Instructions and configurations are versioned with the code.
  • A set of reference tasks makes it possible to compare model or tool versions.
  • A tool update is tested before being rolled out.
  • A fallback procedure exists, including for working without an assistant.

Reading the result

As a rough guide (Opinion, this grid is in no way normative): below half of the boxes ticked, the harness rests mostly on people's goodwill. Between half and three quarters, it is usable but fragile in places: start with the Security section. Beyond that, the challenge becomes upkeep: updating, measuring, simplifying.

Conclusion

The choice of model matters, but it changes every few months. What lasts is the working system built around it: a clear, single context, rules that tools enforce, tests that make verification possible, guardrails based on infrastructure rather than trust, and an organization that is not locked into a vendor. A good harness benefits humans and agents alike, and it keeps its value the day you change assistants.

References and status of the information

The official documentation below was consulted in October 2026. Its content changes: check the version of the tool you use.

The information on Roo Code, on the list of tools compatible with AGENTS.md and on Codex configuration precedence comes partly from secondary sources and is flagged as such in the text. The recommendations marked Opinion are personal.