The Role of Markdown Files in the Harness

Same file, different channel, different authority: injection timing as a harness design problem

The Problem: Do Not Blindly Dump Markdown 🍅

Every coding agent system eventually accumulates a pile of markdown: project conventions, architecture notes, deployment runbooks, task checklists. The naive integration is tempting because it is one line of code: concatenate everything into the prompt and let the model sort it out. In practice, this is where instruction-following quietly degrades, and it degrades for structural reasons rather than anything to do with model capability.

The first failure mode is instruction competition. A context window is a shared, fixed-size resource, and every injected document bids for the same attention. Outdated notes sit next to current instructions with identical formatting and identical apparent authority; the model gets no channel-level signal about which one wins. When a six-month-old runbook says “always use the staging database” and this turn’s task says otherwise, the conflict is resolved by luck.

The second is displacement. Long documentation competes not just with other instructions but with the most recent tool results, which are exactly the tokens the agent needs to reason over right now. In a long session, with compaction or truncation in play, a 2,000-line style guide can push the last test failure out of effective attention. The net effect is perverse: the agent receives more text and fewer actionable instructions.

The lesson is not “write less markdown.” The lesson is that what a file says matters less than when, and through which channel, it enters the context, and that managing this is a harness responsibility, not a documentation one.

Two Files, Two Contracts: AGENTS.md and SKILL.md 🍅

Coding agent systems have converged on a pattern that splits this markdown into two files with deliberately different loading contracts.

FilePurposeLoading triggerScope
AGENTS.mdWorkspace rules: how the agent should behave inside this specific projectInjected before the start of every turnPersistent across all tasks in the workspace
SKILL.mdTask workflows: step-by-step procedures and tool expectations for one task typeLoaded when the specific task type is triggeredDedicated exclusively to the current workflow

The split is not about content categories. It is about invariance. AGENTS.md holds what must stay true no matter what the agent is doing: build commands, review conventions, lines it must not cross. Because these constraints have to survive arbitrarily long sessions, the harness re-injects the file every turn, refreshing its position instead of letting it sink into the middle of a long history. SKILL.md holds procedures that are only true while a particular task is running: the release checklist matters during a release and is pure noise during a bug fix. Loading it on trigger gives it a recency advantage exactly when it applies, and zero context cost when it doesn’t.

Read as architecture rather than file naming, the split defines two layers:

  • AGENTS.md is the invariant instruction layer: project-level constraints with turn-level refresh, the closest thing to law a harness can express in prose.
  • SKILL.md is the task execution layer: procedural logic loaded on demand and scoped to the lifetime of the workflow that summoned it.

Injection Channel Determines Constraint Strength 🍅

The two-file split is one point in a larger design space. A harness has several ways to place an instruction in the model’s context, and the same sentence binds with very different force depending on which one delivers it. Laying them side by side makes the design logic visible.

Injection methodWhen it enters contextPersistenceConstraint strengthCharacteristic failure mode
Baked into the system promptSession start, fixedEntire sessionStrongestCannot adapt per project; every added rule taxes every task forever
Per-turn re-injection (AGENTS.md)Refreshed before each turnEntire session, no positional decayStrongBloat: each line is paid on every turn, so the file must stay near ~100 lines
On-trigger load (SKILL.md)At task activationDuration of the workflowStrong, locallyTrigger misses: if the task is not recognized, the procedure never loads at all
One-shot dump in the first user messageSession start, onceDecays as history growsMedium, degradingConstraints silently fall out of effective attention (or out of the window) mid-task
Retrieved chunks (RAG-style) mid-conversationOn semantic matchOne turnWeakTreated as reference material to consult, not instructions to obey
Content inside tool results and file readsWhenever a tool returnsOne turnWeakest, by designThe model is trained to distrust data-channel text; this is also the prompt-injection defense boundary

Two regularities fall out of this table.

Constraint strength tracks the trust hierarchy, not the wording. Models are trained on an authority ordering: system instructions outrank harness-injected context, which outranks user messages, which outrank tool-returned data. The ordering exists to defend against adversarial prompt injection (instructions smuggled into a fetched web page, or into a file being read), but the same ordering weakens legitimate instructions placed in a low-authority channel. A convention sitting in a file the agent happens to Read mid-task arrives through the data channel and is correctly discounted; the identical sentence in AGENTS.md arrives through the instruction channel and binds. A harness that dumps markdown indiscriminately is voluntarily downgrading its own rules to the authority of scraped data.

Constraint strength falls as co-injected volume grows. Within a single channel, authority is split among the tokens that share it. A 100-line AGENTS.md where every line is load-bearing constrains harder than a 2,000-line one where the constraints are buried in background prose, because attention is spread across the whole payload before any instruction-following happens. This is why progressive disclosure is more than a token-cost optimization. Exposing lightweight metadata first (a skill’s name and a one-line description) and loading the full content only when it is needed keeps each channel’s payload small enough that what does get injected keeps its force.

The combined design rule: put an instruction in the highest-authority channel whose refresh schedule matches how often the instruction changes. Invariants go where they are re-asserted every turn. Procedures go where they appear exactly when triggered. Reference material stays behind a tool call, where being discounted as data is the correct behavior.

What the Harness Is For 🍅

Loading the right markdown into the context at the right moment is not a workaround or a prompt trick. It is the job the harness layer exists to do. Small files change no model weights, yet they move task performance out of all proportion to their size, because they act on the one variable that actually governs agent behavior at inference time: what occupies the context, at what position, with what authority, at the moment a decision is made. A harness that treats markdown loading as a scheduling and channel-assignment problem gets an agent that follows its rules. A harness that treats it as concatenation gets an agent that has read its rules, once, a long time ago.