AI Coding Agents: Breaking Down the Five Core Mechanisms of the Agent Harness
This article explains why the same model can perform an order of magnitude differently depending on which tool wraps it, and argues that the difference comes from the Agent Harness rather than the model itself. It then breaks down the mechanisms teams most often get wrong: what actually occupies the context window, why long conversations lose instructions, how project-level rule files and a "compaction contract" protect persistent constraints, how hooks turn engineering standards into hard gates, how Skills load full workflows only when triggered, and how Subagents isolate exploration from the main context. It closes with a full task lifecycle, an implementation checklist, common pitfalls, suggested metrics, and enterprise concerns around permissions, observability, and governance.
1. Fix the Mental Model First: The “Shell” Decides the Experience
Many people think of an AI coding assistant as “a model that writes code.” That works well enough for individual trials. The gap appears as soon as the assistant meets a real repository, real engineering standards, and a real CI pipeline: the same model can differ by an order of magnitude in task success rate depending on which tool wraps it.
The reason is that the model is only the reasoning core. What actually determines the experience is the engineering structure around it, commonly called the Agent Harness. At a minimum, it is responsible for five things:
- Context orchestration: deciding what goes into each request, what stays out, and in what order.
- Tool and permission definitions: what can be read, what can be written, and which operations must be blocked.
- Execution loop: either a ReAct-style “observe–reason–act” cycle, or a Plan-and-Execute “plan first, then execute step by step” flow. The two are often mixed.
- Memory and rules: keeping behavior consistent across turns and across sessions.
- Subtask delegation: handing large tasks to isolated subagents to protect the main context budget.
The rest of this article walks through the mechanisms that are easiest to get wrong: the context window, project-level rule files, context compaction, execution hooks (Hooks), skill packages (Skills), and subagents (Subagents).
2. The Context Window: What Is Actually Inside It
A common misconception is that “the context is just what I’ve said to the assistant.” In reality, conversation history is only one of seven categories of content:
| Category | Content | Typical size | Freshness |
|---|---|---|---|
| Conversation history | Back-and-forth between the user and the model | Medium | High |
| File contents | Source code that has been read or edited | Large | Medium |
| Command output | Results of running tests, builds, and logs | Very large | Low |
| Project-level rules | Persistent constraints injected through convention files | Small | Very high |
| Automatic memory | Preferences and facts accumulated across sessions | Small | High |
| Loaded skill instructions | Full workflow text injected after a skill is triggered | Medium | Task-dependent |
| System instructions and tool definitions | The shell’s own runtime rules and tool schemas | Fixed | Very high |
Understanding this table pays off in two ways.
First, it explains “why it suddenly got dumber.” The full output of a single npm test run, or the results of a repository-wide grep, can outweigh dozens of turns of conversation combined. Once the context budget is eaten by this low-value content, the constraints that actually matter get diluted.
Second, it lets you actively optimize context efficiency. Common engineering practices include reading only the necessary slices instead of whole files, redirecting long command output to a file and letting the model search it in a targeted way, and keeping the context prefix stable so prompt caching can do its job (cached portions cost significantly less than new content). The last point matters especially: if your rule file changes on every turn and always inserts a timestamp, you are voluntarily giving up the caching benefit.
3. Context Compaction and the Real Cause of “Forgetting”
Context cannot grow indefinitely, so every mainstream implementation compacts it, usually in two steps.
Step one: drop low-freshness, high-volume content. Older tool-call outputs, file-read results, and command outputs are removed first. This step is essentially lossless, because the model can simply read a file again if it needs to.
Step two: summarize the conversation history. Exact wording, numbers, and code snippets are condensed into summaries. This step is lossy: in turn 3 you repeatedly stress “this project forbids runtime dependencies,” and by turn 8 it may already read “the user prefers to keep the code simple.” An architecture decision discussed in turn 5 may survive compaction only as a vague “several options were discussed.”
That is why instruction adherence decays in long conversations. It is not that the model stops listening; the instruction was lost during one of the compaction passes.
Countermeasure 1: Put Persistent Constraints in Project-Level Rule Files
Anything that needs to hold across turns and across sessions should not live in the conversation. Different tools name these files differently, but the semantics are the same: the file is injected when a session starts, and it is re-injected after every compaction, so summaries never touch it. This article uses AI-GUIDE.md as a placeholder name.
A layered suggestion:
- User level: personal preferences such as answer language and comment style.
- Project level: engineering conventions such as the tech stack, directory responsibilities, and prohibitions.
- Subdirectory level: module-specific constraints such as a module’s legacy baggage and compatibility requirements.
Write in an imperative, verifiable style rather than a lyrical one:
# Project Conventions## Technical constraints- No new third-party runtime dependencies; tool-chain dependencies must be justified in the PR description- Every exported function must carry type annotations- Never build SQL directly in the business layer; always go through the data access layer## Verification requirements- After any change, run `make lint && make test`; do not commit if either fails- Any change that touches an interface must also update `docs/api.md`## Must survive compaction (compaction contract)- Confirmed target architecture decisions, plus rejected alternatives and the reasons for rejecting them- The list of signature and field changes to the public API- Currently failing test cases that are still unfixed, with their verbatim error output- Writing patterns explicitly forbidden this round
Note the last section, the “compaction contract.” It is the most underrated technique here: it explicitly tells the shell which items must never be summarized away, effectively adding a whitelist on top of a lossy process.
Countermeasure 2: Compact Proactively and Set a Focus
Most tools offer a slash command that triggers compaction manually and lets you specify what to keep. When costs start to climb, do not passively wait near the threshold; converge on purpose and keep only what relates to the current sub-goal. A practical rule is to compact per sub-task: right after finishing the “interface definition,” compact once with the focus set to interface signatures and field constraints, then move on to “implementation.”
4. Hooks: Turning Engineering Standards from “Requests” into “Constraints”
A rule file is essentially “asking the model to do this,” and the model can choose not to understand it or not to comply. Hooks insert your own code at fixed points in the execution chain, acting as hard gates. Common event points:
- Before a tool call: validate parameters, block dangerous commands, inject prerequisite notes.
- After a tool call: format output, append error hints, write audit logs.
- Session start/end: load the environment, clean up temporary resources.
- After a rule file changes: validate the format, notify the team.
- After compaction: re-inject key constraints, forming a second layer of protection together with the “compaction contract.”
Hooks have two typical return semantics: block (exit with a non-zero code and feed stderr back to the model as the reason) and inject context (append structured content to the current turn’s context).
{"on": "before_tool_use","match": { "tool": "run_command" },"run": ".ai-guide/hooks/guard-irreversible.sh","deny_on_nonzero_exit": true,"feed_stderr_to_model": true}
#!/usr/bin/env bashset -euo pipefailpayload=$(cat)cmd=$(printf '%s' "$payload" | jq -r '.tool_input.command // empty')for pattern in 'rm -rf /' 'git push --force' 'DROP TABLE' 'kubectl delete'; doif [[ "$cmd" == *"$pattern"* ]]; thenecho "Detected an irreversible operation (${pattern}); blocked. Rewrite it as a reversible step, or explain why human confirmation is required before running it." >&2exit 2fidoneexit 0
Hooks that run after a tool call are a better fit for “correcting and re-injecting feedback”:
#!/usr/bin/env bash# When tests fail, re-inject a structured summary so the model does not have to guessjq -nc --arg ctx "Unit tests failed: 3 cases did not pass. Fix the failing cases first before moving to the next step." \'{additionalContext: $ctx}'
In practice, the three most valuable categories of hooks are:
- Dangerous-operation gates: writes to production, data deletion, force-pushing branches.
- Pre-commit quality gates: formatting, static checks, and type checks. If they fail, the session is not allowed to finish.
- Audit and telemetry: who changed what and when, recorded in a shared log.
The first two guarantee a behavior floor. The third guarantees traceability when something goes wrong, and in enterprise environments that often matters more than the feature itself.
5. Skills: Capability Packages Loaded on Demand
Rule files are “always in effect”; skill packages are “conditionally triggered.” Their core mechanism is progressive disclosure: only a skill’s name and trigger description stay in context, and its body is loaded only after the skill is triggered. That lets you build up dozens or even hundreds of skills without noticeably raising the fixed cost of every request.
The standard structure is a “thin entry point plus a thick body”:
.ai-guide/skills/├── api-migration/│ ├── SKILL.md # name + trigger description + a workflow skeleton of 10 lines or fewer (always resident)│ ├── steps.md # detailed steps and edge cases (loaded only after a trigger)│ ├── checklist.md # pre-release checklist│ └── templates/ # migration script templates└── perf-profiling/└── SKILL.md
The header of SKILL.md decides whether the skill ever fires, so state clearly “when to use me”:
---name: api-migrationdescription: Use when adding fields to a public interface, changing response structures, or handling version compatibility. Covers contract review, dual-write migration, canary rollout, and rollback plans.---1. Locate every call site (including the frontend, SDKs, and downstream services)2. Confirm the compatibility strategy: add an optional field / run two versions in parallel / a breaking change requires review3. Write the migration script and the rollback script4. Check each item against checklist.md5. Produce a change list and a canary rollout plan
A simple way to remember the boundaries between the three: rule files govern the baseline you must hold at all times, skill packages govern the workflow to follow in a specific scenario, and hooks govern what becomes physically impossible when you cross the baseline. Two anti-patterns show up most often when writing skill packages: turning general preferences into skills (those belong in rule files), and writing trigger descriptions that are too abstract (the model cannot tell when to load the skill, so the hit rate is close to zero).
6. Subagents: Trading Context Isolation for Main-Chain Bandwidth
A subagent is essentially an independent context window plus a restricted toolset. An exploration subagent can read 50 files and run 20 searches, but return only a conclusion of a few hundred words to the main agent. As a result, only the “conclusion” enters the main context, never the “process.”
name: code-explorerdescription: Locate implementations and call chains in large repositories; read-only; returns a conclusion summarytools: [read_file, search_code, list_dir] # no write access, no command executionmodel: cost-effective-tierreturns: |Relevant file paths + key function signatures + call relationships + a list of uncertainties, no more than 400 words
Four design points:
- Contract the return value. Require a fixed format (paths, signatures, call relationships, uncertainties). Otherwise the main agent receives free-form text that needs extra turns to digest, which cancels out the benefit of isolation.
- Orchestrate reads and writes separately. Read-only exploration can be fanned out in parallel (architecture research, test location, and dependency investigation can run at the same time). Writes should be serialized so that multiple subagents never modify the same file concurrently.
- Be clear about how delegation relates to planning. Plan-and-Execute is responsible for “thinking it through before acting,” while multi-agent delegation is responsible for “handing the thought-through steps to separate workers.” Producing an explicit step list in a planning phase and then delegating step by step is far more stable than delegating while still thinking.
- Watch out for error amplification. A wrong judgment that a subagent makes on incomplete information enters the main context as an “authoritative conclusion.” The countermeasure is to have subagents explicitly label their confidence and uncertainties, and to have the main agent or a hook validate key conclusions once.
7. Wiring the Five Together Across One Task Lifecycle
Session start├─ Inject system instructions + tool definitions├─ Inject user-level / project-level rule files (including the "compaction contract" section)├─ Register hooks (guards, quality gates, audit)└─ Keep the "name + trigger description" index of always-resident skillsTask issued by the user├─ Plan: break the task into explicit steps (Plan-and-Execute)├─ Skill triggered: load the full workflow and checklist on demand└─ Delegate to subagents: read-only exploration runs in parallel and returns contract-shaped summariesExecution loop (ReAct)├─ Read files / search / edit / run commands├─ before_hook: validate parameters, block irreversible operations├─ after_hook: re-inject failure summaries, run formatting and static checks└─ Size above threshold → compaction is triggered (old tool output is dropped first, then theconversation history is summarized; whitelist entries are kept per the"compaction contract"; after_hook re-injects key constraints)Wrap-up├─ Finish only after every quality gate passes├─ Write audit events to the logging service└─ Consolidate: new conventions go into rule files, new workflows go into skill packages
8. Implementation Checklist and Common Pitfalls
Checklist
- Keep rule files short enough to read on a single screen; write imperatives and verifiable standards, not background or personal reflections.
- Fetch context on a “read only the necessary slices” basis, and put long output in a file for targeted retrieval.
- Keep the context prefix stable so prompt caching can do its work.
- Break long tasks into sub-goals; when each sub-goal is done, compact proactively and set a focus.
- Leave reversible operations open, and force every irreversible operation through hook-based blocking plus human confirmation.
- Any process that repeats three or more steps at high frequency is worth turning into a skill package.
- Delegate large-scale exploration to read-only subagents, and keep writes on the main chain and serialized.
- Put all rules, hooks, and skills under version control and code review; they are code.
Common pitfalls
- Writing key constraints in the conversation and hoping the model remembers them (they belong in rule files).
- Turning a rule file into a thousand-line document (it dilutes attention and breaks the cache at the same time).
- Using hooks for soft constraints that the model could judge on its own (hooks should stay fast, deterministic, and side-effect free).
- Splitting skill packages finer and finer until their trigger descriptions look alike (which leads to false triggers or none at all).
- Caring only about “can it run” and never defining a return format (the main context fills up with process noise).
Metrics: do not optimize by gut feeling. You can track task first-pass rate, average number of compactions, the number of hook blocks and the rework rate after them, per-task context consumption, and the number of lines a human reviewer has to modify. Together, these show whether the problem lies in the context, the rules, or the delegation strategy.
9. Three Additional Notes for Enterprise Adoption
Permissions and security: follow the least-privilege principle and make subagents read-only by default; never let secrets enter the context, and inject them through the runtime environment instead; operations such as writing to production, deleting data, and force-pushing branches must be physically blocked by hooks, not discouraged by prompts.
Observability: emit session traces, compaction events, and hook block records as structured output, and connect them to logging services and monitoring/alerting. Set threshold alerts for “high-frequency blocks,” “frequent compaction,” and “repeated rework.” General-purpose cloud platforms typically offer corresponding forms for these building blocks, such as log services, object storage, monitoring and alerting, and container platforms (Baidu AI Cloud is one example). They can be combined into a complete audit loop without relying on any single tool’s proprietary implementation.
Asset management and governance: treat rule files, skill packages, and hook scripts as team assets. Host them centrally, review them in a unified process, and release them in versions, with a gradual rollout mechanism: trial them in one small team for two weeks, validate the benefit with the metrics above, and then roll them out to the whole team.
10. Summary
These five mechanisms are not independent features; they are different facets of the same context engineering discipline. Rule files counter cross-turn forgetting, the compaction mechanism counters the capacity limit, hooks counter unreliable behavior, skill packages counter workflows that never get consolidated, and subagents counter main-chain congestion. What really separates skilled users of these tools is not which model they switch to, but whether they explicitly design these five layers and keep measuring and iterating on them with verifiable methods.
