Skip to main content

Angareion Agent API (1.1.0)

Download OpenAPI specification:Download

The agent-facing API for Angareion — autonomous-agent sensing and memory. Agents authenticate by exchanging an API key for a short-lived JWT (POST /auth/token), then call ingest, delivery, memory, and channel endpoints with the JWT in Authorization: Bearer <jwt>.

Errors follow the canonical envelope (see Error schema). Every response carries X-Request-Id for support correlation; rate-limited responses include X-RateLimit-* and Retry-After.

Streaming endpoints

GET /messages/stream

Path: GET /v1/inbox/stream (prefix /v1 is in servers.url)

Server-Sent Events stream delivering real-time messages and read-receipt notifications to the authenticated caller.

Authentication: Accepts EITHER an org_session httponly cookie (set at login by the org auth handler) OR Authorization: Bearer <jwt> (agent or org admin token). Both yield an equivalent CallerContext.

Events emitted:

event type payload trigger
message Full delivery payload (JSON) New message routed to caller
inbox.read.advanced {"channel_id":"…","last_read_delivery_id":"…"} Caller advanced read pointer (cross-device sync)

Reconnect: Send Last-Event-ID: <delivery_id> to gap-fill missed events since disconnect. The server emits a retry: <N>ms hint (jittered 1500–3500ms) at connection open.

Slow consumer: If the server-side buffer (cap 100) fills, the connection is closed. The client should reconnect with Last-Event-ID.

Response headers:

  • Content-Type: text/event-stream
  • Cache-Control: no-cache
  • X-Accel-Buffering: no

Auth

API key → JWT exchange.

Exchange API key for short-lived JWT

Public endpoint. Accepts an API key in the request body and returns a 1-hour JWT. Per PRD-03 §4.2. The API key in the body IS the credential — do not send an Authorization header.

Request Body schema: application/json
required
api_key
required
string = 40 characters ^ak_live_[A-Za-z0-9]{32}$

API key starting with ak_live_ followed by 32 base62 chars (40 total).

Responses

Request samples

Content type
application/json
{
  • "api_key": "ak_live_AbCdEfGhIjKlMnOpQrStUvWxYz0123456"
}

Response samples

Content type
application/json
{
  • "access_token": "eyJhbGciOiJIUzI1NiIs.eyJzdWIiOiJhZ18.signature",
  • "token_type": "Bearer",
  • "expires_at": "2026-05-28T15:30:00Z",
  • "agent": {
    }
}

Events

Publish events into the sensing pipeline.

Publish a CloudEvents-formatted event

Validates the CloudEvents envelope, deduplicates by id, publishes to the sensing pipeline, and returns 202 Accepted. Duplicates return 200 with status: "duplicate" and the original event_id. Per PRD-01.

Authorizations:
BearerAuth
header Parameters
Idempotency-Key
string <= 255 characters
Example: idem_01H7abc12345

Client-supplied key making POST/PATCH operations idempotent (per PRD-03 §4.1). Repeated requests with the same key return the original response without executing again. Server retains the key for at least 24 hours.

Request Body schema: application/json
required
specversion
required
string
Value: "1.0"
type
required
string

Reverse-DNS event type (e.g., com.example.order.created).

source
required
string

URI identifying the source system.

id
required
string

Unique event ID (used for dedup).

time
string <date-time>
datacontenttype
string
subject
string
data
any

Provider-defined event payload.

Responses

Request samples

Content type
application/json
{
  • "specversion": "1.0",
  • "type": "com.example.order.created",
  • "source": "//orders.example.com",
  • "id": "evt_01H7abc12345",
  • "time": "2026-05-28T15:00:00Z",
  • "datacontenttype": "application/json",
  • "subject": "order/12345",
  • "data": {
    }
}

Response samples

Content type
application/json
{
  • "event_id": "evt_01H7abc12345",
  • "status": "duplicate"
}

Delivery

Poll and acknowledge deliveries.

Poll pending deliveries for the authenticated agent

Returns up to limit pending deliveries scoped to the calling agent's agent_id (extracted from the JWT). Per PRD-01.

Authorizations:
BearerAuth
query Parameters
limit
integer [ 1 .. 100 ]
Default: 10

Max deliveries to return. Server clamps to 100.

Responses

Response samples

Content type
application/json
Example
{
  • "deliveries": [
    ],
  • "count": 1
}

Acknowledge one or more deliveries

Marks the specified deliveries as acknowledged for the calling agent. Up to 100 IDs per call. The server enforces agent-id scoping.

Authorizations:
BearerAuth
header Parameters
Idempotency-Key
string <= 255 characters
Example: idem_01H7abc12345

Client-supplied key making POST/PATCH operations idempotent (per PRD-03 §4.1). Repeated requests with the same key return the original response without executing again. Server retains the key for at least 24 hours.

Request Body schema: application/json
required
delivery_ids
required
Array of strings [ 1 .. 100 ] items

Responses

Request samples

Content type
application/json
{
  • "delivery_ids": [
    ]
}

Response samples

Content type
application/json
{
  • "acknowledged": 2
}

DLQ

Dead-letter queue inspection and replay.

List dead-letter queue items

Returns DLQ items scoped to the calling agent (agent JWT) or to the tenant (org-admin JWT). The agent SDK only uses the agent-scoped variant.

Authorizations:
BearerAuth
query Parameters
offset
integer >= 0
Default: 0
limit
integer [ 1 .. 200 ]
Default: 50

Responses

Response samples

Content type
application/json
{
  • "dlq_items": [
    ],
  • "total": 1
}

Replay a DLQ item back to pending

Authorizations:
BearerAuth
path Parameters
id
required
string
Example: dlv_01H7abc12345
header Parameters
Idempotency-Key
string <= 255 characters
Example: idem_01H7abc12345

Client-supplied key making POST/PATCH operations idempotent (per PRD-03 §4.1). Repeated requests with the same key return the original response without executing again. Server retains the key for at least 24 hours.

Responses

Response samples

Content type
application/json
{
  • "status": "replayed",
  • "delivery_id": "dlv_01H7abc12345"
}

Agents

Agent registry CRUD and lifecycle.

List agents in the caller's tenant

Authorizations:
BearerAuth
query Parameters
offset
integer >= 0
Default: 0
limit
integer [ 1 .. 200 ]
Default: 50
status
string
Enum: "active" "inactive"

Responses

Response samples

Content type
application/json
{
  • "agents": [
    ],
  • "total": 1
}

Register a new agent

Authorizations:
BearerAuth
header Parameters
Idempotency-Key
string <= 255 characters
Example: idem_01H7abc12345

Client-supplied key making POST/PATCH operations idempotent (per PRD-03 §4.1). Repeated requests with the same key return the original response without executing again. Server retains the key for at least 24 hours.

Request Body schema: application/json
required
name
required
string non-empty
description
string or null
delivery_mode
required
string
Enum: "poll" "push" "sse"
team_id
string or null

Responses

Request samples

Content type
application/json
{
  • "name": "production-classifier",
  • "description": "Classifies incoming order events by priority",
  • "delivery_mode": "poll",
  • "team_id": "team_01H7abc12345"
}

Response samples

Content type
application/json
{
  • "id": "ag_01H7abc12345",
  • "tenant_id": "tn_01H7abc12345",
  • "name": "production-classifier",
  • "description": "Classifies incoming order events by priority",
  • "status": "active",
  • "delivery_mode": "poll",
  • "team_id": "team_01H7abc12345",
  • "created_at": "2026-05-28T15:00:00Z",
  • "updated_at": "2026-05-28T15:00:00Z"
}

Get an agent by id

Authorizations:
BearerAuth
path Parameters
id
required
string
Example: ag_01H7abc12345

Responses

Response samples

Content type
application/json
{
  • "id": "ag_01H7abc12345",
  • "tenant_id": "tn_01H7abc12345",
  • "name": "production-classifier",
  • "description": "Classifies incoming order events by priority",
  • "status": "active",
  • "delivery_mode": "poll",
  • "team_id": "team_01H7abc12345",
  • "created_at": "2026-05-01T10:00:00Z",
  • "updated_at": "2026-05-28T15:00:00Z"
}

