AI Coding Agents: The Five Core Mechanisms Behind the Agent Harness
This article breaks down the five core mechanisms that shape the behavior of AI coding agents: context management, memory and rules files, event hooks, skills, and subagent delegation. It explains what each mechanism controls, where its boundaries are, how to use it in engineering workflows, and what to monitor when optimizing agent-driven development.
1. Rethinking the Agent Harness: Mechanisms Set the Capability Ceiling
When people evaluate AI coding tools, they often focus on the reasoning ability of the underlying model. In real engineering settings, however, delivery quality is often determined by the “runtime framework” wrapped around the model, commonly known as the agent harness. It manages context, loads rules, schedules tools, blocks dangerous actions, and splits tasks for parallel execution.
The same model can show very different stability under different harnesses. The reason is that the model’s context budget is a limited and decaying resource, while the harness must keep the most relevant information loaded at each moment.
This article identifies five components that determine the effectiveness of this mechanism and explains, one by one, what problem each solves, where its limits are, and how to use it well in engineering:
| Mechanism | Core Problem It Solves | Typical Symptoms When It Fails |
|---|---|---|
| Context management | Deciding what information to keep within a limited window | The model “forgets” earlier agreements during long conversations |
| Memory and rules files | Stable constraints across sessions and compression | You have to repeat the same conventions every time |
| Event hooks | Moving deterministic requirements from a probabilistic model to a program | Code is committed or run without formatting, checks, or safeguards |
| Skills | On-demand injection of domain knowledge | Prompts grow endlessly, and tasks drift out of scope |
| Subagent delegation | Context isolation and parallel fan-out | The main context is filled with search logs and intermediate output |
2. Mechanism 1: What Actually Fills the Context Window
A common misconception is that the context is simply “what I asked and what the model answered.” Conversation history is only one part. A complete window is usually consumed by several types of content:
- System instructions: the framework’s runtime rules, behavior constraints, and tool definitions. The more tools there are and the longer their descriptions are, the larger this portion becomes. It is usually not compressible.
- Conversation history: the original text of multiple interaction turns, including the user’s wording and the model’s reasoning and conclusions.
- File contents: source code, configuration files, and test files that have been read or edited.
- Command and tool output: build logs, test results, search results, and error stacks.
- Automatic memory: project facts and user preferences retained across sessions.
- Loaded skill content: full instruction text injected after a skill is triggered.
- Environment metadata: working directory structure, version control status, runtime information, and platform details.
Items 3 and 4 are the easiest to get out of control: reading a large file in full or pasting tens of thousands of log lines can consume most of the window in one step.
2.1 Two-Stage Handling After the Window Fills Up
Most mainstream implementations use a two-stage strategy: “demote first, then compress.” The first step prioritizes removing earlier tool outputs that are large but low in timeliness, such as early file snapshots and command echoes. Their value is usually already absorbed by later conclusions. The second step summarizes and compresses the entire conversation history, turning specific wording, numeric ranges, and code snippets into concise descriptions.
2.2 Why Models “Forget” Your Requirements
Compression is lossy. A naming convention you emphasized in turn three or an architecture decision you made in turn five may be merged into a single sentence like “the user prefers clean code” after summarization.
This is the real cause of instruction drift in long conversations: the model is not disobeying; the constraints have lost their original precision during compression.
This leads to four practical guidelines:
- Move important constraints into memory files, because memory files are reinjected every turn, including after compression, and are not affected by summarization.
- Actively control read granularity: have the agent read by symbol or line range rather than loading an entire file.
- Reference paths instead of pasting content: say “follow the existing style in
service/user.ts” rather than pasting the file into the conversation. - Externalize search results: store large materials in files and let the agent read them back on demand instead of loading everything into the window at once.
3. Mechanism 2: Project Memory and Rules Files
Rules files are essentially prompts that are forcibly replayed every turn. They usually support layered loading, with layers taking effect cumulatively:
# User-level (general preferences across projects, illustrative)~/.agent/rules.md# Project-level (shared by the team and committed to the repository)./agent-rules.md# Subdirectory-level (applied locally, useful for monorepos with multiple tech stacks)./packages/web/agent-rules.md
A high-quality rules file should meet three criteria: executable, verifiable, and short.
- Executable means writing concrete practices rather than slogans.
- Verifiable means that each rule can be checked by a command.
- Short means you must tolerate the cost of injecting it completely into every turn.
# Project Rules (illustrative)## Tech Stack and Conventions- Use TypeScript 5.x with ESM module style. Do not use CommonJS `require`.- Use only the existing store module for state management. Do not introduce a new state library.- Every new export must add a corresponding type declaration in `src/types/index.ts`.## Verification Requirements- Run `pnpm lint && pnpm test` after every change.- New behavior must be accompanied by unit tests, with coverage no lower than the existing baseline.## Prohibitions- Do not modify automatically generated code under `generated/`.- Do not introduce runtime dependencies that require external network access.- Do not commit credential files. Secrets must be injected through environment variables.## Compression-Preservation Directive (illustrative)When the context is compressed, this section must be preserved verbatim, along with every item under “Prohibitions.”
The final “Compression-Preservation Directive” is a practical technique: explicitly declaring which information cannot be lost during summarization can significantly reduce rule decay in long tasks.
A common anti-pattern is to write a rules file like a requirements document or long-form prose, or to repeatedly explain general best practices that the model already knows. Such content not only consumes context budget but also dilutes the truly critical hard constraints.
4. Mechanism 3: Event Hooks — Moving Determinism from the Model to the Program
Large language models are inherently probabilistic systems, but engineering has many requirements that must be deterministic: formatting before commit, type checking before execution, blocking writes to sensitive paths, and intercepting dangerous commands. These requirements should not rely on “reminding the model to be careful”; they should be enforced by event hooks.
Hooks trigger external commands at key lifecycle points, and their output can determine subsequent behavior. Typical points include: session start, before the user submits a message, before a tool is invoked, after a tool is invoked, session end, and stop.
For example, a “pre-tool-use” hook can return decisions such as allow, deny, modify input arguments, or append context. It can pass semantics through exit codes and structured output. For example, a non-zero exit indicates blocking, and specific output means injecting information into the context.
{"hooks": {"PreToolUse": [{"matcher": "Write|Edit","command": "node scripts/guard-paths.mjs"},{"matcher": "Bash","command": "node scripts/guard-commands.mjs"}],"PostToolUse": [{"matcher": "Write|Edit","command": "pnpm format-staged"}]}}
A minimal path guard script looks like this:
#!/usr/bin/env node// scripts/guard-paths.mjs: block writes to protected pathsconst PROTECTED = [/^\.github\/workflows\//, /^generated\//, /\.env$/];const input = JSON.parse(await readStdin());const target = input?.tool_input?.file_path ?? "";if (PROTECTED.some((re) => re.test(target))) {console.log(JSON.stringify({decision: "block",reason: `Blocked write to protected path: ${target}`,}));process.exit(0);}
When designing hooks, follow three principles:
- Single responsibility: one script should check one thing, making troubleshooting easier.
- Fast return: hooks sit on the interactive critical path, and slow scripts directly degrade responsiveness.
- Deny suspicious operations by default: unknown high-risk commands should require human confirmation rather than being silently allowed.
There is also an important security boundary: hooks execute arbitrary scripts with the developer’s own permissions, so hook configuration itself is a high-value attack surface. Teams should include the hook directory in code review and prohibit copying hook scripts directly from untrusted sources.
5. Mechanism 4: Skills and Progressive Disclosure
When a project accumulates stable domain workflows, such as “the complete steps for adding a CRUD endpoint” or “generating migration scripts according to team standards,” writing these workflows into prompts repeatedly consumes context.
The idea behind skills is to package this kind of knowledge into capability units that can be loaded on demand. The core principle is progressive disclosure:
- First level: only the skill name and trigger description remain in context, costing only a few dozen tokens.
- Second level: when a task matches the skill, load the full skill body, including complete steps, constraints, and examples.
- Third level: scripts, templates, and reference documents cited by the skill body are read only when truly needed.
Example directory structure:
skills/api-endpoint/SKILL.md # Trigger description + execution stepstemplates/route.mdscripts/gen-test.mjsdb-migration/SKILL.mdreferences/policy.md
---name: api-endpointdescription: Use this skill when the user asks to add or modify an HTTP endpoint or add endpoint tests.---## Applicable ScenariosAdding or modifying REST endpoints, or adding unit tests and type declarations for them.## Execution Steps1. Define request and response types in `src/types/index.ts`.2. Add a handler in `src/routes/`, reusing existing validation middleware.3. Add tests in `tests/` covering success cases, boundary cases, and authentication failures.4. Run `pnpm lint && pnpm test` and include the output.## Completion CriteriaNo lint warnings, all tests pass, and no new third-party dependencies.
The division between skills and rules files is clear: rules files are permanent hard constraints, while skills are operation manuals loaded on demand.
Putting “must use pnpm” or “must write tests” into a skill is wrong because these must apply every time. Putting an entire endpoint development workflow into a rules file is also wrong because it is only relevant to some tasks; keeping it permanently loaded merely wastes budget.
When writing a skill, the most important part is the description. It determines whether the skill can be triggered correctly. The description should explain “under what conditions to use it,” not “what this skill is.” It is also important to keep a single responsibility and avoid creating a “universal skill” that contains everything.
6. Mechanism 5: Subagent Delegation and Context Isolation
The value of subagents is not “division of labor” but context isolation.
A codebase-wide search may produce tens of thousands of characters of raw results, but only a few lines contain useful conclusions. If the main agent performs the search, the intermediate process permanently occupies the main window. If the task is delegated to a subagent, the subagent uses its own window to digest the large amount of intermediate information and returns only the conclusions.
Typical scenarios suitable for delegation include:
- Broad search fan-out: when you need to confirm in multiple directories where a function is called, multiple read-only subagents can run concurrently.
- Specialist review: security and performance reviews require many details, but the main agent only needs to receive a list of issues.
- Independent verification: a subagent that did not participate in the implementation can run tests and acceptance checks, reducing self-confirmation bias.
The quality of the delegation protocol directly determines success. In practice, follow these rules:
- Make the task self-contained: the subagent cannot see the main conversation, so the task description must include the objective, scope, constraints, and output format.
- Ask for summaries, not the full process: explicitly require “conclusions + key file paths + evidence,” and prohibit returning raw logs.
- Restrict permissions: read-only permissions should be given for search tasks to avoid side effects.
- Control fan-out size: too much concurrency can cause context contention and rate limiting; usually a few parallel tasks are enough.
Task: Confirm all references to the legacyAuth module in the projectScope: only src/ and tests/; ignore node_modules and generated/Constraints: read-only; do not modify any filesReturn format:- file path:line number -- reference type (import / dynamic loading / string concatenation)- risks: whether auth-related calls lack unified error handling
A common anti-pattern is to throw a vague task at a subagent, such as “optimize this code,” while also requiring it to return all change details. The former lacks acceptance criteria, and the latter directly pollutes the main context, making the isolation pointless.
7. How the Five Mechanisms Work Together
Using a real requirement as an example, the approximate sequence in which these mechanisms are involved is as follows:
- Session start: the framework injects system instructions and layered rules files; hooks at the session-start point check repository status and dependency readiness.
- Requirement clarification: the main agent judges task complexity. Simple tasks are executed directly; complex tasks are decomposed first to avoid filling the window with a large task all at once.
- Information collection: read-only subagents are delegated to search call chains and related tests in parallel; the main window only receives summary conclusions.
- Plan generation: if a domain workflow matches, load the corresponding skill and implement according to its steps, while following the hard constraints in the rules file.
- Execution and interception: edit actions trigger pre-write hooks to validate paths and sensitive information, and post-edit hooks automatically format the changes.
- Acceptance: run type checks and tests; an independent subagent reviews the result and outputs an issue list.
- Wrap-up: the session-end hook outputs a change summary, making it easier to archive logs into a log service and monitoring/alerting system.
8. Measuring Effectiveness and Tuning Guidance
Whether this mechanism works should be judged by observable metrics rather than intuition:
- Context utilization: the trend of window usage per turn. If it keeps rising steadily, read granularity or resident skill content needs to be simplified.
- Compression frequency: frequent compression often indicates that task splitting is too coarse.
- Rule violation rate: hook interception counts by type can help determine whether the wording of the rules file is clear enough.
- Rework rate: the proportion of tasks that require multiple correction rounds. This is a core indicator for evaluating the quality of task descriptions and acceptance criteria.
- Cost per task: token consumption and elapsed time, used to evaluate whether delegation and skill loading bring a net benefit.
The recommended optimization order is to start with “reducing unnecessary injections”: first simplify rules files and tool descriptions, then control read granularity, then introduce hooks to enforce deterministic checks, and only then consider adding skills and subagents. Reversing this order easily produces a complex configuration with limited benefit.
For engineering implementation, hook execution logs, agent session traces, and change records should be collected uniformly into logging and monitoring systems. Sensitive credentials should be injected through secret management or environment variables, never written into rules files or skill directories. These files are usually distributed with the repository, and once secrets are mixed into them, they are effectively publicly exposed.
Teams that already run development workflows on a cloud platform can often reuse existing platform capabilities, such as containers, object storage, logging, monitoring, and alerting, to close this observability loop instead of building new infrastructure from scratch.
9. Common Pitfalls Quick Reference
| Pitfall | Consequence | Correct Approach |
|---|---|---|
| Writing hard constraints only in the conversation | They are lost after compression | Put them in the project rules file |
| Pasting an entire large file at once | The window is quickly exhausted | Reference by symbol or line range |
| Using prompt reminders to stop the model from dangerous operations | It fails probabilistically | Enforce blocking with pre-write hooks |
| Putting all workflows into the rules file | Permanent context cost grows | Split them into on-demand skills |
| Asking subagents to return the full process | Isolation fails and the window is polluted | Define a conclusion-based return format |
| Writing the rules file as a requirements document | Key constraints are diluted | Keep only executable and verifiable items |
10. Conclusion
The capability boundary of AI coding tools is largely determined not by the model alone, but by the coordination precision of five layers: context management, layered memory, deterministic hooks, on-demand skills, and isolated delegation.
Understanding their operational logic is essentially doing one thing: continuously supplying the most relevant, precise, and trustworthy information within a limited context budget, and assigning all deterministic engineering requirements to programs rather than probabilistic models.
Mastering this point has more long-term value than memorizing any specific command.
