Skip to content
Work in progresspre-register via email

Coding agents

A coding agent works with the hub under its own key, never under yours. The hub knows from the key that the caller is an agent and holds it to a fixed ceiling, whatever role the device has.

  • With pbx in agent mode: the agent runs pbx --agent claude-code …, or pbx with PBX_AGENT=claude-code in its environment. pbx signs each request with the device’s agent key of that integration (below).
  • Through ownpaas’s MCP server (ownpaas-mcp) on your Mac (ownpaas is a separate product, not released yet): the agent calls the hub’s tools (list_servers, get_status, create_twin, list_twins, reset_twin_data, delete_twin, get_evidence, request_access, list_releases). ownpaas signs each call with an agent key registered for that agent integration (Claude Code, Cursor, Codex) on that device. No key is in the agent’s configuration.
  • With an API key of kind agent, for scripts and CI: read, twins:write and access:developer at most. The key is shown once; the hub stores only a hash.
Terminal window
pbx --agent claude-code twin create --production shop --task fix-42
PBX_AGENT=claude-code pbx twin list
  • The key. Each device has one agent key per integration (P-256, no user presence). The hub takes the principal agent from the key, not from anything the request says.
  • First use registers it. The first agent-mode run on a device creates the agent key and registers it with the hub, signed with the device’s own key: a presence device asks its person once (Touch ID, a PIN). After that the agent key signs without anyone. pbx agent register claude-code does the same ahead of time, so the prompt does not arrive in the middle of an agent’s run.
  • A revocation stays. After pbx agent revoke claude-code (or an owner’s revocation), the agent’s requests fail with the hint that a person registers the key again. pbx does not register it again on its own.
  • No fallback to your key. With PBX_AGENT set, what only a person signs is refused before anything is signed: pbx open, pbx approve, pairing, pbx agent register and pbx agent revoke. Set PBX_AGENT in the agent’s environment (its shell profile, the MCP server’s configuration), not only --agent on its command lines.
  • The answers. Allowed requests exit 0. Requests above the ceiling exit 4 with the hub’s refusal. Requests a person must approve exit 5 with the approval’s id and the pbx approve line to run; with --output json the approval is on stdout. Destructive commands take --confirm NAME, never --yes, so an agent can call them without a terminal; the hub still decides.
  • The session. The audit names the integration and the session: PBX_AGENT_SESSION, else one per pbx run.

The limit. On a device whose signing key opens without a person (passphrase-stored, tpm, tang), a process of the same user can read what pbx reads and sign as the device. Agent mode keeps an agent that follows the rules to its ceiling; only a presence device’s signing key keeps one that does not. The boundary is the hub’s ceiling and its approvals, not the client.

Agent
Read hosts, twins, releases, evidenceallowed
Create, reset and delete twinsallowed
SSH and podman --remote access on a twinallowed
Delete a production or staging host, promote a release, operate login or admin access on productionasks; a person approves
Admin access on a twin, keys, devices, settingsrefused
A twin with a copy of production’s dataasks; a person approves

An agent’s request that needs a person waits as pending. A person approves it from a paired device of level presence, with the host’s name typed: pbx approvals lists them, pbx approve <id> signs the approval with the device’s key. The hub then runs the recorded request once. No tool approves, and an agent key never can. The hub’s portal shows approvals but cannot decide them, because a browser holds no signing key.

Every line names the principal (person, agent or CI), the device, the key and, for an agent, its integration and session. An approved operation names who asked and who approved.