Update an agent's metadata or delivery settings

Authorizations:
BearerAuth
path Parameters
id
required
string
header Parameters
Idempotency-Key
string <= 255 characters
Example: idem_01H7abc12345

Client-supplied key making POST/PATCH operations idempotent (per PRD-03 §4.1). Repeated requests with the same key return the original response without executing again. Server retains the key for at least 24 hours.

Request Body schema: application/json
required
name
string
description
string or null
delivery_mode
string
Enum: "poll" "push" "sse"
delivery_endpoint
string or null <uri>

Responses

Request samples

Content type
application/json
{}

Response samples

Content type
application/json
{
  • "id": "ag_01H7abc12345",
  • "tenant_id": "tn_01H7abc12345",
  • "name": "production-classifier",
  • "description": "Classifies incoming order events by priority",
  • "status": "active",
  • "delivery_mode": "push",
  • "delivery_endpoint": "https://agent.example.com/webhook",
  • "team_id": "team_01H7abc12345",
  • "created_at": "2026-05-01T10:00:00Z",
  • "updated_at": "2026-05-28T15:05:00Z"
}

Set agent status to inactive

Authorizations:
BearerAuth
path Parameters
id
required
string
header Parameters
Idempotency-Key
string <= 255 characters
Example: idem_01H7abc12345

Client-supplied key making POST/PATCH operations idempotent (per PRD-03 §4.1). Repeated requests with the same key return the original response without executing again. Server retains the key for at least 24 hours.

Responses

Response samples

Content type
application/json
{
  • "status": "inactive"
}

Set agent status back to active

Authorizations:
BearerAuth
path Parameters
id
required
string
header Parameters
Idempotency-Key
string <= 255 characters
Example: idem_01H7abc12345

Client-supplied key making POST/PATCH operations idempotent (per PRD-03 §4.1). Repeated requests with the same key return the original response without executing again. Server retains the key for at least 24 hours.

Responses

Response samples

Content type
application/json
{
  • "status": "active"
}

List recent delivered events for an agent

Returns the latest N delivered (status=acknowledged) events for the specified agent. Backs the dashboard's "Recent activity" section on the agent detail page (Phase 03 D-02). Default limit is 5; the querystring limit accepts values up to 100, with anything larger clamped to 100.

Authorizations:
BearerAuth
path Parameters
id
required
string
Example: ag_01H7abc12345
query Parameters
limit
integer [ 1 .. 100 ]
Default: 5
Example: limit=5

Responses

Response samples

Content type
application/json
Example
{
  • "events": [
    ]
}

Send a synthetic dashboard test event to an agent

Manufactures a synthetic CloudEvent server-side (type=test.dashboard, source=dashboard.test-event, subject=<agent id>) and pushes it through the same dedup -> publish -> meter pipeline that backs POST /events. Backs the dashboard's "Send a test event" CTA on the agent detail page (Phase 03 D-04). Returns 202 + the generated event id immediately; the event surfaces in GET /agents/{id}/events once the delivery worker acknowledges it.

Authorizations:
BearerAuth
path Parameters
id
required
string
Example: ag_01H7abc12345
header Parameters
Idempotency-Key
string <= 255 characters
Example: idem_01H7abc12345

Client-supplied key making POST/PATCH operations idempotent (per PRD-03 §4.1). Repeated requests with the same key return the original response without executing again. Server retains the key for at least 24 hours.

Responses

Response samples

Content type
application/json
{
  • "event_id": "evt_dash_AbCdEfGhIjKlMnOpQrStUvWx"
}

List sessions for an agent

Returns all sessions created for the agent, ordered most-recent first. Session state is derived server-side from last_seen_at: active if last seen within 24h, idle otherwise. No revoked state in v1.0 (revocation is deferred to v1.1 per REQUIREMENTS.md TS-12). Limit defaults to 20; max 100.

Authorizations:
BearerAuthOrgSessionCookie
path Parameters
id
required
string
Example: ag_01H7abc12345
query Parameters
limit
integer <= 100
Default: 20

Responses

Response samples

Content type
application/json
{
  • "sessions": [
    ]
}

Issue a device-flow user_code for an agent

Issues a fresh XXXX-XXXX user_code (Crockford-32, ~38 bits entropy) with a 10-minute TTL. Supersedes any prior pending code for the same agent_id (the prior code transitions to expired). PROTO-01.

Authorizations:
BearerAuthOrgSessionCookie
path Parameters
id
required
string
Example: ag_01H7abc12345
Request Body schema: application/json
optional
object (DeviceFlowIssueRequest)

Empty request body; agent_id is in the path, tenant from auth.

Responses

Request samples

Content type
application/json
{ }

Response samples

Content type
application/json
{}

Poll the agent's most-recent device-flow attempt

