Agent Gateway¶
The Agent Gateway is self-host only. It runs inside your appliance, where agent frameworks on your machine can reach it. The Second Brain MCP server is not limited to the appliance any more: cloud serves 37 tools in single-key mode (v2.49.0), while named per-agent keys and the full 42-tool lane remain appliance surfaces.
The Agent Gateway connects external AI agent frameworks to Glassy, letting you dispatch tasks and share MCP tools from one central workspace.
Overview¶
The Agent Gateway provides a pluggable adapter system that bridges Glassy with local and cloud-based AI agent frameworks. Each adapter implements a common interface (getStatus, sendTask, getSessions, getConfigSnippet, healthCheck) so you can manage all your agents from a single UI.
Supported Frameworks¶
| Framework | Type | Default Endpoint | Session Continuity |
|---|---|---|---|
| OpenClaw | Local | http://127.0.0.1:18789 |
user field in chat completions |
| Hermes | Local | http://127.0.0.1:8642 |
X-Hermes-Session-Key header |
| Antigravity | Cloud | Google Gemini API | Stateless — dispatch returns sessionId: null |
Enabling the Agent Gateway¶
The Agent Gateway is behind a feature flag and disabled by default.
Server-side¶
Set in your .env:
Client-side¶
Set in your .env:
Both flags must be enabled for full functionality. The server flag mounts the API routes at /api/agents; the client flag shows the sidebar item and settings section.
Using the Agent Gateway¶
Adding an Agent Connection¶
- Navigate to Settings → Agent connections (or click Add Agent in the Agent Gateway view).
- Select the framework type (OpenClaw, Hermes, or Antigravity).
- Enter a label for the connection.
- For local agents (OpenClaw, Hermes), enter the base URL (defaults are pre-filled).
- For Antigravity, enter your Google API key.
- Optionally provide a bearer token for authentication.
- Click Add Connection.
The gateway will automatically detect if the framework is running on your machine.
Dispatching Tasks¶
- Open the Agent Gateway from the sidebar.
- Click Dispatch on any connected agent card.
- Type your task in the dispatch panel (up to 10,000 characters).
- Press Ctrl+Enter (or Cmd+Enter on macOS) to dispatch, or click the Dispatch button.
- The response will appear in the panel and be logged to the activity feed.
Viewing Activity¶
The activity feed at the bottom of the Agent Gateway view shows recent dispatches, errors, and connection events. You can filter by action type and load more entries with pagination.
MCP Config Snippets¶
Each agent connection can generate an MCP config snippet that configures the agent to use Glassy's MCP server. Click MCP Config on any agent row in Settings to view and copy the snippet.
The snippet includes:
- MCP server URL and authentication header
- Tool filter (where supported) to limit which Glassy tools the agent can access
- Framework-specific settings (e.g., enabling the chat completions endpoint for OpenClaw, API server for Hermes)
Event-Triggered Dispatch (Calendar)¶
v2.36.0-beta.22+ — calendar events can now start agent tasks on their own. Open any event in the Today calendar cockpit and add a "when this event starts, run…" agent task (validated against the same rules as manual dispatch, up to 10,000 characters). A minute-tick cron fires due payloads through your connected agent:
- At-most-once delivery — every dispatch is written to the
agent_dispatch_logledger before the task is sent, so server restarts never double-fire an event. - Flag-gated — set
ENABLE_CALENDAR_AUTOMATION=true(plusENABLE_AGENT_GATEWAY=true) and restart. Off by default; the calendar is fully functional without it. - Results in the activity feed — dispatch outcomes land in the same Agent Gateway activity feed as manual dispatches.
- Rules can fire too — GlassyKeep rules support
on_due/on_overduetriggers withdispatch_agent,create_event, andpush_reminderactions, deduplicated through the same ledger.
See the Calendar page for the full workflow.
Security¶
- SSRF Protection: agent URLs are validated per surface. On the cloud, a strict localhost allowlist applies (
localhost,127.0.0.1,::1,host.docker.internal) and external URLs are rejected. On a self-hosted appliance (beta.40+), LAN and Tailscale addresses are also allowed (http://192.168.x.x:8642,http://box.tailnet.ts.net:8642) — you own the network the appliance runs on, so pointing an agent at another machine on it is the normal case. - CLI Safety: Hermes CLI fallback uses
execFilewith an args array (notexec), preventing command injection. - Rate Limiting: 30 dispatches per minute, 12 status polls per minute per user.
- Activity Logging: All dispatches and errors are logged to the
agent_activitytable with 30-day retention. MCP keys and auth tokens are never logged. - Token Storage: Config tokens are stored locally in the Glassy database. For Clear (self-hosted) instances, this is on your own machine.
- User Isolation: On hosted (multi-user) instances, all agent connections are scoped by
user_id. Users can only see, edit, delete, or dispatch to their own agents. Activity logs are scoped via JOIN onagent_connections.user_id. - SaaS Restrictions: On SaaS instances, local-only agent frameworks (OpenClaw, Hermes) are hidden from the framework selector. Only Antigravity (cloud, Google Gemini API) is available. The agent discovery banner is suppressed. Ollama "local" connection type is also hidden — only "cloud" (ollama.com) is offered.
API Reference¶
All endpoints are mounted at /api/agents and require authentication.
| Method | Path | Description |
|---|---|---|
GET |
/api/agents |
List all agent connections with status |
POST |
/api/agents |
Create a new agent connection |
GET |
/api/agents/:id |
Get single agent status |
PUT |
/api/agents/:id |
Update an agent connection |
DELETE |
/api/agents/:id |
Delete an agent connection |
POST |
/api/agents/:id/task |
Dispatch a task to an agent |
GET |
/api/agents/:id/sessions |
List agent sessions |
GET |
/api/agents/:id/config |
Get MCP config snippet |
GET |
/api/agents/activity |
List recent activity |
GET |
/api/agents/discover |
Discover local agent frameworks |
Dispatching a task over the API¶
POST /api/agents/:id/task with a body whose key is task, not prompt. The task is capped
at 10,000 characters.
curl -sX POST http://localhost:8080/api/agents/<connection-id>/task \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"task": "Summarise what changed in the vault today"}'
{ "success": true,
"response": "…the model's actual answer…",
"sessionId": "glassy_1790988394714",
"resumeId": "hres-…",
"metadata": { "completionId": "chatcmpl-…", "model": "…", "usage": { "total_tokens": 1234 } } }
The session contract, as a rule. sessionId is the session key: pass it back as
{"task":"…","options":{"sessionId":"<that value>"}} to continue the same conversation. It is
never the provider's per-call id — that is metadata.completionId. A transport with no sessions
(Antigravity/Gemini) returns sessionId: null rather than a value that implies resumability.
resumeId is a separate resume handle when the gateway has one. On Hermes, the gateway has
two headers: X-Hermes-Session-Key (long-term memory scope — this is what sessionId carries)
and X-Hermes-Session-Id (actual conversation history, returned in the response header). The
adapter reads that header into resumeId, and you pass it back as
{"task":"…","options":{"sessionId":"…","resumeId":"<that value>"}}. Passing back only the key
resumes nothing and lets memory accumulate under the key (a field measurement saw 5.3× cost at
turn two); forwarding the id is flat at 1.0×. OpenClaw and Antigravity return resumeId: null —
OpenClaw resumes on the sessionId it already carries (the user field), and Antigravity has no
sessions.
Why that distinction is spelled out
Before v2.41.0 this field carried the provider's completion id instead of the key. Passing it back therefore handed the gateway a key it had never issued, so every turn started a fresh session and re-seeded the agent's full system prompt — which is why multi-turn dispatch looked stateless and expensive, and why a filed report of "dispatch re-pays its context every turn" could not be reproduced as anything else. The observation was right; the handle was wrong.
Optional options. The recognized keys are timeout (positive milliseconds, capped at 10
minutes), model, sessionId, and resumeId. Anything else — including a timeout of "30s", which used
to coerce to an immediate abort — comes back in warnings[] naming the key and the reason, and
the dispatch still runs:
{ "success": true, "sessionId": "glassy_1790988394714",
"warnings": [ { "code": "IGNORED_OPTION",
"message": "\"timeout\" must be a positive number of milliseconds" } ] }
Nothing is dropped silently, so a dispatch that ignored part of your input says so instead of behaving in a way you have to explain later.
The record of every dispatch lives at GET /api/agents/activity (action, task_text,
response_text, timestamp) and in the panel's activity feed. A dispatch that "did nothing" is
usually visible there as an error row carrying the upstream message — check that before
concluding the connection is wrong.
Agent-as-vault-provider (no-Obsidian self-host)¶
On a self-host, an operator can declare one Agent Gateway connection the vault provider by
setting vaultProvider: true in that connection's config. Then glassy_vault_read and
glassy_vault_append dispatch to that agent — which holds the filesystem — instead of needing the
Obsidian stack, with a deterministic [glassy-vault-provider] instruction and the agent's reply
mapped back (file contents on read, NOT_FOUND → 404, OK/error on write). glassy_obsidian_proxy
still requires the full Obsidian stack and is not routed through the provider. The capability is
advertised as agentIdentity.agentVaultProvider in GET /api/capabilities, so an agent learns the
lane exists rather than improvising an MCP shim behind obsidian_url.
Troubleshooting¶
Agent shows "Offline"¶
- Ensure the agent framework is running on your machine.
- Check that the base URL is correct (localhost on cloud; on a self-hosted appliance, localhost or any LAN/Tailscale address — beta.40+).
- Verify any required authentication tokens are set.
Agent shows "Setup needed"¶
- OpenClaw: Enable the chat completions endpoint in
openclaw.json:gateway.http.endpoints.chatCompletions.enabled: true - Hermes: Enable the API server by setting
API_SERVER_ENABLED=truein your Hermes.envfile. Without the API server, tasks will fall back to the Hermes CLI.
"Hermes CLI not found"¶
Install the Hermes CLI tool or enable the Hermes API server for task dispatch.
MCP key not found¶
Generate an MCP key in Settings → Knowledge Base → MCP Server before configuring agents. The MCP key is required for agents to access Glassy tools.