Prompt Engineering in Codex CLI: Contracts That Hold

Use AGENTS.md discovery, read-only runs, review mode, and codex exec to make Codex plan, debug, and verify without widening scope.

October 24, 2026
codex-cliprompt-engineeringagents-mdreviewverification

The instruction chain

Codex reads AGENTS.md before doing any work, once per run. Discovery has three layers:

  1. Global — in CODEX_HOME (default ~/.codex), Codex reads AGENTS.override.md if present, otherwise AGENTS.md. Only the first non-empty file at this level is used.
  2. Project — starting at the project root (usually the Git root), Codex walks down to your current working directory. In each directory it checks AGENTS.override.md, then AGENTS.md, then any names in project_doc_fallback_filenames. At most one file per directory.
  3. Merge — files are concatenated root-first, so guidance closer to your working directory appears later and wins.

The combined size is capped by project_doc_max_bytes, 32 KiB by default. When you hit the cap, Codex stops adding files silently. Move service-specific rules into the service directory instead of growing the root file:

# ~/.codex/config.toml
project_doc_fallback_filenames = ["TEAM_GUIDE.md", ".agents.md"]
project_doc_max_bytes = 65536

AGENTS.md is a prompt, not a policy engine. Sandbox and approval settings constrain behavior technically; a line in AGENTS.md does not. Put hard limits in configuration and keep AGENTS.md to the things a reviewer would otherwise repeat: test commands, naming rules, module boundaries, and what "done" means.

Stale instructions:

Codex rebuilds the chain on every run and at the start of each TUI session. If guidance looks stale, restart in the target directory before editing files. The instruction chain is not hot-reloaded.

AGENTS.md that survives review

A useful AGENTS.md reads like the notes a senior engineer gives a new teammate: commands that actually work, boundaries that are not obvious from the tree, and a definition of done. It should not restate general engineering advice, because every token competes with the task.

A structure that holds up across repositories:

# AGENTS.md

## Commands
- Test one file: `npm test -- <path>`
- Lint: `npm run lint`
- Type check: `npm run typecheck`

## Boundaries
- Do not edit files under `generated/`.
- Ask before adding a dependency.
- Keep API response shapes backward compatible.

## Definition of done
- The narrow test fails before the change and passes after it.
- No unrelated formatting changes in the diff.

Three rules keep it from rotting: put service-specific instructions in the service directory, keep the root file under the byte cap, and review AGENTS.md when the test command changes. A stale test command is worse than no command, because it sends every session down a failing path.

Four prompt contracts

The contract is the shape of the request, not a magic phrase. The general shape of delegating to an autonomous agent is covered in agentic prompting; each one below varies it for Codex and pairs it with the mode that makes the result cheap to verify.

Plan — read-only run

Use the documented read-only combination so the agent cannot edit while it reasons:

codex --sandbox read-only --ask-for-approval on-request
Plan a change to the billing webhook. Read the handler, the queue consumer, and the existing tests. Return: the files you would touch, the failure mode you are fixing, the test that proves it, and the risks you cannot verify from the repo. Do not edit anything.

Ask for a plan that names files and tests. A plan that names only concepts cannot be checked, and it will produce a vague diff.

Review — review mode, not a prompt

Asking a general session to "review the diff" mixes review with implementation. Codex has a dedicated mode:

codex review --uncommitted
codex review --base main
codex review --commit <sha>

Choose exactly one target, or pass custom instructions as a prompt. Review reports prioritized findings without modifying your working tree. --title is only valid with --commit. The full workflow is in Codex as reviewer.

Debug — bounded hypothesis loop

Debugging prompts fail when they invite a rewrite. Bound the loop to one hypothesis at a time and force evidence:

codex exec --sandbox read-only --json "Trace why POST /uploads returns 500 for PNG files over 10 MB. The pipeline is multer -> sharp -> S3 upload. Walk the three stages in order and, for each, say whether the 10 MB file reaches it and what the code does with it. Then name the one stage that fails, quote the line, and explain why a JPEG of the same size passes. Propose the smallest fix. Do not edit files."

One run, one hypothesis. If the answer is a tour of the pipeline instead of a named failing stage, pin the stage and run the loop again rather than asking for a fix:

codex exec --sandbox read-only "Assume sharp is the failing stage. Show the resize call, the input size limit it enforces, and the error branch that turns the failure into a 500. Quote each line and its file path."

Read-only mode is what makes this cheap to repeat: the trace cannot change the tree, so a wrong hypothesis costs a run and nothing else. --json turns stdout into a JSON Lines stream of events, including command executions and agent messages. That gives you a machine-readable record of what the agent actually inspected instead of a confident summary — check the named stage against the files the events show it opening.

Decompose — numbered tasks with dependencies

Decomposition is a planning format, not a permission to touch everything at once:

Implement this as four tasks:
1. Add the User model in prisma/schema.prisma.
2. Add POST /users, depends on 1.
3. Add integration tests for validation failures, depends on 2.
4. Update the API reference, depends on 2.
After each task, run the narrowest test that covers it and report the command and result. Stop if a task needs a file outside src/users/.

Two properties make this work: each task has a verification command, and the scope fence is explicit. Without the fence, decomposition becomes a license to refactor.

Bounding scope

Scope control is configuration plus prompt, in that order.

  • Sandbox first. read-only for investigation, workspace-write for a change. danger-full-access belongs in an isolated runner, not on your laptop.
  • Network second. workspace-write keeps network off. If the task needs a package install, enable [sandbox_workspace_write] network_access = true for that run rather than globally.
  • Path third. Name the directory the agent may touch. The workspace is the technical boundary; the prompt narrows it further.
  • Turn fourth. One change per run. A second, unrelated change in the same session is how diffs become unreviewable.

For approval behavior, on-request is the default that still asks before leaving the sandbox. never is appropriate for read-only CI, not for editing sessions. The retired untrusted policy is no longer supported and can prevent the client from starting — remove it rather than working around it.

Forcing verification

Codex will usually tell you what it did. That is not the same as proving it. Three prompts change the output:

  1. Name the check. "Run npm test -- create-user.test.ts and paste the result" beats "make sure it works."
  2. Ask for the failing case first. A test that only covers the happy path does not verify a validation change.
  3. Ask for the command, not the conclusion. The command and its output are auditable; "tests pass" is a claim.

In automation, put the evidence in the stream:

codex exec --json --output-schema ./review.schema.json -o ./review.json "Review the current diff against main. Return findings only."

--output-schema constrains the final response to a JSON Schema and -o writes the last message to a file, so the verdict can gate a pipeline instead of being read by a human.

TODO: capture from real run — paste one codex exec --json event sequence from a verification run, trimmed to turn.started, one item.completed, and turn.completed.

Anti-patterns

  • "Fix the bug" with no failing case. The agent will guess which bug you mean and edit the nearest suspicious code.
  • Review and fix in one prompt. You lose the clean diff that makes review meaningful.
  • Unbounded parallel edits. Subagents are for read-heavy work; concurrent writers create conflicts and coordination overhead.
  • A 40 KiB AGENTS.md. Past the cap, later files are dropped without an error. Split by directory.
  • Re-teaching generic patterns per tool. Prompt chaining, tool-use shape, and evaluation belong in prompt chaining, tool-use patterns, and agent evaluation; this page should only carry what is Codex-specific.

Sources