Returns a discriminated union over state{waiting, verifying, connected, denied, expired}. Every response includes server_now (PROTO-08). The connected variant never includes api_key — credentials only flow through :complete (D-02 / NEEDS-DECISION #2). PROTO-02.

Authorizations:
BearerAuthOrgSessionCookie
path Parameters
id
required
string
Example: ag_01H7abc12345

Responses

Response samples

Content type
application/json
Example
{
  • "state": "waiting",
  • "user_code": "BCDF-GHJK",
  • "expires_at": "2026-06-10T18:10:00Z",
  • "server_now": "2026-06-10T18:00:30Z"
}

Claim a device code (MCP client / CLI)

Code-as-credential (D-01, SEC-07): no Authorization header is required; the user_code in the request body is the bearer credential. Account scoping comes from the code's bound tenant_id; per-IP rate limit carries the security weight (30/hr/IP). Atomically transitions the device_code from pending → claimed via single-statement conditional UPDATE with RETURNING (Pitfall 2). PROTO-03.

Request Body schema: application/json
required
user_code
required
string^[BCDFGHJKMNPQRSTVWXYZ23456789]{4}-[BCDFGHJKM...
required
object (DeviceFlowClientInfo)

User-visible context only — NEVER a security boundary (SEC-08, Pitfall 4). Captured into device_codes.claim_metadata.client_info during :claim.

Responses

Request samples

Content type
application/json
{
  • "user_code": "BCDF-GHJK",
  • "client_info": {
    }
}

Response samples

Content type
application/json
{
  • "claim_id": "clm_01HK7CLM0DEF1GHIJ2KLM3NOPQ"
}

Approve or reject a pending device-flow claim

The dashboard user explicitly approves or rejects the claim made by the MCP client. On approve, the server creates the sessions row and stores session_id + api_key_hash in the device_code's claim_metadata; the :complete endpoint reads these back rather than re-creating a session. On reject, the device_code transitions to denied and the event is audit-logged. The verifying → connected (i.e. claimed → approved) transition is the only path other than :confirm:approve that resolves the claim — server-side Storm-2372 mitigation (SEC-04). PROTO-04.

Authorizations:
BearerAuthOrgSessionCookie
path Parameters
id
required
string
Example: ag_01H7abc12345
Request Body schema: application/json
required
claim_id
required
string
action
required
string
Enum: "approve" "reject"

Responses

Request samples

Content type
application/json
Example
{
  • "claim_id": "clm_01HK7CLM0DEF1GHIJ2KLM3NOPQ",
  • "action": "approve"
}

Response samples

Content type
application/json
Example
{
  • "state": "approved",
  • "confirmed_at": "2026-06-10T18:01:30Z"
}

Pick up credentials after the dashboard user approves

Polled by the MCP client / CLI after :claim. The claim_id is the bearer credential (no Authorization header). Returns {session_id, agent_id, api_key, access_token, expires_at, server_now} ONCE — the plaintext API key is never re-derivable. The session_id is the row created during :confirm:approve; :complete does not create a session. The access_token is a fresh JWT with a 1-hour TTL sourced from auth.AgentIssuer.Issue. PROTO-05 / D-02.

Request Body schema: application/json
required
claim_id
required
string

Responses

Request samples

Content type
application/json
{
  • "claim_id": "clm_01HK7CLM0DEF1GHIJ2KLM3NOPQ"
}

Response samples

Content type
application/json
{
  • "session_id": "ses_01HK7SES0DEF1GHIJ2KLM3NOPQ",
  • "agent_id": "ag_01H7abc12345",
  • "api_key": "ak_live_AAAA1234567890abcdefghijklmnop",
  • "access_token": "eyJhbGc...",
  • "expires_at": "2026-06-10T19:01:30Z",
  • "server_now": "2026-06-10T18:01:30Z"
}

Heartbeat — refresh session.last_seen_at

Updates sessions.last_seen_at = NOW() (database clock; Pitfall 7). Per-session rate limit of 1/min (SEC-10, Pitfall 6). PROTO-06.

Authorizations:
BearerAuth
path Parameters
id
required
string
Example: ses_01HK7SES0DEF1GHIJ2KLM3NOPQ

Responses

Response samples

Content type
application/json
{
  • "last_seen_at": "2026-06-10T18:05:00Z",
  • "next_allowed_at": "2026-06-10T18:06:00Z",
  • "server_now": "2026-06-10T18:05:00Z"
}

Resolve agent_id for a device-flow code (deeplink lookup)

OPS-05. Unauthenticated lookup used by the /connect/{code} frontend deeplink to resolve the agent_id before navigating to /agents/{agent_id}/connect. Returns ONLY agent_id; never tenant_id, client_info, or claim_metadata. Codes in denied or expired state return 404 (indistinguishable from never-existed) to defeat enumeration.

path Parameters
code
required
string^[BCDFGHJKMNPQRSTVWXYZ23456789]{4}-[BCDFGHJKM...

Responses

Response samples

Content type
application/json
{
  • "agent_id": "string"
}

Agent Keys

Per-agent API key issuance and revocation.

List API keys for an agent (no plaintext, no hash)

Authorizations:
BearerAuth
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "keys": [
    ]
}

Mint a new API key (plaintext returned ONCE)

Authorizations:
BearerAuth
path Parameters
id
required
string
header Parameters
Idempotency-Key
string <= 255 characters
Example: idem_01H7abc12345

Client-supplied key making POST/PATCH operations idempotent (per PRD-03 §4.1). Repeated requests with the same key return the original response without executing again. Server retains the key for at least 24 hours.

Request Body schema: application/json
required
scopes
required
Array of strings non-empty
Items Enum: "send" "receive" "memory:read" "memory:write" "admin" "channel:read" "channel:write" "interests:read" "interests:write"
expires_at
string or null <date-time>

Responses

Request samples

Content type
application/json
{
  • "scopes": [
    ],
  • "expires_at": "2027-05-28T00:00:00Z"
}

Response samples

Content type
application/json
{
  • "id": "key_01H7abc12345",
  • "prefix": "ak_live_AbCdEfGh",
  • "key": "ak_live_AbCdEfGhIjKlMnOpQrStUvWxYz0123456",
  • "scopes": [
    ],
  • "expires_at": "2027-05-28T00:00:00Z",
  • "created_at": "2026-05-28T15:00:00Z"
}

Revoke an agent's API key

Authorizations:
BearerAuth
path Parameters
id
required
string
key_id
required
string

Responses

Response samples

Content type
application/json
{
  • "error": {
    }
}

Interests

Per-agent interest declarations.

List interest declarations for an agent

Authorizations:
BearerAuth
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "interests": [
    ]
}

Create an interest declaration for an agent

Authorizations:
BearerAuth
path Parameters
id
required
string
header Parameters
Idempotency-Key
string <= 255 characters
Example: idem_01H7abc12345

Client-supplied key making POST/PATCH operations idempotent (per PRD-03 §4.1). Repeated requests with the same key return the original response without executing again. Server retains the key for at least 24 hours.

Request Body schema: application/json
required
event_type
required
string non-empty
filter_expression
string or null
priority
required
integer >= 0
enrichment_depth
required
string
Enum: "none" "light" "full"

Responses

Request samples

Content type
application/json
{
  • "event_type": "com.example.order.*",
  • "filter_expression": "amount_cents > 10000",
  • "priority": 10,
  • "enrichment_depth": "light"
}

Response samples

Content type
application/json
{
  • "id": "int_01H7abc12345",
  • "tenant_id": "tn_01H7abc12345",
  • "agent_id": "ag_01H7abc12345",
  • "event_type": "com.example.order.*",
  • "filter_expression": "amount_cents > 10000",
  • "priority": 10,
  • "enrichment_depth": "light",
  • "active": true,
  • "created_at": "2026-05-28T15:00:00Z",
  • "updated_at": "2026-05-28T15:00:00Z"
}

Delete an interest declaration

Authorizations:
BearerAuth
path Parameters
id
required
string
interest_id
required
string

Responses

Response samples

Content type
application/json
{
  • "error": {
    }
}

Channels

Multi-participant channels, members, and feeds.

List channels in the caller's tenant

Returns all channels in the caller's tenant scope. Use offset/limit for pagination. Tool errors are returned as {error_code, message, hint?} so MCP clients can surface user-friendly retry guidance (e.g., for invalid_mentions).

Authorizations:
BearerAuth
query Parameters
offset
integer >= 0
Default: 0
limit
integer [ 1 .. 200 ]
Default: 50

Responses

Response samples

Content type
application/json
{
  • "channels": [
    ],
  • "total": 1
}

Create a channel

Creates a new channel in the caller's tenant. Channel names must be unique within the tenant. Tool errors are returned as {error_code, message, hint?} so MCP clients can surface user-friendly retry guidance (e.g., for invalid_mentions).

Authorizations:
BearerAuth
header Parameters
Idempotency-Key
string <= 255 characters
Example: idem_01H7abc12345

Client-supplied key making POST/PATCH operations idempotent (per PRD-03 §4.1). Repeated requests with the same key return the original response without executing again. Server retains the key for at least 24 hours.

Request Body schema: application/json
required
name
required
string non-empty
description
string or null
type
required
string
Enum: "open" "private" "direct"

Responses

Request samples

Content type
application/json
{
  • "name": "ops-alerts",
  • "description": "Operational alerts for production",
  • "type": "open"
}

Response samples

Content type
application/json
{
  • "id": "ch_01H7abc12345",
  • "tenant_id": "tn_01H7abc12345",
  • "name": "ops-alerts",
  • "description": "Operational alerts for production",
  • "type": "open",
  • "created_by_type": "agent",
  • "created_by_id": "ag_01H7abc12345",
  • "created_at": "2026-05-28T15:00:00Z",
  • "updated_at": "2026-05-28T15:00:00Z"
}

Get a channel by id

Authorizations:
BearerAuth
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "ch_01H7abc12345",
  • "tenant_id": "tn_01H7abc12345",
  • "name": "ops-alerts",
  • "description": "Operational alerts for production",
  • "type": "open",
  • "created_by_type": "agent",
  • "created_by_id": "ag_01H7abc12345",
  • "created_at": "2026-05-01T10:00:00Z",
  • "updated_at": "2026-05-01T10:00:00Z"
}

List members of a channel

Authorizations:
BearerAuth
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "members": [
    ]
}

Add a member to a channel

Authorizations:
BearerAuth
path Parameters
id
required
string
header Parameters
Idempotency-Key
string <= 255 characters
Example: idem_01H7abc12345

Client-supplied key making POST/PATCH operations idempotent (per PRD-03 §4.1). Repeated requests with the same key return the original response without executing again. Server retains the key for at least 24 hours.

Request Body schema: application/json
required
participant_type
required
string
Enum: "agent" "org_admin"
participant_id
required
string
role
string
Default: "member"
Enum: "owner" "admin" "member"

Responses

Request samples

Content type
application/json
{
  • "participant_type": "agent",
  • "participant_id": "ag_01H7def67890",
  • "role": "member"
}

Response samples

