What Pi Coding Agent Keeps in the Core
A source-based comparison of Pi, Codex, and OpenCode shows how a minimal coding harness leaves workflow policy and isolation to the user.
I wanted to understand Pi beyond a feature checklist. Why would a coding agent deliberately leave out plan mode, subagents, MCP, permission popups, and background shell jobs?
If feature count were the only measure, Pi would look unfinished. Its default coding agent exposes just four tools: read, write, edit, and bash. After tracing its agent loop, session model, and extension system, I found a more useful distinction: Pi supplies mechanisms, while users assemble workflow policy around them.
This is not a benchmark of model quality, speed, or cost. I compared code snapshots from August 6, 2026: Pi c03d78b, Codex 57f42a8, and OpenCode def7220. I checked their official documentation again on August 7. The comparison is about where each system puts its agent loop, extension points, workflow defaults, and execution boundary.
What happens in one agent turn
Pi core receives AgentMessage[]. Before a model call, transformContext() can reshape the saved context and convertToLlm() turns it into messages the provider accepts. The model then streams text or tool calls. When it requests tools, the core validates their arguments, runs the complete batch, appends each toolResult, and decides whether another model turn is needed. The agent core documentation and agent-loop.ts expose the flow directly.
The diagram puts the mechanics and policy boundary in the same view.
Pi core repeats the turn mechanics. Planning, approvals, delegation, and other workflow policy sit outside this loop.
Hooks such as beforeToolCall and afterToolCall let a caller block a tool or rewrite its result. Steering, follow-up queues, abort signals, and shouldStopAfterTurn provide more control without prescribing a working method. Pi’s minimalism keeps the loop separate from the rules around it.
Four layers, one responsibility each
Pi splits a complete coding agent into four packages that can also be used independently:
| Layer | Responsibility |
|---|---|
pi-ai |
Normalize streaming, thinking, tool calls, usage, and errors across model providers |
pi-agent-core |
Hold agent state, drive the multi-turn tool loop, execute tools, and emit lifecycle events |
pi-tui |
Update the terminal interface while preserving normal terminal scrollback |
pi-coding-agent |
Combine the first three layers with file and shell tools, context files, sessions, and extensions |
This split supports two different jobs. Someone studying an agent runtime can use only pi-ai or pi-agent-core; someone who wants a ready coding agent can use the complete CLI. The complete CLI still has four official interfaces: an interactive TUI, print or JSON event output for scripts, stdin/stdout RPC, and an embeddable SDK. Pi documentation|Usage|SDK
Sessions follow the same separation. Pi stores JSONL nodes with id and parentId, allowing one history to branch while keeping the original records. Compaction and branch summaries prepare a smaller context for later model calls; they do not replace the saved history. Sessions|Compaction What the session retains and what the model sees in one turn remain separate decisions.
“Not built in” does not mean “impossible”
Pi describes its approach as “primitives, not features.” The core stays small, while TypeScript extensions, skills, prompt templates, themes, and packages supply optional behavior. Pi|Extensions
An extension can add or replace tools, commands, shortcuts, events, UI components, and providers. Permission gates, path protection, MCP, subagent orchestration, and plan mode can live outside the core. Skills load their full SKILL.md only when relevant, while a package can distribute extensions, skills, prompts, and themes together.
I read this as a separation between mechanism and policy. The agent loop exposes events and hooks, but it does not decide a team’s approval rules. Files, shell commands, and processes remain ordinary composition points rather than a built-in feature for every workflow.
The cost is direct. Different users can assemble meaningfully different versions of Pi. A team that needs consistent approvals, isolation, and collaboration rules has to own that policy layer itself.
Minimalism does not supply a security boundary
Pi has no built-in operating-system sandbox. Its file tools, shell, extensions, and packages run with the permissions of the user who started Pi. The official security documentation also draws a narrow boundary around Project Trust: it controls whether project settings, extensions, packages, and skills are loaded, but it does not constrain later tool requests from the model.
Real isolation has to come from a container, VM, microVM, or another OS boundary. Pi can run entirely inside that environment, or it can route its built-in tools into Gondolin. Extension tools that have not been routed separately may still execute on the host. Containerization
A permission extension can govern whether a tool is called. That is different from an OS boundary that technically prevents a process from reaching a file or the network. This is the distinction that matters most in the comparison with Codex and OpenCode.
Pi, Codex, and OpenCode set different defaults
| Dimension | Pi | Codex | OpenCode |
|---|---|---|---|
| Product shape | Separable provider API, agent runtime, TUI, and minimal coding harness | Integrated coding-agent product built around a shared Rust core and app-server | Multi-model client/server coding environment whose TUI is one client |
| Default workflow | Four tools and an open loop; plan mode, MCP, and subagents live outside the core | A shared product workflow across CLI, IDE, desktop, and cloud | Build and Plan agents, subagents, LSP, MCP, plugins, and permission rules are provided |
| Execution safety | Tools inherit the host user’s authority; isolation is deployed separately | Approval policy and an OS-enforced sandbox are separate controls | allow, ask, and deny govern tool policy; shell still has host-user authority |
| Model direction | pi-ai is designed for multiple providers and cross-model sessions |
The official product centers on OpenAI and Codex; the CLI also supports custom and local providers | AI SDK and Models.dev provide cloud and local provider options |
For Codex, the difference that matters here is the execution boundary. Sandbox mode limits what a process can technically reach, while approval policy decides when Codex must stop and ask. The common local defaults allow writes in the workspace and keep network access off; Codex cloud runs in isolated managed containers. Official OpenAI documentation on agent approvals and security
OpenCode places more workflow policy in the product. Its TUI connects to a server that can also expose sessions to other clients, while agents, LSP, MCP, and permissions all have supported configuration surfaces. Server|Agents|Permissions Those permissions are still tool policy rather than an OS sandbox. The OpenCode v2 documentation states that shell commands retain the host user’s filesystem, process, and network authority. OpenCode v2 permissions
All three systems are extensible and can eventually be assembled into similar shapes. The table compares their defaults: Pi asks the user to choose the policy, Codex puts policy inside an integrated product, and OpenCode provides a broader ready-made workflow enforced mainly at the tool layer.
How I would choose
- I would choose Pi when I want to study or reshape an agent loop, embed a coding harness, or keep the workflow minimal. I would also need to manage extensions and isolation myself.
- I would choose Codex when I need an OS-enforced local boundary and want one product model across CLI, IDE, desktop, and cloud.
- I would choose OpenCode when I want an open-source, multi-provider setup with Plan, subagent, LSP, MCP, and server interfaces ready to use.
These are starting points rather than fixed categories. All three projects change quickly, and extensions, plugins, and configuration can move their boundaries. I would ask two questions: who will maintain the workflow policy, and does the tool itself need to enforce execution isolation?
For my own work, I agree with Pi’s decision to keep the core small. I am testing Pi in practice, and the small set of components it keeps is exactly what I want in a coding agent. The DeepSeek harness is outside this comparison for now, but it seems to follow a similar philosophy to mine. I would like to explore it next.