ControlCenter
REST API for querying agent fleet status.
Provides the initial data load for the Command Hub,
while real-time updates flow through the AgentStatus SignalR hub.
API contract for Rex (Frontend):
- GET /api/agents — Returns all known agents with current status
- GET /api/agents/{agentId} — Returns a specific agent's status
Gets the current fleet status — all known agents with their latest state.
This is the initial load endpoint; subsequent updates arrive via SignalR.
An array of agent card data for the entire fleet.
Returns the fleet snapshot.
Gets the current status of a specific agent.
The agent identifier, e.g. "otto", "dex".
The agent's current card data.
Returns the agent's status.
Agent not found in the fleet state.
REST API for sending control commands to agents.
Provides the Command Hub's action endpoints for agent lifecycle control.
API contract for Rex (Frontend):
- POST /api/command/stop/{agentId} — Stop/abort an agent's active session
- POST /api/command/restart/{agentId} — Restart an agent
- POST /api/command/steer/{agentId} — Inject a message into an agent's session
Commands are forwarded to the OpenClaw Gateway via the
WebSocket bridge service. The Gateway handles the actual execution.
Stops (aborts) an agent's active session.
Sends an abort command to the OpenClaw Gateway.
The agent identifier to stop.
Confirmation of the stop command.
Stop command sent successfully.
No active session found for the agent.
Restarts an agent by aborting the current session and allowing
a new one to start on the next incoming message.
The agent identifier to restart.
Confirmation of the restart command.
Restart command sent successfully.
Steers (injects a message into) an agent's active session.
Used by operators to redirect an agent's task mid-execution.
The agent identifier to steer.
The steering message to inject.
Confirmation of the steer command.
Steer command sent successfully.
Missing or empty message.
Request body for the steer command.
The message to inject into the agent's session.
Request body for the steer command.
The message to inject into the agent's session.
The message to inject into the agent's session.
REST API for querying agent session logs.
Provides historical message and tool call logs for a specific agent.
API contract for Rex (Frontend):
- GET /api/logs/{agentId} — Returns recent logs for an agent
- GET /api/logs/{agentId}/tools — Returns recent tool calls for an agent
Log data is sourced from the OpenClaw Gateway's transcript files.
The Gateway's logs.tail RPC provides the raw data, and this
controller formats it for the frontend.
Gets recent session logs for a specific agent.
Returns the last N messages from the agent's active session transcript.
The agent identifier, e.g. "otto", "dex".
Maximum number of log entries to return (default: 50, max: 200).
An array of log entries for the agent.
Returns the agent's recent logs.
No active session found for the agent.
Gets recent tool call logs for a specific agent.
Returns the last N tool invocations from the agent's session.
The agent identifier.
Maximum number of tool entries to return (default: 20, max: 100).
An array of tool call entries for the agent.
Returns the agent's recent tool calls.
No active session found for the agent.
SignalR hub for real-time agent status updates in the Command Hub.
Usage flow:
- Client connects to /hubs/agent-status
- Client calls to subscribe to all agent updates
- Client calls to subscribe to a specific agent
- Server pushes
and events
- Client calls for initial state on connect
Group naming:
- Fleet group: fleet — receives all agent updates
- Agent group: agent:{agentId} — receives updates for one agent
Typed client: — all server-to-client
calls go through this interface for compile-time safety.
Architecture note: This hub bridges OpenClaw Gateway WebSocket events
to SignalR clients. A background service ()
subscribes to Gateway events and pushes them through this hub's extension methods.
Adds the calling connection to the fleet group.
Once joined, the client will receive all agent status changes
and task progress updates across the entire fleet.
Removes the calling connection from the fleet group.
Adds the calling connection to a specific agent's group.
Once joined, the client will receive updates only for that agent.
The agent identifier, e.g. "otto", "dex".
Thrown if agentId is null or empty.
Removes the calling connection from a specific agent's group.
The agent identifier.
Returns a snapshot of the current fleet state.
Called by clients on initial connection to get the full picture
before incremental updates begin arriving.
An array of representing all known agents.
Overrides to perform cleanup.
SignalR automatically removes disconnected connections from all groups.
Exception that caused the disconnection, if any.
The SignalR group name for the entire fleet (all agents).
Returns the SignalR group name for a specific agent.
Format: agent:{agentId} (lowercase for consistency).
The agent identifier.
Extension methods for pushing real-time agent updates through
the of .
These methods are intended to be called from background services
(e.g., ) or other
server-side code that detects an agent state change.
Pushes an agent status change to all clients subscribed to
the fleet group and the specific agent's group.
Call this from any background service when an agent's
operational status changes (e.g., the Gateway reports a
session transition from "running" to "done").
The hub context injected via DI.
The agent status update payload.
A Task that completes when the message has been sent to all group members.
Pushes a task progress update to all clients subscribed to
the fleet group and the specific agent's group.
The hub context injected via DI.
The task progress update payload.
A Task that completes when the message has been sent to all group members.
Strongly-typed client interface for the AgentStatus SignalR hub.
Defines the methods the server can invoke on connected clients
to push real-time agent status and task progress updates.
All server-to-client calls go through this interface for
compile-time safety — matching the pattern used by the
Extrudex PrinterHub.
Pushes an agent status change to all subscribed clients.
Fired whenever an agent's operational status changes
(e.g., idle → active, active → thinking, active → error).
The full status update payload.
A Task that completes when the client has processed the update.
Pushes a task progress update to all subscribed clients.
Fired when an agent reports progress on its current task.
The task progress update payload.
A Task that completes when the client has processed the update.
Agent operational status derived from OpenClaw Gateway session activity.
Maps to the frontend AgentStatus type: 'active' | 'idle' | 'thinking' | 'error'.
Agent is currently processing a turn.
Agent completed its last turn; no active work.
LLM call in flight; tokens streaming.
Agent encountered an unhandled error.
Extended lifecycle status including offline — not all agents have active sessions.
Used internally; clients only see (offline maps to idle).
Pushed to SignalR clients when an agent's status changes.
Matches the TypeScript AgentStatusUpdate interface from the design spec.
Agent identifier, e.g. "otto", "dex".
Human-readable name, e.g. "Otto".
Role description, e.g. "Orchestrator Agent".
Current operational status.
Description of the current task, if any.
Full session key, e.g. "agent:otto:telegram:direct:8787451565".
Channel the agent is operating on, e.g. "telegram".
ISO 8601 timestamp of last activity.
Error message when status is 'error'.
Pushed to SignalR clients when an agent's status changes.
Matches the TypeScript AgentStatusUpdate interface from the design spec.
Agent identifier, e.g. "otto", "dex".
Human-readable name, e.g. "Otto".
Role description, e.g. "Orchestrator Agent".
Current operational status.
Description of the current task, if any.
Full session key, e.g. "agent:otto:telegram:direct:8787451565".
Channel the agent is operating on, e.g. "telegram".
ISO 8601 timestamp of last activity.
Error message when status is 'error'.
Agent identifier, e.g. "otto", "dex".
Human-readable name, e.g. "Otto".
Role description, e.g. "Orchestrator Agent".
Current operational status.
Description of the current task, if any.
Full session key, e.g. "agent:otto:telegram:direct:8787451565".
Channel the agent is operating on, e.g. "telegram".
ISO 8601 timestamp of last activity.
Error message when status is 'error'.
Pushed to SignalR clients when an agent's task progress updates.
Matches the TypeScript TaskProgressUpdate interface from the design spec.
Agent identifier.
Description of the current task.
Task progress percentage (0–100), if trackable.
Elapsed time string, e.g. "04m 12s".
Pushed to SignalR clients when an agent's task progress updates.
Matches the TypeScript TaskProgressUpdate interface from the design spec.
Agent identifier.
Description of the current task.
Task progress percentage (0–100), if trackable.
Elapsed time string, e.g. "04m 12s".
Agent identifier.
Description of the current task.
Task progress percentage (0–100), if trackable.
Elapsed time string, e.g. "04m 12s".
Snapshot of an agent's full card data, sent on initial connection
or when the fleet state is requested.
Matches the TypeScript AgentCardData interface from the design spec.
Snapshot of an agent's full card data, sent on initial connection
or when the fleet state is requested.
Matches the TypeScript AgentCardData interface from the design spec.
Background service that connects to the OpenClaw Gateway WebSocket
and bridges Gateway events to the .
Architecture:
- Connects to the Gateway WS endpoint (configurable via appsettings)
- Handles the v3 protocol handshake (challenge → connect → hello-ok)
- Subscribes to sessions.changed and related events
- Translates session state changes into
and objects
- Pushes updates through the SignalR hub
This is the server-side bridge that allows Angular clients to
receive real-time updates via SignalR instead of connecting directly
to the Gateway WebSocket.
In-memory fleet state — maps agent IDs to their latest card data.
Updated on every sessions.changed event from the Gateway.
Known agent roles for display in the Command Hub.
Maps agent IDs to their functional descriptions.
Maps OpenClaw session status to .
Returns the current fleet state snapshot.
Used by the hub's GetFleetSnapshot method and by the
AgentsController REST endpoint.
Connects to the OpenClaw Gateway WebSocket and processes events
until the connection is lost or cancellation is requested.
Receives and processes WebSocket messages from the Gateway.
Handles the v3 protocol handshake and dispatches events.
Processes a single WebSocket message from the Gateway.
Routes based on the message type: event, response, or challenge.
Handles the Gateway connect.challenge event by sending
a connect request with authentication credentials.
Handles a Gateway event message by dispatching to the
appropriate handler based on event name.
Handles a sessions.changed event from the Gateway.
Updates the fleet state and pushes status changes through SignalR.
Handles a session.message event. Updates the agent's last activity
and pushes a status update if the status changed.
Handles a session.tool event. Extracts tool progress information
and pushes a through SignalR.
Handles a health event from the Gateway.
Logs the health status for diagnostics.
Handles a Gateway response message. Currently only logs for diagnostics.
Converts a raw Gateway session JSON element into an
record.
Extracts the agent ID from a session key.
Session key format: "agent:{agentId}:{channel}:..."
Extracts the channel from a session element.