Skip to content

Agent API

Early

This API is used by our own agent instances today. It will change; we will version it before a third party depends on it.

Base URL: https://app.olsie.ai. Every call carries a tenant agent token: Authorization: Bearer olsie_…. Tokens are minted per workspace and stored hashed; a token can only touch its own workspace.

POST /api/agent/ingest

An agent reports what it did. Idempotent on (agent, externalId).

{
  "agent": "gro",
  "events": [
    { "type": "heartbeat", "channelLabel": "Discord #growth-ops" },
    { "type": "approval", "externalId": "a1b2c3d4", "title": "google_ads_mutate: add 12 negatives", "status": "pending", "detail": { "input": { } } },
    { "type": "job", "externalId": "weekly-digest-2026-09-05T08:30", "kind": "scheduled", "summary": "Weekly digest posted", "status": "done", "costPence": 34 }
  ]
}

Event types: heartbeat (marks the agent active), approval (pending | approved | declined | expired), job (running | done | failed, with optional tokensIn, tokensOut, costPence, startedAt, finishedAt). Everything lands in the audit trail.

POST /api/agent/secret

{ "name": "CLOUDFLARE_TOKEN", "agent": "heimdall" }

Returns { "ok": true, "value": "…" } for the calling workspace only, and records secret.used in the audit. This is the only path by which a value leaves the vault, and it is called by a tool, never by the model.

GET /api/agent/approvals?agent=gro

Decisions made in the pane that the agent has not yet acted on:

{ "ok": true, "decisions": [ { "id": "…", "externalId": "a1b2c3d4", "status": "approved", "decidedAt": "…" } ] }

The agent treats approved exactly like a ✅ in its channel, then acknowledges with POST /api/agent/approvals { "ids": ["…"] }.

Errors

401 bad or missing token · 400 malformed body · 404 secret not set. Bodies are { "ok": false, "error": "…" }.