Skip to main content

Command Palette

Search for a command to run...

Context Engineering for Coding Agents: What Anthropic and OpenAI's Guidance Actually Implies

Most "AI coding tips" content is recycled opinion with no engineering substance. This piece works from primary sources only: Anthropic's published best practices for Claude Code, and OpenAI's published best practices for Codex. It reframes their guidance the way an engineer would read an incident postmortem. Root cause first, then the mitigations that actually generalize.

Updated
•10 min read•View as Markdown
Context Engineering for Coding Agents: What Anthropic and OpenAI's Guidance Actually Implies
A
Software Engineer passionate about backend engineering, distributed systems, and AI infrastructure. Writing about building scalable, production-ready systems.

Root cause: context is a finite, decaying resource

Strip the vendor-specific vocabulary and both companies are describing the same failure mode you'd recognize from any stateful system: a bounded resource that degrades under load and needs an explicit eviction policy. Anthropic states this directly. Claude's context window fills up fast, and performance degrades as it fills. They treat this as a first class engineering constraint, not a footnote.

OpenAI reaches the same conclusion from the supply side rather than the degradation side. Codex's guidance centers on front loading durable, well scoped context: start with the right task context, use AGENTS.md for durable guidance, configure Codex to match your workflow, connect external systems with MCP, and turn repeated work into skills. Different entry point, same underlying model. Output quality is bounded by what's in context, and context is scarce and depreciating across a session, not a static asset.

If you've debugged a service where cache staleness silently degraded correctness instead of throwing an error, this should feel familiar. The failure isn't loud. It's a slow drift in output quality that looks like a model problem until you check what's actually in the window.

Proven method 1: treat context pollution like cache invalidation

Anthropic documents a specific antipattern worth naming precisely: the kitchen sink session. Start one task, ask something unrelated mid session, return to the original task, and now the context carries irrelevant history competing with the actual task for the model's attention. The fix isn't smarter prompting to make the model ignore stale content. It's structural: clear the session between unrelated tasks, the same way you'd invalidate a cache key rather than trust the consumer to filter stale reads.

Rule of thumb that generalizes: if a correction doesn't land within two attempts, the problem isn't the phrasing of the correction. The context itself has become corrupted state. At that point, the documented move is to stop patching, reset the session, and write a single better initial prompt that incorporates everything learned from the failed attempts. This is the agent session equivalent of refusing to hotfix around a bad cache entry. You flush it and repopulate from source.

Proven method 2: structural separation of generation and verification

Both vendors converge on a principle that maps directly onto independent code review and independent test authorship: the component that produces output should never be the sole authority on whether that output is correct.

Anthropic implements this as a writer/reviewer split across separate sessions. One instance writes code, a fresh instance with zero prior exposure reviews it, because a model reviewing its own recent output is measurably biased toward accepting it. The same split applies to tests: one instance writes tests, a separate instance implements against them. This mirrors how you'd want an engineer who didn't write the endpoint writing the negative test cases for it. They don't share the same blind spots.

There's a sharp, easily missed caveat here, and it matters if you've ever built or evaluated an automated review pipeline: a reviewer explicitly instructed to find gaps will report some even when the work is sound, because finding gaps is the objective it was given. Left unconstrained this produces classic over engineering symptoms: speculative abstraction layers, defensive branches for states that can't occur, tests for impossible inputs. The documented mitigation is narrow scoping of the reviewer's mandate. Flag only findings that affect correctness or explicitly stated requirements; treat everything else as optional, not blocking. Same discipline you'd apply to a static analysis tool with too many enabled lint rules. Unscoped strictness produces noise, not signal.

OpenAI's Codex guidance reaches the same conclusion from the verification side. It states plainly that output quality improves when the agent can verify its own work, and recommends putting reproduction steps, validation criteria, and lint/precommit checks directly in the prompt instead of leaving verification implicit. Functionally this is the same requirement as making tests part of the contract rather than an afterthought. Verification that isn't explicit doesn't happen reliably.

Proven method 3: durable context belongs in a file, not in the prompt

OpenAI's structural discipline is more prescriptive at the single prompt level. Codex's documented format for any nontrivial prompt has four required fields: goal, relevant context (files, folders, docs, or errors), constraints, and completion criteria. That's not a casual request. It's close to a formal spec, and it maps directly onto how you'd write a well scoped engineering ticket rather than a Slack message.

For anything that needs to persist across sessions, OpenAI's AGENTS.md plays the same role as Anthropic's CLAUDE.md: an always loaded README for the agent. The distinction OpenAI draws between AGENTS.md and skills is worth internalizing because it prevents a real category error people make in practice. AGENTS.md holds always on rules that apply to everything the agent touches in a repo (which test command to run, which paths are off limits, commit conventions), while skills are reusable workflows invoked for specific situations, not loaded by default into every session. Conflating the two produces exactly the context bloat this whole approach is trying to eliminate. Durable, structural information belongs in the persistent file. Task specific detail belongs in the prompt.

