REST API
Yes, the REST API belongs to seshat-ai, not to the open-source runtime repository alone. It is the HTTP product and integration layer on top of the Seshat Go runtime: users, workspaces, sessions, provider settings, files, corpora, memories, scheduler jobs, audit-aware auth, and two query surfaces, one native and one Anthropic-compatible.
Overview
The REST server is implemented in seshat-ai/cmd/api and seshat-ai/internal/api. The API layer stays thin on purpose: middleware, auth, route registration, JSON bodies, SSE framing, and error mapping live there, while the real business and runtime logic lives in backend domain services and the Seshat SDK adapter.
Use /api/v1/* when you want the full backend semantics. Use /v1/messages when you want Claude-compatible clients to talk to Seshat while the server still executes tools, permissions, memory, and sessions on your behalf.
The Two REST Surfaces
Choose /api/v1/* for product integration, workspace features, or anything Seshat-specific. Choose /v1/messages when you want drop-in Claude-compatible client behavior and do not need the whole native backend contract.
Authentication Model
The native API uses bearer auth for most protected routes, and the backend accepts both JWTs and Seshat API keys with the sk- prefix. The Anthropic-compatible path additionally accepts the native x-api-key header because that is what Claude SDK clients expect.
- POST /api/v1/auth/login and POST /api/v1/auth/register are public entry points.
- Most /api/v1/* routes require Authorization: Bearer ....
- The auth middleware resolves either a JWT principal or an API-key principal depending on the token format.
- Some routes are admin-only through role checks, notably parts of MCP and skill repository management.
curl -X POST http://localhost:8090/api/v1/auth/login -H 'Content-Type: application/json' -d '{
"email": "[email protected]",
"password": "secret"
}'Streaming, Permissions, And SSE
The native stream endpoint is POST /api/v1/query/stream. It returns Server-Sent Events and stays open across long-running agent turns. The API sets X-SSE-Version: 1, sends keepalive comments, and emits structured runtime events alongside text chunks.
| SSE Event | Payload | Meaning |
|---|---|---|
| default data event | sdk.ResponseChunk JSON | Incremental response chunks from the underlying runtime stream. |
| runtime | sdk.RuntimeEvent JSON | Structured engine events such as tool progress, permission requests, prompt requests, and other runtime-side state changes. |
| done | queryResponse JSON | Final summarized response envelope with content, usage, stop reason, tool uses, tool results, and any RAG results. |
| error | {"error":"..."} | Terminal stream error after the SSE connection has already been established. |
curl -N -X POST http://localhost:8090/api/v1/query/stream -H 'Authorization: Bearer <jwt>' -H 'Content-Type: application/json' -d '{
"prompt": "Inspect the attached corpus and summarize the key risks.",
"session_id": "sess_123",
"corpus_id": "corp_456",
"agent_slug": "risk-analyst"
}'One important backend-specific feature is that permission requests and non-confirm prompts are bridged through SSE. That means web or desktop clients can stay connected to one stream and still react to runtime permission gates without reimplementing the loop themselves.
Endpoint Catalog
The router in internal/api/routes.go currently groups the backend into the following main families.
| Family | Base Path | Auth | Purpose |
|---|---|---|---|
| Health & metrics | /health, /metrics, /api/v1/metrics | Public for /health and top-level /metrics | Basic liveness plus Prometheus or JSON metrics snapshots. |
| Native query runtime | /api/v1/query, /api/v1/query/stream | Bearer JWT or sk-* API key | Run the full Seshat agent loop through the backend with sessions, permissions, agent profiles, RAG, files, and runtime events. |
| Session management | /api/v1/sessions, /api/v1/sessions/{id} | Bearer JWT or sk-* API key | Create, list, update, delete, search, interrupt, and inspect persisted agent sessions. |
| Auth & identity | /api/v1/auth/*, /api/v1/users/*, /api/v1/groups/*, /api/v1/organizations/*, /api/v1/workspaces/* | Mixed: login/register public, most others authenticated | Users, roles, memberships, organizations, workspaces, API keys, and user preferences. |
| Provider settings | /api/v1/settings/providers/*, /api/v1/settings/embedder, /api/v1/settings/storage | Bearer JWT or sk-* API key | Manage provider credentials, OAuth flows, default models, custom model catalogs, embedder config, and storage config. |
| Knowledge & files | /api/v1/files/*, /api/v1/corpora/*, /api/v1/memories/* | Bearer JWT or sk-* API key | Upload files, build corpora, run ingestion jobs, search corpora, and manage extracted long-term memory. |
| Planning & automation | /api/v1/plans/*, /api/v1/scheduler/jobs/* | Bearer JWT or sk-* API key | Read plan-mode artifacts and create cron-like scheduled agent runs. |
| Extensions & admin | /api/v1/skills/*, /api/v1/mcp/*, /api/v1/web/search/*, /api/v1/audit/logs, /api/v1/quotas | Mixed, with some admin-only routes | Skills, MCP configuration, web-search settings, audit access, and quota visibility. |
| Anthropic-compatible layer | /v1/messages | x-api-key or Authorization: Bearer | Expose the backend as a Claude-compatible Messages API while still executing the full Seshat runtime server-side. |
Anthropic-Compatible Messages API
The compatibility layer exists so existing Claude-oriented clients can point their base URL at Seshat and still use the backend as the execution engine. The request format is Anthropic-style, but the actual tool use, permissions, memory, and provider routing remain server-side in Seshat.
- The compatible path is POST /v1/messages.
- It accepts either x-api-key or Authorization: Bearer.
- x-seshat-session-id binds the request to an existing backend session for multi-turn continuity.
- x-seshat-provider-setting-id lets the client override which provider setting the backend should use.
- Runtime events are intentionally not forwarded in Anthropic mode because the protocol has no equivalent for Seshat-specific tool progress or permission events.
curl -N -X POST http://localhost:8090/v1/messages -H 'x-api-key: <seshat-api-key>' -H 'x-seshat-session-id: sess_123' -H 'x-seshat-provider-setting-id: pset_456' -H 'Content-Type: application/json' -d '{
"model": "anthropic:claude-sonnet-4-20250514",
"max_tokens": 2048,
"stream": true,
"messages": [
{"role": "user", "content": "Review the project status and propose next actions."}
]
}'If you want the protobuf-first alternative instead of HTTP compatibility, continue with gRPC API.
Operational Notes
The HTTP server configuration is intentionally SSE-friendly. The backend disables global write timeout for the API server, enables optional localhost-oriented CORS in debug mode, assigns request IDs, caps most JSON bodies to 4 MB, and treats panic recovery as transport middleware rather than app logic.
Set in the API config assembled by cmd/api/config.go.
Disabled globally because SSE responses may stay open for minutes.
Applied through middleware for most routes, excluding stream-like or file-oriented paths.
Without an allowlist, it defaults to localhost origins rather than broad production exposure.
For the backend package map behind this API, see [architecture.md](/home/amiche/Projects/AI/ai/seshat-ai/docs/architecture.md:1). For the runtime side it calls into, see Mono-Run Architecture.