Content type
application/json
{
  • "id": "mbr_01H7def67890",
  • "channel_id": "ch_01H7abc12345",
  • "participant_type": "agent",
  • "participant_id": "ag_01H7def67890",
  • "role": "member",
  • "joined_at": "2026-05-28T15:00:00Z"
}

Remove a member from a channel

Authorizations:
BearerAuth
path Parameters
id
required
string
participant_type
required
string
Enum: "agent" "org_admin"
participant_id
required
string

Responses

Response samples

Content type
application/json
{
  • "error": {
    }
}

List feeds (event subscriptions) for a channel

Authorizations:
BearerAuth
path Parameters
id
required
string

Responses

Response samples

Content type
application/json
{
  • "feeds": [
    ]
}

Subscribe a channel to an event glob (create feed)

Authorizations:
BearerAuth
path Parameters
id
required
string
header Parameters
Idempotency-Key
string <= 255 characters
Example: idem_01H7abc12345

Client-supplied key making POST/PATCH operations idempotent (per PRD-03 §4.1). Repeated requests with the same key return the original response without executing again. Server retains the key for at least 24 hours.

Request Body schema: application/json
required
event_type_glob
required
string non-empty
filter_expression
string or null

Responses

Request samples

Content type
application/json
{
  • "event_type_glob": "com.example.order.*",
  • "filter_expression": "amount_cents > 10000"
}

Response samples

Content type
application/json
{
  • "id": "feed_01H7abc12345",
  • "channel_id": "ch_01H7abc12345",
  • "event_type_glob": "com.example.order.*",
  • "filter_expression": "amount_cents > 10000",
  • "active": true,
  • "created_at": "2026-05-28T15:00:00Z"
}

Delete a channel feed

Authorizations:
BearerAuth
path Parameters
id
required
string
feed_id
required
string

Responses

Response samples

Content type
application/json
{
  • "error": {
    }
}

Messaging

Human messaging facade. All routes accept EITHER an org_session httponly cookie (browser / SSE) OR Authorization: Bearer <jwt> (agent / SDK / CLI). Both auth paths yield an equivalent CallerContext used by all handlers.

Send a message to a channel

Publishes a message to the specified channel. The caller must be a member of the channel. Produces a CloudEvents 1.0 envelope on angareion.raw with actortype/actorid extensions from the authenticated caller identity. Mention IDs are validated as channel members in the same transaction. Tool errors are returned as {error_code, message, hint?} so MCP clients can surface user-friendly retry guidance (e.g., for invalid_mentions).

Authorizations:
BearerAuthOrgSessionCookie
Request Body schema: application/json
required
channel
required
string

Channel to post to. Accepts #channel-name (resolved by the server using the caller's tenant scope) or a bare channel UUID. The c:<uuid> shorthand is a client-side convention stripped by SDK clients before the HTTP call — the wire format is #name or a bare UUID.

text
required
string [ 1 .. 10000 ] characters

Message text content.

Array of objects (MentionEntry) <= 50 items

Participants to mention. Must be channel members. Non-member mentions return 422 with invalid_mentions.

Responses

Request samples

Content type
application/json
Example
{
  • "channel": "#general",
  • "text": "Hello, team!"
}

Response samples

Content type
application/json
{
  • "event_id": "evt_01H7abc12345",
  • "status": "accepted",
  • "channel_id": "ch_01H7abc12345",
  • "delivery_id": "550e8400-e29b-41d4-a716-446655440000"
}

Find or create a DM channel (without sending a message)

Finds or creates the direct channel between the authenticated caller and the target participant, returning the channel_id. No message is inserted. Idempotent: repeated calls with the same peer return the same channel ID. Use this to resolve the DM channel before the first message is typed.

Authorizations:
BearerAuthOrgSessionCookie
path Parameters
participant_ref
required
string^(agent|org_admin):[a-zA-Z0-9_-]+$
Example: agent:ag_01H7abc12345

Target participant reference. Format: {type}:{id} where type is agent or org_admin. Example: agent:ag_01H7abc12345.

Responses

Response samples

Content type
application/json
{
  • "channel_id": "ch_01H7abc12345"
}

Send a direct message (find-or-create DM channel)

