Agent service
Understanding agentd's hub-based architecture for managing AI agent sessions. Use when working with agent sessions, profiles, or the agentd API through the agent-hub.From its SKILL.md
npx -y skills add dokipen/claude-cadence --skill agent-serviceAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
7.1 KB, as published. Nobody here has run it
Filesystem Scope
IMPORTANT: See the Filesystem Scope section in
CLAUDE.md.
Overview
agentd is a service that manages AI agent sessions. It no longer exposes a direct gRPC port. Instead, session management is dispatched through the agent-hub WebSocket reverse connection — agentd connects outbound to the hub and receives JSON-RPC commands over that persistent connection.
This is an internal skill for understanding agentd's architecture and its API surface.
Architecture
┌──────────────────────────────────────┐
Issues UI / ────► agent-hub (4200) │
REST clients │ REST/WebSocket API │
│ dispatches commands to agentd │
└──────────────┬───────────────────────┘
│ WebSocket (outbound from agentd)
▼
┌──────────────────────────────────────┐
│ agentd (host loopback only) │
│ session manager + PTY sessions │
│ JSON-RPC dispatcher │
└──────────────────────────────────────┘
Key points:
- agentd does not listen for inbound connections from external clients
- agentd connects outbound to agent-hub via WebSocket (
hub.urlin config) - Commands arrive as JSON-RPC requests over that WebSocket
- The API surface is defined in
services/agents/internal/hub/dispatch.go
JSON-RPC Methods
The dispatcher handles the following methods (see dispatch.go for full param/result types):
| Method | Description |
|---|---|
createSession | Launch an agent in a new PTY session |
getSession | Get current state of a session (reconciled with PTY process) |
listSessions | List sessions with optional agent_profile, state, and waiting_for_input filters |
destroySession | Kill PTY session, clean up worktree, remove state |
getTerminalEndpoint | Get terminal relay info for a session |
Session States
| State string | Description |
|---|---|
creating | Session is being set up |
running | Agent process is active |
stopped | Agent process has exited |
error | Session encountered an error |
destroying | Session is being torn down |
Session Object Fields
{
"id": "uuid-v4",
"name": "human-readable-name",
"agent_profile": "profile-name",
"state": "running",
"worktree_path": "/var/lib/agentd/worktrees/<id>",
"repo_url": "https://github.com/org/repo.git",
"base_ref": "main",
"created_at": "2025-01-01T00:00:00Z",
"error_message": "",
"agent_pid": 12345,
"websocket_url": "",
"waiting_for_input": false,
"idle_since": null
}
getTerminalEndpoint
Returns either:
{"relay": true}— terminal traffic is relayed through the hub WebSocket (default when noadvertise_addressis configured){"url": "wss://host/ws/terminal/<session-id>"}— direct URL (whenadvertise_addressis set in config)
Session ID Traceability
agentd injects AGENTD_SESSION_ID (the session UUID) into every agent's environment automatically. Combined with --session-id {{.SessionID}} in the profile command template (see config.example.yaml), this makes the Claude Code session ID and the agentd session ID identical — so claude --resume $AGENTD_SESSION_ID reliably resumes the session.
Agents running inside agentd sessions should record $AGENTD_SESSION_ID in ticket comments when transitioning ticket state (IN_PROGRESS and CLOSED). The /lead workflow does this automatically. The expected comment format is:
**Session ID:** `<uuid>` — resume with `/resume <uuid>`
This enables humans and other agents to resume interrupted work. If $AGENTD_SESSION_ID is not set (e.g., running interactively outside agentd), omit the session ID line.
Configuration
agentd connects to agent-hub via a hub: block in ~/.config/agentd/config.yaml:
Note: This path is shown for human reference only. Do not attempt to read, verify, or access
~/.config/agentd/config.yamlor any other home directory path during agent operation — this triggers macOS permission popups. All agentd configuration is managed by the host operator.
hub:
url: "wss://<HUB_URL>/ws/agent" # Replace <HUB_URL> with the hub URL from your agentd configuration
name: "my-machine" # unique identifier for this agentd instance
token_env_var: "HUB_AGENT_TOKEN" # env var holding the hub auth token
reconnect_interval: "5s"
Interacting with Agent Sessions
Session operations go through the agent-hub REST API, not directly to agentd.
Authentication
There are two distinct tokens in this system — use the right one for your context:
HUB_AGENT_TOKEN— used by agentd itself to authenticate its outbound WebSocket connection to the hub. Configured inconfig.yamlunderhub.token_env_var. Only relevant when operating or configuring the agentd daemon.HUB_API_TOKEN— used by REST API callers (agents, humans) to authenticate requests to the agent-hub REST API. Configured in the host operator's.env.devfile. This is the token you need when calling hub endpoints to create sessions, list agents, etc.
Do not read
.env.devprogrammatically — it contains secrets and must not be accessed by agents or scripts.
If $HUB_API_TOKEN is not set in your environment when you need to make hub API calls:
- Ask the user to provide the token, or
- Ask the user to set it in their shell environment (
export HUB_API_TOKEN=...) before running the command
# Replace <HUB_URL> with the hub URL from your agentd configuration
# $HUB_API_TOKEN must be set in your environment (see Authentication section above)
# List all agents registered with the hub
curl -s -H "Authorization: Bearer $HUB_API_TOKEN" \
https://<HUB_URL>/api/v1/agents | jq '.'
# Dispatch a createSession command to a specific agent
curl -s -X POST \
-H "Authorization: Bearer $HUB_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"agent_profile": "code-reviewer", "session_name": "review-pr-42"}' \
https://<HUB_URL>/api/v1/agents/<agent-name>/sessions
# List sessions on an agent
curl -s -H "Authorization: Bearer $HUB_API_TOKEN" \
https://<HUB_URL>/api/v1/agents/<agent-name>/sessions | jq '.'
Error Codes
JSON-RPC errors returned by the dispatcher use these codes:
| Code | Meaning |
|---|---|
| -32000 | Internal error |
| -32001 | Not found |
| -32002 | Already exists |
| -32003 | Invalid argument |
| -32004 | Failed precondition (e.g., destroying a running session without force) |