Skip to main content
Glama

register_agent

Registers this terminal as a named agent so other agents can address it, send messages, assign tasks, or join channels; call first in any messaging 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

NameRequiredDescriptionDefault
nameYesHuman-readable agent name — [A-Za-z0-9_.-]{1,64} (ASCII only)
roleYesAgent role (e.g. orchestrator, builder, ops)
classNoADR-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'.
forceNoADR-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_idNoTether 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`).
managedNov2.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_pidNov2.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_tokenNoYour agent token (from register_agent response). Optional here — also resolvable from RELAY_AGENT_TOKEN env or X-Agent-Token header.
cli_profileNoWhich 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.
descriptionNov2.0: optional human-readable description (max 512 chars). Shown in discover_agents + dashboard. Mutable on re-register — if omitted, previous value preserved.
capabilitiesYesList of capabilities
recovery_tokenNov2.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_startNov2.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_pidsNoTether 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).
on_name_collisionNov2.26: behavior when the requested `name` is ACTIVELY HELD by another live session (same active-held test as NAME_COLLISION_ACTIVE). "reject" (default) = today's behavior exactly: fail with NAME_COLLISION_ACTIVE. "suffix" = instead register under a relay-assigned instance name "<name>-N" (lowest free N≥2 in [A-Za-z0-9_.-], reusing an offline+drained slot when safe, never inheriting mail) and return it as `assigned_name` in the response. Use for several CLIs sharing ONE agent definition that all register the same name. ⚠ The suffixed name is NOT stable across restarts — it is assigned by registration order/occupancy; do NOT hard-code it, re-discover via discover_agents each session. Does NOT apply to force takeovers (force+expected_session_id still wins). For a FIXED per-instance identity, register with a distinct stable name instead (e.g. "<name>-worker1").reject
terminal_title_refNov2.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_idNoADR-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.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • addedInput schema / properties / on_name_collision
      Added value: +{
      +  "default": "reject",
      +  "description": "v2.26: behavior when the requested `name` is ACTIVELY HELD by another live session (same active-held test as NAME_COLLISION_ACTIVE). \"reject\" (default) = today's behavior exactly: fail with NAME_COLLISION_ACTIVE. \"suffix\" = instead register under a relay-assigned instance name \"<name>-N\" (lowest free N≥2 in [A-Za-z0-9_.-], reusing an offline+drained slot when safe, never inheriting mail) and return it as `assigned_name` in the response. Use for several CLIs sharing ONE agent definition that all register the same name. ⚠ The suffixed name is NOT stable across restarts — it is assigned by registration order/occupancy; do NOT hard-code it, re-discover via discover_agents each session. Does NOT apply to force takeovers (force+expected_session_id still wins). For a FIXED per-instance identity, register with a distinct stable name instead (e.g. \"<name>-worker1\").",
      +  "enum": [
      +    "reject",
      +    "suffix"
      +  ],
      +  "type": "string"
      +}
  2. First observed

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full behavioral burden and does so richly: idempotent upsert, token minted once and preserved on re-register unless recovery_token is presented, immutable capabilities, CAS-based force takeover, and rate limiting. Errors are enumerated with codes and their triggering conditions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the purpose, then clearly sectioned into When to use / Behavior / Returns / Errors, which is appropriate for a 17-parameter tool. It has minor redundancy (the 'agent_token shown ONCE — store in RELAY_AGENT_TOKEN' warning appears in both Behavior and Returns), keeping it just below the top score.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 17-parameter, no-annotation, no-output-schema tool, the description fully compensates by documenting the return shape, the one-time token, conditional fields (capabilities_note, auto_assigned_tasks, recovery_completed), and the full error set. An agent has everything needed to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds lifecycle meaning beyond the schema: it explains that the returned agent_token must be stored in RELAY_AGENT_TOKEN, that recovery_token drives the v2 recovery flow, and that capabilities are immutable on re-register. This is genuine value beyond the field-level docs.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Register this terminal as a named agent') plus the downstream benefit ('so other agents can address it'). It is clearly distinguishable from siblings like unregister_agent, abandon_registration, and discover_agents.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says when to call it ('first thing in any session that needs to send/receive messages, post tasks, or join channels') and notes the SessionStart hook usually handles it. It also routes capability changes to `expand_capabilities`. It stops short of an explicit 'do not call this when...' exclusion (e.g., pointing at rotate_token for token refresh), but the guidance is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.