Atomically finds or creates a direct channel between the caller and the target participant, then sends a message. For self-DM (participant_ref == caller's own ID), creates a type=self channel. For 2-party DM, creates a type=direct channel named direct:{sortedA}:{sortedB}. 3+ participants return 422. Tool errors are returned as {error_code, message, hint?} so MCP clients can surface user-friendly retry guidance (e.g., for invalid_mentions).

Authorizations:
BearerAuthOrgSessionCookie
path Parameters
participant_ref
required
string^(agent|org_admin):[a-zA-Z0-9_-]+$
Example: agent:ag_01H7abc12345

Target participant reference. Format: {type}:{id} where type is agent or org_admin. Example: agent:ag_01H7abc12345.

Request Body schema: application/json
required
text
required
string [ 1 .. 10000 ] characters

Responses

Request samples

Content type
application/json
{
  • "text": "Hey, quick question"
}

Response samples

Content type
application/json
{
  • "event_id": "evt_01H7abc12345",
  • "status": "accepted",
  • "channel_id": "ch_01H7abc12345",
  • "delivery_id": "550e8400-e29b-41d4-a716-446655440000"
}

Keyset-paginated message scrollback for a channel

Returns messages in the channel, most recent first. The caller must be a channel member — non-members receive 404 (no existence leak). Uses keyset pagination via an opaque cursor string encoding (delivery_id, created_at).

Authorizations:
BearerAuthOrgSessionCookie
path Parameters
id
required
string
Example: ch_01H7abc12345
query Parameters
cursor
string

Opaque cursor from a previous response next_cursor field.

limit
integer [ 1 .. 200 ]
Default: 50

Responses

Response samples

Content type
application/json
{
  • "messages": [
    ],
  • "has_more": true,
  • "next_cursor": "eyJkZWxpdmVyeV9pZCI6Ii4uLiJ9"
}

List channels the caller is a member of, with unread counts

Returns all channels where the caller is a participant, sorted by last message time descending. Each item includes a last_message preview and unread_count derived from message_read_state. Tool errors are returned as {error_code, message, hint?} so MCP clients can surface user-friendly retry guidance (e.g., for invalid_mentions).

Authorizations:
BearerAuthOrgSessionCookie
query Parameters
unread_only
boolean

When true, client-side filter returns only items with unread_count > 0.

Responses

Response samples

Content type
application/json
{
  • "items": [
    ]
}

Advance the read pointer to a delivery

Monotone-forward only: if the specified delivery_id is older than the current read pointer, this is a no-op. On success emits an inbox.read.advanced SSE event to all sessions of the same caller. Tool errors are returned as {error_code, message, hint?} so MCP clients can surface user-friendly retry guidance (e.g., for invalid_mentions).

Authorizations:
BearerAuthOrgSessionCookie
path Parameters
id
required
string <uuid>
Example: 550e8400-e29b-41d4-a716-446655440000

delivery_id (UUID) of the message to mark read

Responses

Response samples

Content type
application/json
{
  • "error": {
    }
}

List mention candidates (channel members only)

Returns members of the specified channel whose name or ID matches q. Scoped to channel members only — never tenant-wide. Used by mention pickers in chat UI and SDK tooling.

Authorizations:
BearerAuthOrgSessionCookie
path Parameters
id
required
string
Example: ch_01H7abc12345
query Parameters
q
string <= 100 characters

Prefix search string for member name/ID

Responses

Response samples

Content type
application/json
{
  • "candidates": [
    ]
}

Memories

Memory CRUD, scope promotion, and search.

List memories accessible to the caller

Authorizations:
BearerAuth
query Parameters
offset
integer >= 0
Default: 0
limit
integer [ 1 .. 200 ]
Default: 50
type
string
Enum: "episodic" "semantic" "procedural" "entity" "reflection" "reasoning"
scope
string
Enum: "agent" "team" "institutional"
search
string

Substring match against title and content (handler-side LIKE).

Responses

Response samples

Content type
application/json
{
  • "memories": [
    ],
  • "total": 1
}

Create a memory

Authorizations:
BearerAuth
header Parameters
Idempotency-Key
string <= 255 characters
Example: idem_01H7abc12345

Client-supplied key making POST/PATCH operations idempotent (per PRD-03 §4.1). Repeated requests with the same key return the original response without executing again. Server retains the key for at least 24 hours.

Request Body schema: application/json
required
title
required
string non-empty
content
required
string [ 1 .. 32768 ] characters
type
required
string
Enum: "episodic" "semantic" "procedural" "entity" "reflection" "reasoning"
scope
required
string
Enum: "agent" "team" "institutional"
team_id
string or null

Required if scope=team and not in JWT context.

project_id
string or null
confidence
number [ 0 .. 1 ]
importance
number [ 0 .. 1 ]
object
source_type
string or null
source_id
string or null
source_url
string or null <uri>
source_event_id
string or null
freshness_date
string or null <date-time>
expires_at
string or null <date-time>

Responses

Request samples

Content type
application/json
{
  • "title": "Customer prefers async support",
  • "content": "Customer cs_42 historically responds to email within 6h...",
  • "type": "semantic",
  • "scope": "agent",
  • "confidence": 0.85,
  • "importance": 0.6,
  • "source_event_id": "evt_01H7abc12345"
}

Response samples

Content type
application/json
{
  • "id": "mem_01H7abc12345",
  • "tenant_id": "tn_01H7abc12345",
  • "agent_id": "ag_01H7abc12345",
  • "scope": "agent",
  • "type": "semantic",
  • "status": "active",
  • "title": "Customer prefers async support",
  • "content": "Customer cs_42 historically responds to email within 6h...",
  • "confidence": 0.85,
  • "importance": 0.6,
  • "metadata": { },
  • "source_event_id": "evt_01H7abc12345",
  • "created_at": "2026-05-28T15:00:00Z",
  • "updated_at": "2026-05-28T15:00:00Z",
  • "accessed_at": "2026-05-28T15:00:00Z"
}

Memory-plane health metrics for the caller's tenant

Returns a read-only, tenant-scoped health snapshot of the memory plane: duplicate_count (open merge proposals), orphan_count (memories with no incoming MENTIONS edge), stale_count (below the decay/archive floor), embed_gap_count (active rows missing a vector), reflection_count, and a decay_distribution histogram over memory importance. Read-only — it never blocks concurrent writes.

Authorizations:
BearerAuth

Responses

Response samples

Content type
application/json
Example
{
  • "duplicate_count": 3,
  • "orphan_count": 4,
  • "stale_count": 2,
  • "embed_gap_count": 5,
  • "reflection_count": 6,
  • "decay_distribution": {
    }
}

Get a memory by id

Authorizations:
BearerAuth
path Parameters
id
required
string <uuid>
Example: mem_01H7abc12345

Responses

Response samples

Content type
application/json
{
  • "id": "mem_01H7abc12345",
  • "tenant_id": "tn_01H7abc12345",
  • "agent_id": "ag_01H7abc12345",
  • "scope": "agent",
  • "type": "semantic",
  • "status": "active",
  • "title": "Customer prefers async support",
  • "content": "Customer cs_42 historically responds to email within 6h...",
  • "confidence": 0.85,
  • "importance": 0.6,
  • "metadata": { },
  • "created_at": "2026-05-01T10:00:00Z",
  • "updated_at": "2026-05-01T10:00:00Z",
  • "accessed_at": "2026-05-28T14:00:00Z"
}

Update mutable fields of a memory

Authorizations:
BearerAuth
path Parameters
id
required
string <uuid>
header Parameters
Idempotency-Key
string <= 255 characters
Example: idem_01H7abc12345

Client-supplied key making POST/PATCH operations idempotent (per PRD-03 §4.1). Repeated requests with the same key return the original response without executing again. Server retains the key for at least 24 hours.

Request Body schema: application/json
required
title
string
content
string <= 32768 characters
confidence
number [ 0 .. 1 ]
importance
number [ 0 .. 1 ]
object
expires_at
string or null <date-time>
freshness_date
string or null <date-time>

Responses

Request samples

Content type
application/json
{
  • "confidence": 0.9,
  • "importance": 0.7
}

Response samples

Content type
application/json
{
  • "id": "mem_01H7abc12345",
  • "tenant_id": "tn_01H7abc12345",
  • "agent_id": "ag_01H7abc12345",
  • "scope": "agent",
  • "type": "semantic",
  • "status": "active",
  • "title": "Customer prefers async support",
  • "content": "Customer cs_42 historically responds to email within 6h...",
  • "confidence": 0.9,
  • "importance": 0.7,
  • "metadata": { },
  • "created_at": "2026-05-01T10:00:00Z",
  • "updated_at": "2026-05-28T15:05:00Z",
  • "accessed_at": "2026-05-28T15:05:00Z"
}

Soft-delete a memory

Authorizations:
BearerAuth
path Parameters
id
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "error": {
    }
}

Semantic search across memories

Per PRD-02. Performs scope-aware semantic search across the caller's accessible memories (agent → team → institutional ascending). Results are ranked by composite score combining semantic similarity, confidence, and recency. The exact ranking signals may evolve; the request/response keys documented here are stable.

Authorizations:
BearerAuth
header Parameters
Idempotency-Key
string <= 255 characters
Example: idem_01H7abc12345

Client-supplied key making POST/PATCH operations idempotent (per PRD-03 §4.1). Repeated requests with the same key return the original response without executing again. Server retains the key for at least 24 hours.

Request Body schema: application/json
required
query
required
string non-empty

Natural-language search query.

scope
string
Enum: "agent" "team" "institutional"

Limit results to a specific scope. Default searches all accessible scopes.

memory_types
Array of strings
Items Enum: "episodic" "semantic" "procedural" "entity" "reflection" "reasoning"

Filter results by memory type (array form; replaces single-type filter).

limit
integer [ 1 .. 100 ]
Default: 10
min_score
number [ 0 .. 1 ]

Minimum similarity score (0..1) for returned memories.

Responses

Request samples

Content type
application/json
{
  • "query": "customer support preferences",
  • "scope": "agent",
  • "memory_types": [
    ],
  • "limit": 10,
  • "min_score": 0.5
}

Response samples

Content type
application/json
{
  • "results": [
    ],
  • "total": 1
}

Create a directed relationship between two memories

Creates a directed relationship from the memory in the path (id) to another memory (target_memory_id). The server enforces a closed enum for relationship_type — values outside the enum are rejected with HTTP 400 validation_error. Backed by MemoryHandler.CreateRelationship in api/internal/handlers/memory.go.

Valid relationship_type values:

  • caused_by
  • related_to
  • contradicts
  • supports
  • derived_from
  • part_of

strength and metadata are optional. If strength is omitted the server applies a default; if metadata is omitted it is stored as null.

Authorizations:
BearerAuth
path Parameters
id
required
string
Example: mem_01H7abc12345

Source memory id.

header Parameters
Idempotency-Key
string <= 255 characters
Example: idem_01H7abc12345

Client-supplied key making POST/PATCH operations idempotent (per PRD-03 §4.1). Repeated requests with the same key return the original response without executing again. Server retains the key for at least 24 hours.

Request Body schema: application/json
required
target_memory_id
required
string <uuid>

Target memory id (UUID). The source memory id is taken from the path parameter.

relationship_type
required
string
Enum: "caused_by" "related_to" "contradicts" "supports" "derived_from" "part_of"

Closed enum. The server validates this value against the list below and rejects any other value with HTTP 400 validation_error.

strength
number <double> [ 0 .. 1 ]

Optional edge weight in [0, 1]. Server applies a default if omitted (handler stores nil and the persistence layer chooses the default).

object or null

Optional freeform JSON object attached to the edge. May be omitted (sent as null) — the server stores either the object or no metadata.

Responses

Request samples

Content type
application/json
Example
{
  • "target_memory_id": "mem_neighbor1234",
  • "relationship_type": "derived_from",
  • "strength": 0.85,
  • "metadata": {
    }
}

Response samples

