The Core Agent Loop Pattern in Coding Agent CLIs
A research article on the single shared design at the heart of Codex, Claude Code, Gemini CLI, and OpenCode — the "agent loop." Research date: Aug 2, 2026. All facts linked to verified primary sources.
TL;DR
Every coding agent CLI — Codex, Claude Code, Gemini CLI, OpenCode — implements the same core pattern: a loop that alternates model inference with tool execution, feeding tool results back into the prompt until the model emits a final message. OpenAI calls it "the agent loop" and states it sits "at the heart of every AI agent"; Anthropic documents it as the "agentic loop" (gather context → take action → verify results); Google's architecture doc describes the identical flow; OpenCode implements it as iterative steps gated by permissions. The loop is the product of convergent engineering, and its academic ancestor is ReAct (https://arxiv.org/abs/2210.03629).
The real craft of an agent CLI is not the loop itself — a basic loop is "a few dozen lines of code" (Simon Willison, https://simonwillison.net/guides/agentic-engineering-patterns/how-coding-agents-work/) — but the harness engineering around it: prompt assembly, context management, caching, exit conditions, and permission/sandbox gates.
Part 1 — The Canonical Loop Pattern
1.1 The six stages
| # | Stage | What happens | Who controls it |
|---|---|---|---|
| 0 | Turn starts | User submits a query; conversation history is loaded | CLI frontend |
| 1 | Prompt assembly | System/instructions, tool schemas, memory files, environment context, history, user message are composed into one prompt | Harness (not the model) |
| 2 | Model inference | Prompt is sent to the model API (streamed via SSE); model emits reasoning + optional tool calls + text | Model |
| 3 | Parse tool calls | Each function call (name + arguments) is deserialized and validated against registered tools | Harness |
| 4 | Execute tools | Tools run (shell, file edit, search, web); gated by sandboxing / user approval / permissions | Harness + OS + user |
| 5 | Append + re-query | Tool outputs are appended to the input; prompt grows; re-query the model (new prompt = old prompt + tool results, as an exact prefix) | Harness |
| 6 | Exit | Loop ends when the model emits a final assistant message (no more tool calls), or an exit tool / max-steps / user interrupt fires | Model or harness |
1.2 Pseudocode
def run_turn(user_input):
input = assemble_input(system_prompt, tool_schemas, memory_files,
environment_context, conversation_history, user_input)
while True:
response = model.infer(input) # stage 2
if response.is_final_message():
return response.text # stage 6 — exit condition
for call in response.tool_calls:
result = execute_tool(call, gate=permissions) # stage 4
input.append(function_call(call))
input.append(function_call_output(result)) # stage 5
if input.exceeds_context_window():
input = compact(input) # context management
if steps_exhausted():
return summarize_and_stop() # forced exit
This is the loop OpenAI documents end-to-end in "Unrolling the Codex agent loop" (https://openai.com/index/unrolling-the-codex-agent-loop/): "the agent executes the tool call and appends its output to the original prompt. This output is used to generate a new input that's used to re-query the model... This process repeats until the model stops emitting tool calls and instead produces a message for the user."
1.3 Key terminology (turn / thread / step)
- Step / iteration: one inference + tool-call cycle inside a turn. A turn can contain "hundreds of tool calls" (OpenAI).
- Turn: the whole journey from user input to final assistant message. "Each turn always ends with an assistant message... which signals a termination state in the agent loop" (OpenAI).
- Thread / session: the multi-turn conversation; every new turn re-sends the full accumulated history as part of the prompt.
- OpenCode's
steps: "the maximum number of agentic iterations an agent can perform before being forced to respond with text only" (https://opencode.ai/docs/agents/).
Part 2 — How the Four Major CLIs Implement the Same Loop
2.1 Codex CLI — the most explicit documentation
Source: https://openai.com/index/unrolling-the-codex-agent-loop/ (M. Bolin, Jan 2026), plus the open-source repo https://github.com/openai/codex.
- Transport: HTTP to the Responses API (SSE stream; events like
response.output_item.added,response.output_text.delta,response.completed). - Prompt construction (the
instructions/tools/inputfields): instructions: model-specific base instructions bundled with the CLI (e.g.gpt-5.2-codex_prompt.mdin the repo).tools: CLI-provided tools (e.g.shell,update_plan), API-provided tools (e.g.web_search), and user tools via MCP servers (e.g.mcp__weather__get-forecast).input, in order: (1) adevelopermessage describing the sandbox and permission rules — which apply only to Codex's ownshelltool, not to MCP tools; (2) optionaldeveloper_instructionsfrom config; (3) user instructions aggregated fromAGENTS.override.md/AGENTS.mdhierarchy (32 KiB cap) and skills metadata; (4) an<environment_context>message withcwdandshell.- Loop mechanics: each tool call and its
function_call_outputare appended toinputso the new prompt is an exact prefix of the old one — intentionally, to maximize prompt-cache hits. - Statelessness: Codex deliberately does not use
previous_response_id, keeping every request stateless and ZDR-compatible (PRs #642, #1641). - Compaction: originally manual
/compact(summarize via the API and restart with the summary); now automatic via the/responses/compactendpoint whenauto_compact_limitis exceeded; a specialtype=compactionitem withencrypted_contentpreserves the model's latent understanding.
2.2 Claude Code — "gather context, take action, verify results"
Source: https://code.claude.com/docs/en/how-claude-code-works (official docs).
- The agentic loop: three phases that blend together — gather context (search/read), take action (edit/run), verify results (run tests, check output) — repeated until the task is complete. A question may only need context gathering; a bug fix cycles through all three.
- Two components: "models that reason and tools that act"; Claude Code itself is the "agentic harness" — "it provides the tools, context management, and execution environment that turn a language model into a capable coding agent."
- Tool categories (five): file operations, search, execution, web, code intelligence. "Each tool use returns information that feeds back into the loop, informing Claude's next decision."
- Human in the loop: the user can interrupt at any point (Esc cancels the running tool call; typed corrections are read as soon as the current action completes).
- Context management: auto-compaction clears older tool outputs first, then summarizes the conversation; persistent rules belong in
CLAUDE.md(a "Compact Instructions" section can control what's preserved);/contextshows usage; skills load on demand; subagents get a fresh, isolated context and return only a summary. - Sessions: every message/tool use is written to JSONL under
~/.claude/projects/; file edits are snapshotted (checkpoints) before changes; sessions can be resumed (--continue/--resume) and forked (--fork-session). - Safety gates: four permission modes (Manual, Accept edits, Plan, Auto) cycled with Shift+Tab, plus per-command rules in
.claude/settings.json.
2.3 Gemini CLI — approval-gated loop with PTY terminal emulation
Sources: architecture docs https://google-gemini.github.io/gemini-cli/docs/architecture.html · PTY post https://developers.googleblog.com/en/say-hello-to-a-new-level-of-interactivity-in-gemini-cli/ · repo https://github.com/google-gemini/gemini-cli (→ Antigravity CLI).
- Two packages:
packages/cli(frontend: input, history, rendering) andpackages/core(backend: prompt construction, tool registration/execution, conversation state management). - The interaction flow (per architecture doc): user input → core constructs a prompt (history + tool definitions) → Gemini API → if the API requests a tool: mutating tools (file system or shell) require explicit user approval; read-only tools may proceed without confirmation → execute → "the result is sent back to the Gemini API" → API processes the result and generates the final response → displayed by the CLI.
- Signature difference: shell commands run inside a PTY (node-pty) with terminal-state serialization, enabling interactive commands (e.g.
vim, long-running processes) that a plain subprocessbashtool cannot drive. - Loop topology is otherwise identical: prompt → API → tool request → execute → result back → next inference.
2.4 OpenCode — steps, subagents, and permission-gated iterations
Source: https://opencode.ai/docs/agents/ · repo https://github.com/anomalyco/opencode.
- Loop shape: with no
stepslimit set, "the agent will continue to iterate until the model chooses to stop or the user interrupts the session." Withstepsset, the agent is forced to respond with text only when exhausted, receiving "a special system prompt instructing it to respond with a summarization of its work and recommended remaining tasks" — i.e. a harness-enforced exit condition. - Agent hierarchy: primary agents (Build — all tools; Plan — read-only) and subagents (General, Explore, Scout) invoked via a Task tool or
@mention; subagent runs are child sessions with fresh context. - Hidden system agents running inside the loop: a compaction agent (compacts long context into a smaller summary automatically), a title agent, and a summary agent.
- Permission gates:
ask/allow/denyper tool, with glob patterns for fine-grained bash control (e.g."bash": {"git push": "ask", "grep *": "allow"}) and wildcard tool matching ("mymcp_*": "deny").
2.5 The shared shape — one table
| Aspect | Codex CLI | Claude Code | Gemini CLI | OpenCode |
|---|---|---|---|---|
| Loop name | "the agent loop" | "the agentic loop" | core interaction flow | agentic iterations / steps |
| Stages | input → prompt → inference → tool call → execute → append → repeat | gather context → take action → verify → repeat | input → prompt → API → tool request → approve/execute → result back → final | prompt → tool calls → execute (gated) → append → repeat |
| Exit condition | assistant message; /responses/compact when full |
model stops; auto-compaction | final response after tool results | model stops, or steps limit forces summarization |
| Safety gate | OS sandbox for its own shell tool; approval policy messages |
permission modes + checkpoints | per-tool user approval for mutating tools | permission ask/allow/deny + glob rules |
| Context mgmt | auto compaction via /responses/compact, ZDR stateless |
auto-compaction (clear outputs → summarize) | conversation state mgmt; 1M-token window | hidden compaction agent |
| Nested loops | subagents via update_plan-style orchestration |
dispatch_agent subagent tool (fresh context) |
— | subagents = child sessions, Task tool |
| Docs | openai.com/index/unrolling-the-codex-agent-loop/ | code.claude.com/docs/en/how-claude-code-works | google-gemini.github.io/gemini-cli/docs/architecture.html | opencode.ai/docs/agents/ |
Part 3 — The Engineering Around the Loop
The loop is identical; the engineering differs. Four problems dominate every implementation:
3.1 Context window management (the quadratic growth problem)
- Every inference re-sends the full conversation, so prompt length grows with each tool call — "the agent could decide to make hundreds of tool calls in a single turn, potentially exhausting the context window. For this reason, context window management is one of the agent's many responsibilities" (OpenAI).
- Compaction strategies evolve from manual to automatic: Codex went from user-invoked
/compactto the automatic/responses/compactendpoint (https://openai.com/index/unrolling-the-codex-agent-loop/); Claude Code clears older tool outputs first, then summarizes, and stops auto-compacting with a "thrashing error" if a single huge output refills the window (https://code.claude.com/docs/en/how-claude-code-works); OpenCode delegates compaction to a hidden agent (https://opencode.ai/docs/agents/). - Isolation as an alternative to compaction: subagents with fresh context (Claude Code's
dispatch_agent, OpenCode's child sessions) keep the main context lean — "their work doesn't bloat your context" (Claude Code docs).
3.2 Prompt caching (making the growing loop affordable)
- Cache hits require exact prefix matches; "to realize caching benefits, place static content like instructions and examples at the beginning of your prompt, and put variable content at the end" (OpenAI, https://platform.openai.com/docs/guides/prompt-caching).
- Cache-miss hazards documented by the Codex team: changing the
toolslist mid-conversation, changing the model, changing sandbox/approval config or cwd. The Codex team even fixed an MCP tool-enumeration ordering bug because it broke caching (https://github.com/openai/codex/pull/2611), and handles mid-conversation config changes by appending new messages instead of editing old ones. - Because cache hits make sampling linear instead of quadratic, caching discipline is the single biggest cost lever in the loop (ByteByteGo's analysis: "quadratic prompt growth, caching fragility" — https://blog.bytebytego.com/p/how-openai-codex-works).
3.3 Exit conditions and runaway prevention
- Model-determined exit: assistant message without tool calls (OpenAI), model "chooses to stop" (OpenCode docs).
- Harness-enforced exit: OpenCode's
stepslimit forces a text-only summarization; Claude Code stops auto-compacting after repeated refills to avoid infinite loops (thrashing error); Anthropic's loop taxonomy adds goal-based (/goal) and time-based (/loop,/schedule) loops over the basic turn-based one (https://claude.com/blog/getting-started-with-loops). - User interrupt: Esc/Steering input mid-turn is a first-class part of Claude Code's loop ("You're part of this loop too").
3.4 Safety gates inside the loop
The human sits inside the loop at the tool-execution stage, not after it:
- Gemini: approval required per mutating tool call before execution (architecture doc).
- Codex: sandbox rules and approval policies are injected as developer-role messages into the prompt — the model is told when to ask; the sandbox itself only wraps Codex's own shell tool.
- Claude Code: permission modes gate file edits and shell commands; checkpoints make edits reversible.
- OpenCode: permission matrix (
ask/allow/deny) including glob-matched bash commands;planagent defaults everything toask.
Part 4 — Variants on the Pattern
- Workflow vs. agent (Anthropic, https://www.anthropic.com/research/building-effective-agents): workflows = predetermined code paths orchestrating LLMs; agents = LLMs choosing tools in a loop based on environmental feedback. Coding CLIs are agents.
- Loop + memory (Reflexion, https://arxiv.org/abs/2303.11366): the loop gains an explicit reflect-and-store step (episodic memory) — the ancestor of session persistence (Claude Code JSONL sessions, auto-memory,
AGENTS.md). - Plan mode as a restricted loop: Claude Code's Plan mode (read-only tools), OpenCode's Plan agent (all edits
ask), and Codex'supdate_plantool are the same loop with the tool surface restricted — evidence that the loop is orthogonal to the toolset. - Nested loops: subagent loops with fresh context (Claude Code
dispatch_agent, OpenCode Task tool child sessions) run inside the outer loop and return only summaries — a hierarchy, not a different loop.
Conclusion
The core agent loop is one pattern, universally implemented: assemble prompt → infer → parse tool calls → execute (gated) → append results → re-query → exit on assistant message. It is documented identically by OpenAI, Anthropic, and Google, descended from ReAct, and — in Simon Willison's words — "LLM + system prompt + tools in a loop… that's most of what it takes to build a coding agent" (https://simonwillison.net/guides/agentic-engineering-patterns/how-coding-agents-work/).
What differentiates coding agent CLIs is not the loop but the harness around it: context compaction, prompt-cache discipline, exit-condition enforcement, subagent isolation, and where the human permission gate sits. As Gergely Orosz concluded after interviewing the Codex team: the agent loop is "something every AI agent uses, not just Codex" (https://newsletter.pragmaticengineer.com/p/how-codex-is-built).
References (all primary/verified)
Official loop documentation - OpenAI — Unrolling the Codex agent loop: https://openai.com/index/unrolling-the-codex-agent-loop/ · Codex repo: https://github.com/openai/codex - Anthropic — How Claude Code works: https://code.claude.com/docs/en/how-claude-code-works · Building effective agents: https://www.anthropic.com/research/building-effective-agents · Getting started with loops: https://claude.com/blog/getting-started-with-loops - Google — Gemini CLI architecture: https://google-gemini.github.io/gemini-cli/docs/architecture.html · PTY interactivity: https://developers.googleblog.com/en/say-hello-to-a-new-level-of-interactivity-in-gemini-cli/ · Gemini CLI repo: https://github.com/google-gemini/gemini-cli - OpenCode — Agents docs: https://opencode.ai/docs/agents/ · repo: https://github.com/anomalyco/opencode - OpenAI — A Practical Guide to Building Agents (the loop is "central"): https://cdn.openai.com/business-guides-and-resources/a-practical-guide-to-building-agents.pdf
Academic ancestors - ReAct: https://arxiv.org/abs/2210.03629 · Reflexion: https://arxiv.org/abs/2303.11366
Analyses - Simon Willison — How coding agents work: https://simonwillison.net/guides/agentic-engineering-patterns/how-coding-agents-work/ · Designing agentic loops: https://simonwillison.net/2025/Sep/30/designing-agentic-loops/ - Gergely Orosz (Pragmatic Engineer) — How Codex is built: https://newsletter.pragmaticengineer.com/p/how-codex-is-built - ByteByteGo — How OpenAI Codex works: https://blog.bytebytego.com/p/how-openai-codex-works - OpenAI prompt caching docs: https://platform.openai.com/docs/guides/prompt-caching