Where the philosophies actually diverge: loop tightness and blast radius

Anthropic's approach assumes a human in a tight loop: actively steering, clearing context, reviewing diffs as they land. Their documentation states explicitly that active collaboration outperforms full autopilot even when the agent occasionally nails a task unattended on the first try.

OpenAI is more comfortable pushing toward autonomy once durable context exists. Their subagent model spawns multiple narrow, specialized agents in parallel for exploration, review, and implementation, each with a constrained tool surface and its own model configuration, results collected in a single pass. The design principle is explicit: the best custom agents are narrow and opinionated, with a tool surface matched to one clear job and instructions that prevent drift into adjacent work. This is least privilege applied to agent design instead of access control. Scope the capability to the job, not to what the agent is theoretically capable of doing.

Neither vendor treats full autonomy as safe by default, and this matters if you've done any adversarial testing of LLM backed systems. OpenAI's own Codex introduction states that manual review of all agent generated code remains essential before integration and execution. Anthropic's newer engineering writing on agent containment frames the real question as blast radius. As agents get more capable, the operative concern isn't whether the agent will occasionally act incorrectly, it's how much damage a single bad action can do before a human sees it. That's the same threat model you'd apply to any system executing model generated actions against production infrastructure: assume the boundary will eventually be crossed, and design the containment so a crossed boundary is cheap, not catastrophic.

This isn't theoretical. Doing independent security research against LLM backed tooling, I've repeatedly found the same class of failure across otherwise unrelated products: the trust boundary between system level instructions and user supplied input doesn't hold under adversarial pressure. The instances map cleanly onto the OWASP Top 10 for LLM Applications, and in every case the root cause traces back to the same architectural gap.

  • Prompt injection (LLM01): adversarial input structured to override or extend the system prompt's authority, causing the model to execute instructions it should have treated as untrusted data.

  • Sensitive information disclosure (LLM02): system prompt and configuration leakage, where crafted input gets the model to reproduce instructions it was explicitly told to keep confidential.

  • Insecure output handling (LLM05): model output consumed downstream (rendered, executed, or piped into another system call) without the same validation you'd apply to any other untrusted input.

  • Excessive agency (LLM08): agents granted tool access broader than the task requires, so a successful injection has a blast radius well past the original prompt.

Several of these I identified and responsibly disclosed against production systems, with root cause, working reproduction, and remediation steps the maintainers confirmed as immediately actionable.

The pattern generalizes across all of them. LLMs have no hard architectural separation between instructions and data the way a parameterized query separates code from user input. Everything is tokens in the same context window, and what the model treats as authoritative is learned, not enforced. Context boundary trust is a property you test for adversarially, not one you get by construction. A system prompt that says never reveal these instructions is a policy, not a guarantee, in the same way a client side input check is a UX nicety and not a security control. Prompt level instructions and output filters function as guardrails, not as a security boundary. Guardrails shape LLM behaviour under normal conditions; they don't hold under adversarial input, because the model has no reliable way to distinguish an instruction from data crafted to look like one. If your threat model for an agentic system stops at "the model was told not to," you don't have a threat model.

This changes what blast radius means for coding agents specifically. It's not only about what a misbehaving agent can do to your filesystem or production database, which is where most public containment guidance focuses. It's also about what an agent operating over untrusted input, a pasted error log, a fetched web page, a third party MCP tool's output, can be manipulated into doing or disclosing before a human ever reviews the diff. Sandboxing the agent's write access is necessary but not sufficient if the read path is equally exploitable. Run adversarial input structuring against your own context boundary before someone else does it for you, the same way you'd fuzz a parser before shipping it. The failure isn't hypothetical. It's a question of when the boundary gets tested and what's on the other side of it when it does.

Summary: four things to actually implement

  1. Budget context like a scarce resource. Stale or irrelevant context isn't neutral, it actively degrades output quality, the same way a stale cache entry degrades correctness instead of failing loudly. Clear sessions between unrelated tasks. Don't try to prompt your way around pollution.

  2. Write the persistent instruction file before the first serious prompt, not after the agent repeats the same mistake a third time. Keep it to durable, structural information. Task specific detail stays in the prompt.

  3. Separate generation from verification structurally. Second session, subagent with read only access, or a deterministic test suite the agent must actually pass. Pick one, but don't let a single pass self certify. If you're using an automated reviewer, scope its mandate narrowly or it will manufacture findings to justify its own existence.

  4. Scope autonomy to the cost of failure, not to how well the agent has performed so far. Both vendors caveat their most autonomous workflows with mandatory human review before anything ships. That's not boilerplate, it's least privilege applied to agentic systems: grant capability incrementally, keep review as the default, and don't extend trust past the point where you understand the failure mode.