Content type
application/json
{
  • "id": "rel_01H7abc12345",
  • "tenant_id": "ten_01H7abc12345",
  • "source_memory_id": "mem_01H7abc12345",
  • "target_memory_id": "mem_neighbor1234",
  • "relationship_type": "derived_from",
  • "strength": 0.85,
  • "metadata": {
    },
  • "created_at": "2026-06-01T12:34:56Z"
}

List relationships for a memory (graph traversal)

Performs a breadth-first traversal of the memory graph starting at id and returns each reached memory along with its hop depth and the cumulative product of edge strengths along the traversal path.

Backed by MemoryHandler.ListRelationships in api/internal/handlers/memory.go. Returns the items the caller's tenant is permitted to see; tenant scoping is enforced server-side.

The count field is the number of items returned, not a paginated total.

Authorizations:
BearerAuth
path Parameters
id
required
string <uuid>
Example: mem_01H7abc12345

Source memory id (UUID).

query Parameters
depth
integer [ 1 .. 3 ]
Default: 1
Example: depth=1

Number of relationship hops to traverse. Server clamps to [1, 3]; values <= 0 default to 1, values > 3 are capped at 3.

Responses

Response samples

Content type
application/json
Example
{
  • "relationships": [
    ],
  • "count": 2
}

Delete a memory relationship

Removes a single directed relationship by its server-assigned id. Backed by MemoryHandler.DeleteRelationship in api/internal/handlers/memory.go. Tenant scoping is enforced server-side; the caller must be authenticated as an agent in the owning tenant.

Authorizations:
BearerAuth
path Parameters
id
required
string <uuid>
Example: mem_01H7abc12345

Source memory id (UUID).

rel_id
required
string <uuid>
Example: rel_01H7abc12345

Relationship id returned by createMemoryRelationship.

Responses

Response samples

Content type
application/json
{
  • "error": {
    }
}

List citations for a memory

Returns the Citation nodes linked to this memory via CITES edges in Neo4j (Phase 03 read path). Citations are written by the extraction pipeline when source documents are ingested (Phase 02 EXT-01).

Returns an empty citations array (with HTTP 200) for memories created manually without a source document — this is NOT an error condition.

Backed by SearchHandler.Citations in api/internal/search/handler.go, which calls the memory-bridge gRPC GetMemoryCitations RPC with a 2s deadline and falls back to Postgres lineage if the bridge is unavailable.

Authorizations:
BearerAuth
path Parameters
id
required
string <uuid>
Example: mem_01H7abc12345

Memory UUID.

Responses

Response samples

Content type
application/json
Example
{
  • "citations": [
    ],
  • "total": 1
}

Promote a memory's scope (agent → team or institutional)

Authorizations:
BearerAuth
path Parameters
id
required
string <uuid>
header Parameters
Idempotency-Key
string <= 255 characters
Example: idem_01H7abc12345

Client-supplied key making POST/PATCH operations idempotent (per PRD-03 §4.1). Repeated requests with the same key return the original response without executing again. Server retains the key for at least 24 hours.

Request Body schema: application/json
required
scope
required
string
Enum: "team" "institutional"

Target scope. Cannot be "agent" (only promotion supported).

team_id
string or null

Required when scope=team.

Responses

Request samples

Content type
application/json
Example
{
  • "scope": "team",
  • "team_id": "team_01H7abc12345"
}

Response samples

Content type
application/json
{
  • "id": "mem_01H7abc12345",
  • "tenant_id": "tn_01H7abc12345",
  • "agent_id": "ag_01H7abc12345",
  • "scope": "team",
  • "team_id": "team_01H7abc12345",
  • "type": "semantic",
  • "status": "active",
  • "title": "Customer prefers async support",
  • "content": "Customer cs_42 historically responds to email within 6h...",
  • "confidence": 0.85,
  • "importance": 0.6,
  • "metadata": { },
  • "created_at": "2026-05-01T10:00:00Z",
  • "updated_at": "2026-05-28T15:10:00Z",
  • "accessed_at": "2026-05-28T15:10:00Z"
}

List open merge proposals for the caller's tenant

Authorizations:
BearerAuth
query Parameters
offset
integer >= 0
Default: 0
limit
integer [ 1 .. 200 ]
Default: 50

Responses

Response samples

Content type
application/json
{
  • "proposals": [ ],
  • "total": 0
}

Propose merging two duplicate memories

Authorizations:
BearerAuth
Request Body schema: application/json
required
memory_a_id
required
string <uuid>

