register_agent
Register this terminal as a named agent so other agents can message it, post tasks, or join channels. Idempotent upsert; call first in any session.
Instructions
Register this terminal as a named agent so other agents can address it.
When to use: call this first thing in any session that needs to send/receive messages, post tasks, or join channels. Idempotent upsert, safe to call again on reconnect. The SessionStart hook (hooks/check-relay.sh) typically calls it for you.
Behavior: creates or updates the agent row keyed by name. First registration mints a fresh agent_token (returned ONCE, store it in RELAY_AGENT_TOKEN). Re-registering preserves the existing token unless recovery_token is presented (v2.1 Phase 4b.1 v2 recovery flow). Capabilities are immutable on re-register (v1.7.1), use expand_capabilities for additive changes.
Returns: { success: true, agent: AgentWithStatus, protocol_version, message }. First-time registration also includes agent_token (shown ONCE — store in RELAY_AGENT_TOKEN) and auth_note. If the request asked for capabilities that differ from the stored set, capabilities_note explains the immutability. If queued auto-routed tasks were assigned at register time, auto_assigned_tasks: { task_id, title, priority }[] lists them. Successful recovery flow includes recovery_completed: true.
Errors: AUTH_FAILED (recovery_pending row presented without recovery_token), RECOVERY_REQUIRED (token rejected, present recovery_token), INVALID_INPUT (name/role/capabilities malformed), RATE_LIMITED.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Human-readable agent name — [A-Za-z0-9_.-]{1,64} (ASCII only) | |
| role | Yes | Agent role (e.g. orchestrator, builder, ops) | |
| class | No | ADR-0002 (v2.21.0): the agent's COARSE coordination posture — one of orchestrator | builder | advisory | auditor | transient (SSOT: src/agent-class.ts). Self-declared; IMMUTABLE after first registration (same rule as managed/host_id). Orthogonal to `role` (free-text label) and `capabilities` (what it does). Omit → `unclassified`; surfaced in discover_agents view='topology'. | |
| force | No | ADR-0012: request a CAS TAKEOVER of an actively-held name (NOT an unconditional bypass). MUST be accompanied by expected_session_id (the session_id you READ from the row; null = expect an offline row). The takeover is an atomic compare-and-swap on that session_id — exactly one of two racing relaunches wins; the loser gets FORCE_PRECONDITION_FAILED and re-reads (never retry-force). Default false rejects re-registration on an actively-held name with NAME_COLLISION_ACTIVE. Set true only when the prior session is unreachable (crashed/relaunched terminal); a live concurrent terminal still wins the CAS and you correctly lose. | |
| host_id | No | Tether v0.3 PID-handshake (schema v16): stable OS machine GUID (macOS IOPlatformUUID / Linux /etc/machine-id / Windows MachineGuid). Host-scopes the PID match so equal PIDs on different hosts never false-match (federation-safe). Immutable after first registration (same rule as `managed`). | |
| managed | No | v2.1 Phase 4b.2: true = agent is a Managed Agent wrapper that can parse push-token messages + self-update its local config on rotation. false (default) = Claude Code terminal or equivalent (restart-required on rotation). Immutable after first registration — change requires unregister + fresh register. | |
| agent_pid | No | v2.13.0 presence liveness: the agent's OWN process id (this CLI/wrapper's PID). Lets the relay confirm the agent is alive-and-idle via a same-host probe instead of misreading idle silence as closed. Self-reported by managed/script agents; stdio MCP agents have it captured automatically by the relay stdio server. Host-scoped by host_id; cleared on close. Omit if unknown → age-based presence (unchanged). | |
| agent_token | No | Your agent token (from register_agent response). Optional here — also resolvable from RELAY_AGENT_TOKEN env or X-Agent-Token header. | |
| cli_profile | No | Which agent-CLI this session runs under (e.g. "claude", "codex"). Set by the SessionStart hook; VALIDATED against the agent-CLI profile registry and stored as NULL when unrecognised — never defaulted, because a wrong default would make the verdict-absence check fire on healthy agents. Enables the server to know whether this agent OWES a session-start verdict. | |
| description | No | v2.0: optional human-readable description (max 512 chars). Shown in discover_agents + dashboard. Mutable on re-register — if omitted, previous value preserved. | |
| capabilities | Yes | List of capabilities | |
| recovery_token | No | v2.1 Phase 4b.1 v2: required when re-registering an agent whose auth_state is 'recovery_pending'. Obtained from the revoker's revoke_token response (shown ONCE) and handed off to the operator out-of-band. | |
| agent_pid_start | No | v2.13.0 presence liveness: an opaque start-time token for agent_pid (e.g. the process start clock time) used as a PID-reuse guard — a recycled PID with a different start-time reads dead. Optional; omit if unavailable. | |
| host_shell_pids | No | Tether v0.3 PID-handshake (schema v16): the agent's process-ancestry PID chain (own PID → … → init/launchd). Tether reads vscode.Terminal.processId for each terminal and intersects with this chain (host-scoped by host_id) to bind a terminal to this agent — no manual naming. Mutable on re-register: OVERWRITES the stored chain (replaces, not appends). Writing it under an existing name requires that name's token (same auth as any re-register). | |
| terminal_title_ref | No | v2.2.0: window title the agent's terminal was spawned with. Used by the dashboard's click-to-focus driver. Typically equals the agent's `--name`. Mutable on re-register (updates to reflect the current session's title). | |
| expected_session_id | No | ADR-0012 CAS precondition for a force takeover. REQUIRED whenever force=true: the session_id the caller READ from the row it intends to take over (pass null to mean "I expect an OFFLINE row" → CAS matches session_id IS NULL). The re-register lands ONLY if the row's session_id still equals this value, so exactly one of two racing relaunches wins; the loser is rejected with FORCE_PRECONDITION_FAILED and MUST re-read (never retry-force, never come up mute). force=true WITHOUT this field is rejected as malformed — there is NO unconditional-force bypass, which would reopen the lost-update TOCTOU ADR-0012 eliminates. |