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. claude is the default; pi
(earendil-works/pi) is a native, model-agnostic runtime.
# claude (default): subscription login, capabilities wired as MCPs
agentctl agents add alice --channel webview --user-email alice@example.com
# pi: model-agnostic, capabilities wired as CLI tools. --api-key boots immediately:
agentctl agents add bob --runtime pi --channel webview --user-email bob@example.com \
--api-key <key> [--provider groq]
# either runtime on a chat platform instead (see ../guides/channels.md):
agentctl agents add carol --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.
Tools work differently per runtime, and it matters for setup. A claude
agent takes capabilities as MCPs (mcp add, recorded under tools:); a pi
agent takes them as CLI tools on PATH + a SKILL.md (tool add, recorded under
clitools:). Both resolve through the same GitOps overlay. A catalog MCP is usable
from either runtime: for claude you mcp add it; for pi, mcp add (or tool
wrap-mcp) transparently wraps the same MCP as a CLI tool. So "an MCP is available
as a tool" for pi, you just declare it in the runtime's own way.
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) |
CLI tools (tool add, clitools: ledger) |
| A catalog MCP | used directly | auto-wrapped as a CLI tool (mcp add / tool wrap-mcp) |
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 Microsoft Teams: full tenant setup);
subagents are claude-only; for a pi agent, declare capabilities as tools
(though mcp add wraps an MCP for you). 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 under runtime/pi/.