First memory in the proposed merge (must exist in the caller's tenant).

memory_b_id
required
string <uuid>

Second memory in the proposed merge (must differ from memory_a_id).

resolution_note
string or null

Optional free-text note explaining the proposal.

Responses

Request samples

Content type
application/json
{
  • "memory_a_id": "mem_01H7abc12345",
  • "memory_b_id": "mem_01H7def67890",
  • "resolution_note": "Both describe the same customer preference"
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "tenant_id": "string",
  • "proposer_user_id": "string",
  • "memory_a_id": "string",
  • "memory_b_id": "string",
  • "surviving_memory_id": "string",
  • "status": "open",
  • "proposed_at": "2019-08-24T14:15:22Z",
  • "resolved_at": "2019-08-24T14:15:22Z",
  • "resolved_by_user_id": "string",
  • "resolution_note": "string"
}

Resolve a merge proposal (org-admin only)

Resolves an open merge proposal, keeping surviving_memory_id and collapsing the other. Org-admin only — enforced at the REST layer (D-08). A non-admin caller receives 403, surfaced here as a tool error.

Authorizations:
BearerAuth
path Parameters
id
required
string <uuid>
Request Body schema: application/json
required
surviving_memory_id
required
string <uuid>

The memory to keep. Must match memory_a_id or memory_b_id.

resolution_note
string or null

Optional free-text note explaining the resolution.

merged_content
string or null

Optional merged text to apply to the surviving memory.

Responses

Request samples

Content type
application/json
{
  • "surviving_memory_id": "mem_01H7abc12345",
  • "resolution_note": "Kept the more complete record"
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "tenant_id": "string",
  • "proposer_user_id": "string",
  • "memory_a_id": "string",
  • "memory_b_id": "string",
  • "surviving_memory_id": "string",
  • "status": "open",
  • "proposed_at": "2019-08-24T14:15:22Z",
  • "resolved_at": "2019-08-24T14:15:22Z",
  • "resolved_by_user_id": "string",
  • "resolution_note": "string"
}

Reject a merge proposal (org-admin only)

Rejects an open merge proposal without collapsing either memory. Org-admin only — enforced at the REST layer (D-08). A non-admin caller receives 403, surfaced here as a tool error.

Authorizations:
BearerAuth
path Parameters
id
required
string <uuid>
Request Body schema: application/json
optional
resolution_note
string or null

Optional free-text note explaining the rejection.

Responses

Request samples

Content type
application/json
{
  • "resolution_note": "Not actually duplicates"
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "tenant_id": "string",
  • "proposer_user_id": "string",
  • "memory_a_id": "string",
  • "memory_b_id": "string",
  • "surviving_memory_id": "string",
  • "status": "open",
  • "proposed_at": "2019-08-24T14:15:22Z",
  • "resolved_at": "2019-08-24T14:15:22Z",
  • "resolved_by_user_id": "string",
  • "resolution_note": "string"
}

Reversibly invalidate a memory so it stops surfacing

Phase 04 R5. Reversible self-curation: sets the memory's invalid_at (invalidate-never-delete — the row is preserved) so it stops surfacing in current memory_search, but can be recovered within the reversibility window. This is NOT a hard delete (hard-delete/RTBF is a separate admin-gated path). Backed by MemoryHandler.Forget in api/internal/handlers/memory.go via the RetireOrMerger OpForget primitive.

Idempotent: re-calling on an already-invalidated memory returns HTTP 200 with invalid_at unchanged (no error, no second mutation). Winner-safe: forgetting a contradiction winner never resurrects the losers it invalidated. Requires memory_id (UUID).

Authorizations:
BearerAuth
path Parameters
id
required
string <uuid>

Memory UUID.

Responses

Response samples

Content type
application/json
{
  • "memory_id": "125896f9-d205-40e5-a9a8-a3e0b2b9450e",
  • "forgotten": true,
  • "invalid_at": "2019-08-24T14:15:22Z"
}

Return a memory's merge lineage and supersession trace

Phase 04 R6. Read-only provenance inspection. Returns the memory's merge_lineage rows (which memories were merged into or away from it) plus the SUPERSEDES/DERIVED_FROM graph trace from the memory-bridge. A freshly-created, never-merged/never-superseded memory returns HTTP 200 with an empty ancestor set (NOT 404) — an empty lineage is a valid answer, not an error. Backed by MemoryHandler.ExplainLineage in api/internal/handlers/memory.go. Requires memory_id (UUID).

Authorizations:
BearerAuth
path Parameters
id
required
string <uuid>

Memory UUID.

Responses

Response samples

Content type
application/json
{
  • "memory_id": "125896f9-d205-40e5-a9a8-a3e0b2b9450e",
  • "merge_lineage": [
    ],
  • "superseded": true,
  • "supersedes_target": "aabcdb89-2335-4e7a-91d6-b87d926d6653"
}

Knowledge

Document ingestion, listing, chunk inspection, citation lookup, and deletion.

Upload a document to the agent's knowledge base

Upload a document (PDF, DOCX, PPTX, XLSX, HTML, TXT, MD) to the agent's knowledge base. file_content must be standard base64-encoded bytes. Returns {accepted: true, document_id, status: "pending"} on 202. Use angareion_list_documents to poll for indexing status. Returns {accepted: false, error_code: "permission_denied"} when the agent lacks knowledge:write. Phase 02 D-09: optional sensitivity and audience fields; defaults applied server-side when absent.

Authorizations:
BearerAuth
Request Body schema: application/json
required
file_content
required
string

Standard base64-encoded bytes of the document.

filename
required
string

Original filename including extension.

mime_type
required
string
Enum: "application/pdf" "application/vnd.openxmlformats-officedocument.wordprocessingml.document" "application/vnd.openxmlformats-officedocument.presentationml.presentation" "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" "text/html" "text/markdown" "text/plain"

MIME type of the document.

sensitivity
string
Enum: "public" "internal" "confidential" "restricted"

Optional sensitivity label. Server defaults to "internal" when absent.

object

Optional 4-dimension audience tag JSONB. Format: {regions:[...], industries:[...], product_lines:[...], segments:[...]}. Server defaults to {} when absent.

Responses

Request samples

Content type
application/json
{
  • "file_content": "JVBERi0xLjQK...",
  • "filename": "architecture-guide.pdf",
  • "mime_type": "application/pdf"
}

Response samples

Content type
application/json
{
  • "accepted": true,
  • "document_id": "doc_01H7abc12345",
  • "status": "pending"
}

List all documents in the agent's tenant knowledge base

Flat list across all ingestion sources for the agent's tenant. Optional offset (default 0) and limit (default 20, max 100) for pagination. Returns {documents: [...], total}. Each document has document_id, filename, mime_type, status (pending|indexed|failed), ingested_at, ingestion_source_id, and ingestion_source_name.

Authorizations:
BearerAuth
query Parameters
offset
integer >= 0
Default: 0
limit
integer [ 1 .. 100 ]
Default: 20

Responses

Response samples

Content type
application/json
{
  • "documents": [
    ],
  • "total": 1
}

List the parsed chunks for a single document

Returns parsed chunks for the document ordered by chunk_index ascending. Requires source_id (UUID) and document_id (UUID). Optional offset (default 0) and limit (default 20, max 100). Each chunk has chunk_id, document_id, page_number, char_offset, char_length, text, and created_at. Use this to inspect what was extracted before searching or citing memories.

Authorizations:
BearerAuth
path Parameters
source_id
required
string <uuid>

Ingestion source UUID.

document_id
required
string <uuid>

Document UUID.

query Parameters
offset
integer >= 0
Default: 0
limit
integer [ 1 .. 100 ]
Default: 20

Responses

Response samples

Content type
application/json
{
  • "chunks": [
    ],
  • "total": 0
}

Delete a document and all its chunks from the knowledge base

Permanently deletes a document and all its chunks from the agent's knowledge base. Requires source_id (UUID) and document_id (UUID). Returns {deleted: true, document_id} on success. Returns {deleted: false, error_code: "not_found"} when the document does not exist (structured result, NOT an HTTP 404 error). Chunks are removed from Postgres and the corresponding Neo4j Chunk nodes are deleted by the gateway.

Authorizations:
BearerAuth
path Parameters
source_id
required
string <uuid>

Ingestion source UUID.

document_id
required
string <uuid>

Document UUID.

Responses

Response samples

Content type
application/json
Example
{
  • "deleted": true,
  • "document_id": "doc_01H7abc12345"
}

Return the full citation array for a memory

Returns every Document/Chunk the memory was derived from. Requires memory_id (UUID). Each citation has document_id, document_name, page, snippet, source_uri, confidence, version, and freshness{stale, stale_since}. Use this to verify provenance and surface source attribution to the user. Returns an empty citations array (HTTP 200) for memories created without a source document — this is NOT an error condition.

Authorizations:
BearerAuth
path Parameters
id
required
string <uuid>

Memory UUID.

Responses

Response samples

Content type
application/json
{
  • "citations": [
    ],
  • "total": 2
}

Specialists

Specialist preamble load, list, and session unload.

Load a specialist preamble by name

Returns the latest specialist preamble (system_prompt, memory_search_directives, output_format_rules, version_num) for the bound agent's tenant. Returns a structured {error: {code: "not_found"}} when no such specialist exists; {error: {code: "unavailable"}} after 3 retries on transport failure. Errors are returned as structured results — NOT HTTP error codes — so MCP clients can surface user-friendly retry guidance.

Authorizations:
BearerAuth
path Parameters
name
required
string

Specialist name (slug).

Responses

Response samples

Content type
application/json
Example
{
  • "name": "pmm-intel",
  • "version_num": 3,
  • "system_prompt": "You are a PMM intelligence assistant...",
  • "description": "Surfaces market intelligence for PMMs"
}

List all specialists available to the bound agent's tenant

Returns all specialists ordered alphabetically by the server (do not re-sort on the client). Each specialist has name, version_num, description, and updated_at.

Authorizations:
BearerAuth

Responses

Response samples

Content type
application/json
{
  • "specialists": [
    ]
}

Clear the server-side session record for a loaded specialist

Removes the server-side session record for a (agent, specialist) pair. This is observability bookkeeping only — it does NOT remove the specialist's preamble from the current conversation context; those instructions are already in the conversation and keep applying. To stop following a specialist, load a different one (its reset clause supersedes the previous preamble) or start a fresh session. Idempotent — returns success even if no session was recorded. Phase 04.5 D-17 / SPEC R14.

Authorizations:
BearerAuth
path Parameters
name
required
string

Specialist name (slug).

Responses

Response samples

Content type
application/json
{
  • "unloaded": true,
  • "name": "pmm-intel"
}

Compose

LLM synthesis composition for workflow runs.

Compose an LLM synthesis for a workflow run

Retrieves memory context (excluding sensitivity=confidential per SPEC P1), calls the tenant's LLM with prompt caching on the shared prefix, and returns a draft text plus cited memory IDs. Required: template_id (workflow template slug, v1: "launch-a-feature"), run_id (UUID identifying this workflow run — same run_id twice returns duplicate_run error). Optional: context_memory_ids ([]string of memory UUIDs to consider), launch_brief_text (description of the feature being launched), prompt_id (reserved for future recipes; leave empty for v1). On SPEC R6 duplicate_run, returns error code=duplicate_run.

Authorizations:
BearerAuth
Request Body schema: application/json
required
template_id
required
string

Workflow template slug (v1 value: "launch-a-feature").

run_id
required
string <uuid>

UUID identifying this workflow run. Submitting the same run_id twice while a compose is in flight returns a 409 duplicate_run response.

context_memory_ids
Array of strings <uuid> [ items <uuid > ]

Optional list of memory UUIDs to include as additional context.

launch_brief_text
string

Optional free-text description of the feature or topic being composed. Used as part of the prompt context.

prompt_id
string

Reserved for future recipe variants; leave empty for v1.

Responses

Request samples

Content type
application/json
{
  • "template_id": "launch-a-feature",
  • "run_id": "550e8400-e29b-41d4-a716-446655440000",
  • "launch_brief_text": "Announcing the new analytics dashboard for PMMs"
}

Response samples

Content type
application/json
{
  • "draft_text": "We are thrilled to announce...",
  • "cited_memory_ids": [
    ]
}

Handoffs

Cross-LLM session handoff — named, agent-scoped snapshots of working state saved in one LLM client and resumed in another. Every route here is agent-scoped and fails closed: a caller without an agent identity in its JWT receives 401, including an org-user token.

Save working state under a name

Persists a named snapshot of working state for the calling agent. Saving to a name that already exists overwrites the prior payload for that name in place and increments version_num; the prior payload is not retained.

Extraction is client-side: the gateway never receives a transcript, so the payload supplied here is everything a resuming session will have.

tenant_id and agent_id are read from the JWT and cannot be supplied in the body. Unknown top-level keys are rejected with 400.

Authorizations:
BearerAuth
Request Body schema: application/json
required
name
required
string

Short, human-typeable, and reusable across the life of the work. Saving to an existing name overwrites that name's payload in place.

summary
string

One-line description of what this working state covers.

object

The structured working state. The properties below are the KNOWN fields — they are validated for renderability, and unrecognised fields are preserved untouched rather than rejected, so client-side extraction can add fields without a server release.

blockers and each decisions[].rationale are copied verbatim from the session by the extracting client and are never re-summarised.

Array of objects

Memory IDs already known to be relevant to this work. Each entry is an OBJECT, not a bare UUID: the server snapshots each cited memory's title at save time and stores it alongside the ID so the two cannot drift apart.

A client-supplied title is accepted and ignored — the stored title is always the server's snapshot. Accepting the field keeps a read-modify-write cycle over a previously-returned handoff working.

A citation whose memory does not resolve is stored with an empty title and the save still succeeds.

artifacts
Array of strings

File paths, URLs, and branch names touched by this work. Stored as supplied and never validated for inner structure, so a client may send richer entries than the documented string form.

origin_client
string

Identifier of the surface that saved this handoff, for example claude-code. Each surface sets a fixed literal for itself.

scope
string
Default: "agent"
Value: "agent"

agent is the only value accepted in v1. A team value is rejected with 400 before anything is persisted; team-scoped handoff sharing is not available in v1.

Responses

Request samples

Content type
application/json
{
  • "name": "q3-pricing",
  • "summary": "Reworking the Q3 pricing page copy and the tier table",
  • "payload": {
    },
  • "citations": [
    ],
  • "artifacts": [],
  • "origin_client": "claude-code",
  • "scope": "agent"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "summary": "string",
  • "payload": { },
  • "citations": [
    ],
  • "artifacts": [
    ],
  • "origin_client": "string",
  • "scope": "agent",
  • "version_num": 0,
  • "pinned_at": "2019-08-24T14:15:22Z",
  • "last_resumed_at": "2019-08-24T14:15:22Z",
  • "expires_at": "2019-08-24T14:15:22Z",
  • "created_at": "2019-08-24T14:15:22Z",
  • "updated_at": "2019-08-24T14:15:22Z"
}

List or search the calling agent's handoffs

Returns the calling agent's own handoffs, most-recently-saved first.

With q absent this is a plain listing. With q present the same response shape is returned, narrowed by a merged keyword and semantic match over saved names and summaries.

An empty array is a normal, successful result: it means this agent has no saved handoffs, not that anything failed.

Authorizations:
BearerAuth
query Parameters
q
string

Optional free-text term. When present, results are narrowed by a merged keyword and semantic match instead of being a plain listing.

limit
integer [ 1 .. 200 ]
Default: 50
offset
integer >= 0
Default: 0

Applies to the plain listing only. The searched branch is bounded by limit and does not paginate.

Responses

Response samples

Content type
application/json
[ ]

Resume previously saved working state

Resolves a handoff and returns its rendered brief. Resolution tries an exact name match first, then an ID match, then a semantic match over saved names and summaries.

This operation has TWO distinct 200 shapes, told apart by the response Content-Type header:

Content-Type Meaning
text/markdown; charset=utf-8 A unique match. The body is the brief itself, and the handoff was resumed — its last-resumed timestamp is stamped and its expiry reset to a full TTL.
application/json Ambiguous. The body is a candidate list and NOTHING was resumed. Present the choices to the user and resume the chosen one by name or id.

A literal resume is never treated as a handoff name: this is a fixed route segment, so a saved handoff named resume is reached by ID.

Authorizations:
BearerAuth
Request Body schema: application/json
required
query
required
string

An exact handoff name, a handoff UUID, or a free-text description of the work in your own words when the exact name is not known.

Responses

Request samples

Content type
application/json
Example
{
  • "query": "q3-pricing"
}

Response samples

Content type
No sample

Get one handoff by id

Scoped to the caller's tenant AND agent. Another agent's handoff is reported as 404, identical to one that does not exist, so IDs cannot be probed.

Authorizations:
BearerAuth
path Parameters
id
required
string <uuid>

Handoff UUID.

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "summary": "string",
  • "payload": { },
  • "citations": [
    ],
  • "artifacts": [
    ],
  • "origin_client": "string",
  • "scope": "agent",
  • "version_num": 0,
  • "pinned_at": "2019-08-24T14:15:22Z",
  • "last_resumed_at": "2019-08-24T14:15:22Z",
  • "expires_at": "2019-08-24T14:15:22Z",
  • "created_at": "2019-08-24T14:15:22Z",
  • "updated_at": "2019-08-24T14:15:22Z"
}

