clawseed-gateway — HTTP/WebSocket Gateway¶
Overview¶
clawseed-gateway is built on the Axum framework, providing HTTP/REST and WebSocket endpoints. It serves as the entry point for external clients to interact with the agent. It also handles remote tool bridging — wrapping client-registered tools as RemoteTool instances.
Architecture¶
┌──────────────────────────────────────────────────┐
│ Gateway │
│ │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
│ │ REST API │ │ WebSocket │ │ Static │ │
│ │ (api.rs) │ │ (ws.rs) │ │ Files │ │
│ └─────┬──────┘ └─────┬──────┘ └────────────┘ │
│ │ │ │
│ ┌─────┴───────────────┴──────────────────────┐ │
│ │ Middleware Layer │ │
│ │ CORS · Body limit (64KB) · Timeout (30s) │ │
│ │ Tracing · Rate limiting · Auth │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────┐ │
│ │ Session Storage │ │
│ │ SQLite (session_sqlite.rs) │ │
│ │ In-memory queue (session_queue.rs, backup) │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────┐ │
│ │ Remote Tool Bridge │ │
│ │ RemoteTool (remote_tool.rs) │ │
│ └─────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────┘
Core Modules¶
ws.rs — WebSocket Endpoint¶
The primary communication channel, supporting the following message types:
Each WebSocket connection creates its own Agent via Agent::from_config_with_shared_components(), reusing the shared provider, memory, observer, model, temperature, and BuiltIn tool instances from AppState. Per-connection components (hooks, dispatcher, skill index) are still created fresh; BuiltIn tools reuse shared Arc<dyn Tool> instances registered via register_all_arc(). See Architecture Overview for the runtime init chain.
Client → Server:
- {"type": "message", "content": "..."} — Send a chat message
- {"type": "register_tools", "tools": [...]} — Register client tools
- {"type": "tool_result", "call_id": "...", "output": "..."} — Return tool execution result
- {"type": "tool_error", "call_id": "...", "error": "..."} — Return tool execution error
Server → Client:
- session_start — Session started
- chunk — Streaming text chunk
- thinking — Agent thinking process
- tool_call — Tool call notification
- tool_call_request — Request client to execute a remote tool
- done — Turn completed
- result_acknowledged — Result received acknowledgment
- aborted — Turn aborted
- error — Error notification
api.rs — REST Endpoints¶
System¶
GET /health— Health checkGET /api/doctor— System diagnostics (tool count, memory health, etc.)GET /api/cost— Token cost metrics
Tools & Skills¶
GET /api/tools— List registered tools (viatool_registry.tool_specs())GET /api/cli-tools— List available CLI toolsPOST /api/skills/reload— Re-read skill index from disk without restarting (returns{ ok, skills_count })
Sessions¶
GET /api/sessions— List all sessionsGET /api/sessions/running— Get running sessionsGET /api/sessions/{id}/messages— Get session messagesGET /api/sessions/{id}/state— Get session statePUT /api/sessions/{id}— Rename sessionDELETE /api/sessions/{id}— Delete sessionPOST /api/sessions/{id}/abort— Abort running session
Memory¶
GET /api/memory— List memoriesPOST /api/memory— Store new memoryDELETE /api/memory/{key}— Delete memory
User Profile¶
GET /api/users/me/profile— Get the authenticated local user's profilePOST /api/users/me/profile— Create or replace a profile keyPATCH /api/users/me/profile/items/{id}— Update a profile item or setstatustorejectedDELETE /api/users/me/profile/items/{id}— Delete a profile itemDELETE /api/users/me/profile— Delete all profile itemsPUT /api/users/me/profile/import— Atomically import profile items withreplace,merge, orappend
The current local gateway maps authenticated connections to the stable owner
principal. Session ownership is bound on first use and cannot be reassigned.
Rejecting an inferred item preserves its provenance and prevents automatic inference
from replacing the same key. Editing an item makes it explicit and active.
Imported items use the imported source while retaining their confidence, status,
evidence session, and expiration metadata.
Cron Jobs¶
GET /api/cron— List jobsPOST /api/cron— Add jobPATCH /api/cron/{id}— Update jobDELETE /api/cron/{id}— Delete jobGET /api/cron/{id}/runs— Job execution historyGET /api/cron/settings— Cron settingsPATCH /api/cron/settings— Update cron settings
Personality & Configuration¶
GET /api/personality— Read personality files (SOUL.md, etc.) from workspacePUT /api/personality— Write personality files (allowlist-validated)GET /api/config— Get TOML configurationPUT /api/config— Update configuration (returns warning: provider/model/memory changes require gateway restart)GET /api/provider/models— Proxy fetch available models using configured API key
Webhook¶
POST /webhook— Webhook ingestion (persists messages to session store, returns session_id)
remote_tool.rs — Remote Tool Bridge¶
Wraps client-registered tools as RemoteTool, implementing the Tool trait. Remote tools follow a three-step registration flow:
- Register to shared registry —
state.tool_registry.register_or_replace(tool, ToolSource::Remote { session })so/api/toolsreflects the tool globally - Inject into per-connection Agent —
agent.add_remote_tools(tools, session)before processing each message - Cleanup on disconnect —
state.tool_registry.unregister_by_source(&ToolSource::Remote { session })
This means the shared registry (AppState.tool_registry) and each agent's private registry (Agent.tool_registry) are separate instances. See the "Dual Tool Registry" section in Architecture Overview for implications.
impl Tool for RemoteTool {
fn name(&self) -> &str { &self.spec.name }
fn description(&self) -> &str { &self.spec.description }
fn parameters_schema(&self) -> Value { self.spec.parameters.clone() }
async fn execute(&self, args: Value, _ctx: &dyn ToolContext) -> Result<ToolResult> {
// 1. Generate call_id
// 2. Send tool_call_request to client
// 3. Wait for tool_result or tool_error (30s timeout)
// 4. Return result
}
}
Note: Remote tools do not use ToolContext (no access to server-side memory, security policy, etc.).
Session Management¶
session_backend.rs—SessionBackendtraitsession_sqlite.rs— SQLite persistence backend (default)session_queue.rs— In-memory queue backend (fallback)
Security and Rate Limiting¶
auth_rate_limit.rs— Sliding window rate limiting (per IP/token)tls.rs— TLS/HTTPS support
Static Files¶
static_files.rs— Static asset serving
Configuration Constants¶
| Constant | Value | Description |
|---|---|---|
MAX_BODY_SIZE |
64KB | Request body size limit |
REQUEST_TIMEOUT_SECS |
30 | Request timeout (overridable via CLAWSEED_GATEWAY_TIMEOUT_SECS env var; Android default: 300s) |
REMOTE_TOOL_TIMEOUT |
30s | Remote tool execution timeout |