Every AI coding agent — Claude Code, Cursor, Codex CLI, Devin — is built on the same pattern:
while True:
response = completion(model=MODEL, messages=messages, tools=TOOLS)
message = response.choices[0].message
if not message.tool_calls:
return message.content
for tc in message.tool_calls:
result = execute(tc.function.name, tc.function.arguments)
messages.append({"role": "tool", "tool_call_id": tc.id, "content": result})That's it. The model calls tools until it's done. Everything else is refinement.
Unix philosophy: everything is a file, everything can be piped.
| You need | Bash command |
|---|---|
| Read files | cat, head, grep |
| Write files | echo '...' > file |
| Search | find, grep, rg |
| Execute | python, npm, make |
| Subagent | python 01-agent-loop/agent.py "task" |
The last line is the key insight: calling itself via bash implements subagents. No special framework needed — just recursion through process spawning.
Main Agent
└─ bash: python 01-agent-loop/agent.py "analyze architecture"
└─ Subagent (isolated process, fresh history)
├─ bash: find . -name "*.py"
├─ bash: cat src/main.py
└─ Returns summary via stdout
Process isolation = Context isolation:
- Child process has its own
history=[] - Parent captures stdout as tool result
- Recursive calls enable unlimited nesting
- One tool is enough — Bash is the gateway to everything
- Recursion = hierarchy — Self-calls implement subagents
- Process = isolation — OS provides context separation
- Prompt = constraint — Instructions shape behavior
| Feature | Status | Added In |
|---|---|---|
| Multiple tools | ❌ | Tool Design |
| Todo tracking | ❌ | Structured Planning |
| Agent types | ❌ | Subagents & Skills |
| Skills/knowledge | ❌ | Subagents & Skills |
That's the point — you don't need any of it for a working agent.
Bash is All You Need.