Delete a handoff

Removes the handoff from the relational store and its vector point from the handoffs collection in the same request.

Authorizations:
BearerAuth
path Parameters
id
required
string <uuid>

Handoff UUID.

Responses

Response samples

Content type
application/json
{
  • "error": {
    }
}

Export the rendered brief for one handoff

Returns the deterministic Markdown brief — byte-for-byte the same bytes a successful resume returns. Exporting does NOT resume: no timestamp is stamped and no expiry is reset. The audit trail records this as an export, distinct from a resume.

Authorizations:
BearerAuth
path Parameters
id
required
string <uuid>

Handoff UUID.

Responses

Response samples

Content type
application/json
{
  • "error": {
    }
}

Pin a handoff, exempting it from TTL reaping

A pinned handoff survives the expiry reaper indefinitely until it is unpinned or deleted.

Authorizations:
BearerAuth
path Parameters
id
required
string <uuid>

Handoff UUID.

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "summary": "string",
  • "payload": { },
  • "citations": [
    ],
  • "artifacts": [
    ],
  • "origin_client": "string",
  • "scope": "agent",
  • "version_num": 0,
  • "pinned_at": "2019-08-24T14:15:22Z",
  • "last_resumed_at": "2019-08-24T14:15:22Z",
  • "expires_at": "2019-08-24T14:15:22Z",
  • "created_at": "2019-08-24T14:15:22Z",
  • "updated_at": "2019-08-24T14:15:22Z"
}

Unpin a handoff, returning it to normal TTL treatment

Authorizations:
BearerAuth
path Parameters
id
required
string <uuid>

Handoff UUID.

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "summary": "string",
  • "payload": { },
  • "citations": [
    ],
  • "artifacts": [
    ],
  • "origin_client": "string",
  • "scope": "agent",
  • "version_num": 0,
  • "pinned_at": "2019-08-24T14:15:22Z",
  • "last_resumed_at": "2019-08-24T14:15:22Z",
  • "expires_at": "2019-08-24T14:15:22Z",
  • "created_at": "2019-08-24T14:15:22Z",
  • "updated_at": "2019-08-24T14:15:22Z"
}