Runtimes: claude and pi¶
What is shared between the two harnesses, what differs, and what that difference means when you wire an agent up.
Every agent declares a runtime (agents add --runtime claude|pi). Host-level
concerns (the Linux user + isolation, agentd + authz, secrets/sops, systemd,
crons, the GitOps repo, top) are shared; the agent process, channel, auth,
and tools differ per runtime. pi (earendil-works/pi) — a native,
model-agnostic runtime — is the default, on the web-view cockpit (--channel
webview) as the default channel; claude is the opt-in.
# pi + webview (default): model-agnostic, --api-key boots immediately:
agentctl agents add alice --user-email alice@example.com --api-key <key> [--provider groq]
# claude: subscription login
agentctl agents add bob --runtime claude --user-email bob@example.com
# either runtime on a chat platform instead — --channel is now explicit, since
# webview is the default (see ../guides/channels.md):
agentctl agents add carol --channel telegram --bot-token <t> [--owner-id <id>]
Note. pi always boots on a provider API key (
--api-key, or a stored provider key). The oldlogin piOAuth-subscription path was removed; it was never used in practice.
Both runtimes take a catalog MCP the same way; only the client config differs.
mcp add renders the same secrets, materializes the same socket and unit pair under
the same scope rule, then writes the config its runtime's client reads —
~/.claude.json for claude, ~/.pi/agent/mcp.json for pi. The ledger key does not
differ: both runtimes record the MCP under tools:, which is the one MCP-declaration
key. A name in tools: is a catalog MCP on either runtime — there is no second
population in the key and nothing to disambiguate. Host-level binaries (zk, anydoc)
are not declared there at all: they are installed on every host and reached through
plain Bash, with no ledger entry and no per-agent activation. Both resolve through the
same GitOps overlay, and mcp add <mcp> self is plain self scope on either runtime.
claude vs pi: what works with each¶
| Capability | claude | pi |
|---|---|---|
| Channel: Telegram | yes | yes |
| Channel: Teams | yes (needs teams-gateway install first) |
yes (needs teams-gateway install first) |
| Channel: Slack | yes (needs slack-gateway install first) |
yes (needs slack-gateway install first) |
| Auth | subscription login (PKCE) | provider API key |
| Models | Claude (Anthropic) | model-agnostic (Groq default; any pi provider via its key) |
| Capabilities | MCPs (mcp add, tools: ledger) |
MCPs (mcp add, tools: ledger) — same verb, same key |
| A catalog MCP | used directly, over a socket, from ~/.claude.json |
used directly, over the same socket, from ~/.pi/agent/mcp.json. mcp add <mcp> self needs no operator step |
| MCP client config | ~/.claude.json (secret values substituted) |
~/.pi/agent/mcp.json (${KEY} references, resolved from the unit env) |
| MCP tool surface | every tool declared to the model | codemode by default — tools are reached from a script, not declared one by one; a catalog item opts out with exposure: (see MCPs) |
| Calling several tools at once | one tool call per model turn | one script calls many — MCP tools and the built-ins (bash, read, edit, write) in the same run, with only the script's output returned (see codemode) |
Skills (SKILL.md dirs) |
~/.claude/skills/; root steering file ~/CLAUDE.md |
~/.pi/agent/skills/; root steering file ~/AGENTS.md |
| Subagents | yes (agents subagents) |
no |
| Lifecycle hooks | settings.json hooks (agents hooks) |
pi extensions (~/.pi/agent/extensions/) |
| Safety floor | auto-mode soft_deny prose read by a classifier (draft-don't-send, archive-don't-delete) |
deterministic regex gate: asks in the cockpit, fails closed on deny/timeout/no-operator (PI_FLOOR_OFF to disable). See Security model |
Setup takeaways: Teams and Slack agents work on both runtimes (the shared
gateway feeds claude via its channel shim) but need the host gateway installed first
(teams-gateway install / slack-gateway install; see The Teams gateway);
subagents are claude-only; a pi agent activates any catalogued MCP directly with
mcp add, exactly as a claude agent does, and then reaches it from a
codemode script rather than as a
declared tool. Skills live in a runtime-specific
directory and a per-project note gets the runtime-correct filename too: a fresh
zk new --group project on pi renders AGENTS.md, not CLAUDE.md; agentctl skills
<agent> resolves the right dir either way.
pi internals live in the repo under runtime/pi/ — the bridge, pi-run.sh and the lifecycle
extensions — and ship as the pi runtime payload; see
What the .deb installs.