How to Build an AI Coding Agent in 2026: A Step-by-Step Guide
AI coding agents have moved beyond autocomplete. Tools like Claude Code, OpenAI Codex CLI, and Cursor don't just suggest code — they read your project…
AI coding agents have moved beyond autocomplete. Tools like Claude Code, OpenAI Codex CLI, and Cursor don't just suggest code — they read your project, run commands, fix errors, and ship features. In 2026, building your own coding agent is no longer a research project. It's a weekend build.
This guide walks you through the complete architecture: choosing an LLM, implementing tool calling, building the agent loop, sandboxing execution, and adding the context engineering that makes it all work. By the end, you'll have a working coding agent you can extend for your own workflows.
What Is an AI Coding Agent?
A coding agent is an LLM-powered system that can read, write, and execute code autonomously within a loop. Unlike a chatbot that generates text, a coding agent takes action:
- Reads files from your project
- Writes or patches source code
- Runs shell commands (tests, builds, linters)
- Observes results and self-corrects
- Repeats until the task is done
The key distinction: a coding agent has tools and a loop. The LLM decides which tool to call, observes the output, reasons about what to do next, and keeps going until it either succeeds or gives up.
This is the same pattern behind Claude Code (Anthropic), Codex CLI (OpenAI), and every serious coding agent shipping today.
The 5 Building Blocks
Before writing any code, understand the five components every coding agent needs:
| Component | Purpose | Example |
|---|---|---|
| LLM | Reasoning engine | Claude Sonnet 4, GPT-5.1, Qwen 3.5 |
| Tool definitions | What the agent can do | read_file, write_file, run_command |
| Agent loop | Orchestration logic | Loop until no tool calls remain |
| Sandbox | Safe execution environment | Docker container, Incus, gVisor |
| Context engineering | What the LLM sees | System prompt, project files, tool results |
Miss any one of these and your agent will either be useless (no tools), dangerous (no sandbox), or confused (bad context). Let's build each one.
Step 1: Choose Your LLM
Your LLM is the brain. For a coding agent, you need a model that excels at three things: code generation, tool calling (structured output), and long-context reasoning.
Top picks for March 2026
- Claude Sonnet 4 — Best balance of speed, cost, and coding ability. Native tool calling. 200K context.
- GPT-5.1 — OpenAI's Cookbook literally has a "Build a coding agent with GPT-5.1" recipe. Strong at structured tool use.
- GPT-5.3-Codex-Spark — Optimized for agentic coding, 1,000+ tok/sec. Powers Codex CLI.
- Qwen 3.5 (local) — If you want to run locally with Ollama, Qwen 3.5 is the best open-weight option for tool calling.
- Claude Opus 4 — Maximum reasoning depth for complex multi-file refactors.
For this tutorial we'll use the OpenAI Responses API (works with any GPT-5.x model), but the architecture is identical with Anthropic's Messages API or any provider that supports tool calling.
Quick model setup
from openai import OpenAI
client = OpenAI() # Uses OPENAI_API_KEY env var
MODEL = "gpt-5.1"
If you prefer Anthropic:
from anthropic import Anthropic
client = Anthropic() # Uses ANTHROPIC_API_KEY env var
MODEL = "claude-sonnet-4-20250514"
Step 2: Define Your Tools
Tools are the agent's hands. Without them, it's just a chatbot. A minimal coding agent needs three tools:
1. read_file — Read any file in the project
2. write_file — Create or overwrite a file
3. run_command — Execute a shell command
Here's how to define them as OpenAI-compatible tool schemas:
tools = [
{
"type": "function",
"function": {
"name": "read_file",
"description": "Read the contents of a file at the given path",
"parameters": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "Relative path to the file"
}
},
"required": ["path"]
}
}
},
{
"type": "function",
"function": {
"name": "write_file",
"description": "Write content to a file, creating it if needed",
"parameters": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "Relative path to the file"
},
"content": {
"type": "string",
"description": "Full file content to write"
}
},
"required": ["path", "content"]
}
}
},
{
"type": "function",
"function": {
"name": "run_command",
"description": "Run a shell command and return stdout/stderr",
"parameters": {
"type": "object",
"properties": {
"command": {
"type": "string",
"description": "Shell command to execute"
}
},
"required": ["command"]
}
}
}
]
Implementing tool handlers
import subprocess
from pathlib import Path
WORKDIR = Path("./workspace")
def handle_tool_call(name: str, args: dict) -> str:
if name == "read_file":
path = WORKDIR / args["path"]
if not path.resolve().is_relative_to(WORKDIR.resolve()):
return "Error: path traversal blocked"
return path.read_text() if path.exists() else "Error: file not found"
elif name == "write_file":
path = WORKDIR / args["path"]
if not path.resolve().is_relative_to(WORKDIR.resolve()):
return "Error: path traversal blocked"
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(args["content"])
return f"Written {len(args['content'])} bytes to {args['path']}"
elif name == "run_command":
result = subprocess.run(
args["command"], shell=True, capture_output=True,
text=True, timeout=30, cwd=WORKDIR
)
output = result.stdout + result.stderr
return output[:5000] # Truncate to avoid context bloat
return "Error: unknown tool"
Notice the path traversal check on file operations — this is your first line of defense. The agent should never escape its workspace directory.
> Pro tip: Production agents like Claude Code and Codex CLI add dozens more tools — search_files, patch_file (surgical edits), web_fetch, list_directory, and more. Start with three, then expand based on what your agent needs. For how context size affects tool design, see our context engineering guide.
Step 3: Build the Agent Loop
The agent loop is the core of your coding agent. It's deceptively simple:
1. Send the conversation (system prompt + messages) to the LLM
2. If the response contains tool calls → execute them, append results, go to 1
3. If no tool calls → return the response to the user
This is the exact pattern Claude Code, Codex CLI, and every serious coding agent uses. Here it is in code:
import json
def agent_loop(user_message: str, system_prompt: str) -> str:
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_message}
]
max_iterations = 20 # Safety limit
for i in range(max_iterations):
response = client.chat.completions.create(
model=MODEL,
messages=messages,
tools=tools,
tool_choice="auto"
)
msg = response.choices[0].message
messages.append(msg)
# No tool calls = agent is done
if not msg.tool_calls:
return msg.content
# Execute each tool call
for tool_call in msg.tool_calls:
args = json.loads(tool_call.function.arguments)
result = handle_tool_call(tool_call.function.name, args)
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": result
})
return "Agent hit iteration limit — task may be incomplete."
Why a loop instead of a single call?
A single LLM call can generate code, but it can't verify it works. The loop lets the agent:
- Write code, then run tests to check it
- See a test failure, then fix the bug
- Read existing files to understand context before making changes
- Iterate through multiple files in a logical order
This is what separates a coding agent from a code generator. The agent observes, reasons, and acts — repeatedly.
Step 4: Sandbox Your Agent
Here's the uncomfortable truth: your agent runs arbitrary shell commands. Without sandboxing, a confused or hallucinating LLM could rm -rf /, leak environment variables, or make network requests to arbitrary endpoints.
Every production coding agent sandboxes execution. Here's how the big ones do it:
| Agent | Sandbox approach |
|---|---|
| Codex CLI | Network-disabled Docker container per task |
| Claude Code | Permission tiers (read/write/execute) with user approval |
| Cursor | IDE-integrated with undo, file-scoped changes |
Docker-based sandbox (recommended)
The simplest production-grade approach is a Docker container:
# Dockerfile.sandbox
FROM python:3.12-slim
RUN useradd -m agent
WORKDIR /workspace
USER agent
# No network access, limited memory
# Controlled via docker run flags
Run your agent inside it:
docker run --rm \
--network none \
--memory 512m \
--cpus 1 \
-v $(pwd)/workspace:/workspace \
coding-agent-sandbox \
python agent.py "Add unit tests for auth.py"
Key flags:
--network none— No internet access. The agent can't exfiltrate data or download malicious packages.--memory 512m— Prevents runaway processes from eating all RAM.-v— Mount only the project directory, nothing else.
Minimum sandboxing checklist
Even without Docker, enforce these rules:
- [ ] Path containment — All file operations stay within the workspace
- [ ] Command allowlisting — Block dangerous commands (
rm -rf /,curl | sh, etc.) - [ ] Timeout enforcement — Kill commands that run longer than 30 seconds
- [ ] No secrets injection — Never put API keys in the agent's environment. Let the scripts the agent calls read secrets at runtime, as recommended by sandboxing best practices.
- [ ] Output truncation — Cap tool output at 5-10KB to prevent context window overflow
Step 5: Engineer Your Context
Context engineering is what separates a decent coding agent from a great one. The LLM only knows what you put in its context window — and with tool results piling up, you'll burn through tokens fast.
This is where context engineering becomes critical. If you haven't read our complete guide, the short version: curate what the model sees, not just what you prompt it with.
The system prompt
Your system prompt defines the agent's behavior. Here's a battle-tested starting point:
SYSTEM_PROMPT = """You are a coding agent. You help users by reading, writing,
and executing code in their project.
Rules:
- Always read relevant files before making changes
- Run tests after writing code to verify correctness
- Make minimal, focused changes — don't rewrite entire files
- If a command fails, read the error and try to fix it
- If you're stuck after 3 attempts, explain the issue and stop
Available tools: read_file, write_file, run_command
Working directory: /workspace
"""
Context management strategies
As your agent loops, the message history grows. Here's how to keep it manageable:
1. Truncate tool output — Cap at 5KB per tool result. Nobody needs 50KB of test output.
2. Summarize periodically — After 10+ iterations, inject a summary of progress so far and trim old messages.
3. Use prompt caching — If your provider supports it (Anthropic and OpenAI both do), prompt caching can cut costs by 90% on the static portions of your context.
4. Load files on demand — Don't dump the entire project into context. Let the agent read_file what it needs.
> Real-world example: The OpenAI Cookbook's GPT-5.1 coding agent recipe demonstrates this pattern: the agent scaffolds a project, refines it through patches, executes commands, and even fetches external documentation — all within a managed context window.
Step 6: Put It All Together
Here's the complete minimal coding agent in under 100 lines:
#!/usr/bin/env python3
"""Minimal AI coding agent — reads, writes, and executes code."""
import json
import subprocess
from pathlib import Path
from openai import OpenAI
client = OpenAI()
MODEL = "gpt-5.1"
WORKDIR = Path("./workspace")
MAX_ITERATIONS = 20
SYSTEM_PROMPT = """You are a coding agent. Read files, write code, run commands.
Always read before writing. Run tests after changes. Stop after 3 failed attempts."""
tools = [
{"type": "function", "function": {
"name": "read_file",
"description": "Read a file",
"parameters": {"type": "object", "properties": {
"path": {"type": "string"}}, "required": ["path"]}}},
{"type": "function", "function": {
"name": "write_file",
"description": "Write a file",
"parameters": {"type": "object", "properties": {
"path": {"type": "string"},
"content": {"type": "string"}}, "required": ["path", "content"]}}},
{"type": "function", "function": {
"name": "run_command",
"description": "Run a shell command",
"parameters": {"type": "object", "properties": {
"command": {"type": "string"}}, "required": ["command"]}}}
]
def handle_tool(name, args):
if name == "read_file":
p = WORKDIR / args["path"]
return p.read_text() if p.exists() else "File not found"
elif name == "write_file":
p = WORKDIR / args["path"]
p.parent.mkdir(parents=True, exist_ok=True)
p.write_text(args["content"])
return f"OK — wrote {p}"
elif name == "run_command":
r = subprocess.run(args["command"], shell=True,
capture_output=True, text=True, timeout=30, cwd=WORKDIR)
return (r.stdout + r.stderr)[:5000]
return "Unknown tool"
def run(task):
msgs = [{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": task}]
for _ in range(MAX_ITERATIONS):
resp = client.chat.completions.create(
model=MODEL, messages=msgs, tools=tools)
msg = resp.choices[0].message
msgs.append(msg)
if not msg.tool_calls:
return msg.content
for tc in msg.tool_calls:
result = handle_tool(tc.function.name,
json.loads(tc.function.arguments))
msgs.append({"role": "tool",
"tool_call_id": tc.id, "content": result})
return "Hit iteration limit."
if __name__ == "__main__":
import sys
print(run(" ".join(sys.argv[1:])))
Save this as agent.py, create a workspace/ directory, and run:
python agent.py "Create a Python Flask app with a /health endpoint and write tests for it"
The agent will create the files, write tests, and run them — all autonomously.
Beyond the Basics: What Production Agents Add
The agent above works, but production tools go further. Here's what Claude Code, Codex CLI, and similar agents add on top:
Patch-based editing
Instead of rewriting entire files, production agents use surgical edits — replacing specific lines or applying diffs. This is more token-efficient and less error-prone. The OpenAI Cookbook recipe uses a code_editor tool with apply_patch commands for this.
Multi-file awareness
Real projects span hundreds of files. Production agents add search_files (grep/ripgrep), list_directory, and find_references tools so the LLM can navigate without reading everything.
Permission tiers
Claude Code classifies operations by risk:
- Read — Always allowed (reading files, listing directories)
- Write — Requires approval on first use
- Execute — Always requires approval unless in auto-accept mode
This graduated trust model lets developers work fast while staying safe.
AGENTS.md and project configuration
Both Codex CLI and Claude Code read project-level configuration files (AGENTS.md, CLAUDE.md) that tell the agent about coding standards, test commands, and project structure. This is context engineering in action — the agent gets project-specific knowledge before it starts.
Prompt caching for cost control
A 20-iteration agent loop with GPT-5.1 can easily hit 100K+ tokens. Prompt caching caches the system prompt and tool definitions across calls, cutting per-iteration costs dramatically.
Common Mistakes and How to Avoid Them
| Mistake | Why it happens | Fix |
|---|---|---|
| Agent rewrites files instead of patching | No patch tool available |
Add a surgical edit tool |
| Context window blowup | Uncapped tool output | Truncate all outputs to 5KB |
| Agent loops forever | No stop condition | Set max iterations + "give up" instructions |
| Agent deletes critical files | No sandbox | Docker + path containment |
| Agent ignores test failures | System prompt doesn't enforce testing | Add explicit "run tests after changes" rule |
FAQ
What LLM is best for building a coding agent?
As of March 2026, Claude Sonnet 4 and GPT-5.1 are the strongest options for coding agents. Both have excellent tool calling support and strong code generation. For local/private setups, Qwen 3.5 running on Ollama is the best open-weight alternative, though it trails the commercial models on complex multi-file tasks. Choosing between Qwen versions? See our Qwen 3.5 vs 2.5 comparison — 3.5 has better tool calling, but upgrading isn't always worth it if your prompts are tuned for 2.5. Choosing between Qwen versions? See our Qwen 3.5 vs 2.5 comparison — 3.5 has better tool calling, but upgrading isn't always worth it if your prompts are tuned for 2.5.
How is a coding agent different from GitHub Copilot?
Copilot (and similar autocomplete tools) suggest code inline as you type. A coding agent runs autonomously — it reads your project, writes code, executes commands, checks results, and iterates. Copilot assists; an agent acts. This distinction matters — autonomous coding agents are already reshaping engineering teams as companies rethink how many developers they need. For a full comparison, see our Claude Code vs Cursor vs Copilot breakdown.
Do I need Docker to sandbox my coding agent?
Not strictly, but it's the most reliable approach. Without Docker, you need manual path containment, command filtering, timeout enforcement, and network restrictions — all of which Docker handles with a single docker run command. Alternatives include Incus containers, gVisor, and cloud sandbox services like E2B or Daytona.
How much does it cost to run an AI coding agent?
Costs vary by model and task complexity. A typical 15-iteration agent loop with GPT-5.1 uses roughly 50-80K tokens, costing $0.15-0.40 per task. With prompt caching, you can cut that by 50-90% on the cached portion. Local models via Ollama cost nothing per token but require capable hardware — see our best hardware for local LLMs guide.
Can I build a coding agent with open-source models?
Yes. Qwen 3.5 and similar open-weight models support tool calling and work well for coding tasks. The architecture in this guide is model-agnostic — swap the API client and model name, and everything else stays the same. Performance will be lower than commercial models on complex tasks, but for straightforward code generation and testing, open models are viable.
What is the OpenAI Cookbook coding agent recipe?
The OpenAI Cookbook published a reference implementation showing how to build a coding agent with GPT-5.1 using the Responses API. It covers project scaffolding, code patching, command execution, and fetching external documentation — all within a managed agent loop. It's the closest thing to an official "how to build Codex CLI" tutorial.
Frequently Asked Questions
What LLM is best for building a coding agent?
How is a coding agent different from GitHub Copilot?
Do I need Docker to sandbox my coding agent?
How much does it cost to run an AI coding agent?
Can I build a coding agent with open-source models?
What is the OpenAI Cookbook coding agent recipe?
🔧 Tools in This Article
All tools →Related Guides
All guides →AI Agent Sandbox Guide (2026): Best Options Compared
Looking for the best AI agent sandbox in 2026? Compare AIO Sandbox, E2B, Daytona, and self-hosted options for browser access, isolation, tooling, and fit.
10 min read
AI AgentsThe Reflection Pattern: How AI Agents Self-Correct
The first answer an LLM gives is rarely its best. Ask a developer to write code and they'll write a draft, test it, find bugs, fix them, and iterate. AI…
8 min read
AI AgentsAI Hallucination Guardrails That Actually Work
LLMs hallucinate. That hasn't changed in 2026 — what's changed is that we now have proven, deployable patterns for catching hallucinations before they…
7 min read