For the complete documentation index, see llms.txt. This page is also available as Markdown.

Runs

Browse conversation runs and best-effort projected framework history, inspect structural trajectories, and control channel-aware operator takeover by run ID.

The unified runs endpoint is the public browse surface for conversation runs across voice, text, SMS, email, and web, plus terminal framework runs that reached the durable projection. Framework-run projection is best-effort, so this endpoint is not a live or guaranteed-complete framework-run ledger. Use kind=framework to browse the projected framework history.

Live voice entries come from a best-effort active-call overlay. A live call can appear late or be temporarily absent when that source is unavailable. A terminal conversation record can become available after persistence succeeds, but clients should not treat the live listing as a complete audit ledger.

List Runs

Returns a paginated, newest-first list of conversation runs and projected terminal framework runs under one contract.

List runs (framework + conversation)

get

Paginated, newest-first list of runs for the workspace behind the unified Run contract. Federates framework runs (Delta world.runs MV) and conversation runs (Lakebase world.conversations) at read time. Filter by kind (conversation / framework), channel (voice/text/sms/email/web — conversation runs only), and status (live expands to running + paused). continuation_token is an opaque page cursor.

Authorizations
AuthorizationstringRequired

API key issued via POST /v1/{workspace_id}/api-keys. Pass the returned api_key value as a Bearer token.

Path parameters
workspace_idstring · uuidRequired
Query parameters
sort_bystring[]OptionalDefault: []
limitinteger · max: 200OptionalDefault: 50
continuation_tokenanyOptional
Responses
200

Successful Response

application/json
has_morebooleanRequired
continuation_tokenanyOptional
get/v1/{workspace_id}/runs
GET /v1/{workspace_id}/runs HTTP/1.1
Host: api.platform.amigo.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
  "items": [
    {
      "run_id": "123e4567-e89b-12d3-a456-426614174000",
      "workspace_id": "123e4567-e89b-12d3-a456-426614174000",
      "kind": "conversation",
      "status": "running",
      "channel": "voice",
      "framework": "claude-agent-sdk",
      "entity_id": "123e4567-e89b-12d3-a456-426614174000",
      "service_id": "123e4567-e89b-12d3-a456-426614174000",
      "started_at": "2026-01-01T00:00:00.000Z",
      "ended_at": "2026-01-01T00:00:00.000Z",
      "entity_name": "text",
      "service_name": "text",
      "caller_id": "text",
      "phone_number": "text",
      "direction": "text",
      "turn_count": 1,
      "completion_reason": "text",
      "source_call_sid": "text",
      "source_conversation_id": "123e4567-e89b-12d3-a456-426614174000",
      "source_framework_run_id": "123e4567-e89b-12d3-a456-426614174000",
      "takeover": {
        "eligible": true,
        "mode_options": [
          "listen"
        ],
        "reason": "text"
      }
    }
  ],
  "has_more": true,
  "continuation_token": null
}

Authentication

Workspace API key (bearer token) or operator identity token. The bearer's workspace must match the path workspace.

Status Mapping

The status field on each run is a canonical value derived from the underlying source:

  • Framework runs: Terminal status is projected on a best-effort basis. A framework run may be absent if its terminal projection was not recorded.

  • Conversation runs (voice): An active call with no completion reason maps to running. A timed-out call maps to timed_out. Calls that ended due to errors or no audio map to failed. All other completed calls map to completed.

  • Conversation runs (non-voice): Active or in-progress conversations map to running. Closed or completed conversations map to completed. Failed conversations map to failed.

The virtual live status filter expands to running + paused, returning active conversation runs. Projected framework history is terminal-only.

Example Request

Example Response

Error Responses

Status
Condition

403 Forbidden

Bearer workspace does not match the path workspace.

422 Unprocessable Entity

Invalid query parameter (unsupported sort_by field, invalid continuation_token, etc.).

502 Bad Gateway

Run data is temporarily unavailable.

Runs Summary

Summarizes the same unified inventory. Repeated kind and channel filters use OR semantics, and a channel filter restricts results to conversation runs.

Run counts (framework + conversation)

get

Aggregate counts for the workspace's runs behind the unified Run contract: total, live (running + paused), each canonical status, a full by_status map, and by_kind (conversation vs framework). Federates the Delta world.runs MV and Lakebase world.conversations with a cheap GROUP BY. Optional kind / channel filters mirror the list; a channel filter restricts to conversation runs.

Authorizations
AuthorizationstringRequired

API key issued via POST /v1/{workspace_id}/api-keys. Pass the returned api_key value as a Bearer token.

Path parameters
workspace_idstring · uuidRequired
Query parameters
Responses
200

Successful Response

application/json

Aggregate run counts for the Runs page summary strip.

Honest workspace totals the paginated list cannot derive client-side (it only holds the loaded page). by_status carries the full canonical breakdown (incl. any status beyond the named convenience fields); by_kind splits framework vs conversation. live = running + paused.

totalintegerRequired
liveintegerRequired
runningintegerRequired
pausedintegerRequired
completedintegerRequired
failedintegerRequired
timed_outintegerRequired
get/v1/{workspace_id}/runs/summary
GET /v1/{workspace_id}/runs/summary HTTP/1.1
Host: api.platform.amigo.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
  "total": 1,
  "live": 1,
  "running": 1,
  "paused": 1,
  "completed": 1,
  "failed": 1,
  "timed_out": 1,
  "by_status": {
    "ANY_ADDITIONAL_PROPERTY": 1
  },
  "by_kind": {
    "ANY_ADDITIONAL_PROPERTY": 1
  }
}

Get a Run

Returns one available framework or conversation run. Framework results are limited to terminal runs that reached the best-effort projection. The workspace-scoped run_id is channel-neutral; inspect kind, channel, and the source_* fields to decide whether to open conversation detail, call detail, or framework trajectory next. Returns 404 when the run does not exist in the workspace.

Get one run (framework or conversation) by run_id

get

Resolve a single run by its channel-neutral run_id and return the canonical Run — at any status (live, completed, failed, timed out). Federates the Delta world.runs MV (framework runs), Lakebase world.conversations (conversation runs), and the live-voice registry, matched by run_id and scoped to the workspace. Use the returned kind / channel / source_* fields to open the channel-appropriate detail (voice call, text conversation, framework trace). 404 if the run does not exist in this workspace.

Authorizations
AuthorizationstringRequired

API key issued via POST /v1/{workspace_id}/api-keys. Pass the returned api_key value as a Bearer token.

Path parameters
workspace_idstring · uuidRequired
run_idstring · uuidRequired
Responses
200

Successful Response

application/json

One item in the canonical unified Runs read model.

run_id is a dedicated UUID (not an overloaded call_sid / conversation_id); the originating subsystem's ids are kept as source_* provenance fields so a run can always be traced back to its channel/framework origin. Conversation runs carry a channel and no framework; framework runs carry a framework and no channel — enforced below.

run_idstring · uuidRequired
workspace_idstring · uuidRequired
kindstring · enumRequiredPossible values:
statusstring · enumRequiredPossible values:
channelstring · enum · nullableOptionalPossible values:
frameworkstring · enum · nullableOptionalPossible values:
entity_idstring · uuid · nullableOptional
service_idstring · uuid · nullableOptional
started_atstring · date-timeRequired
ended_atstring · date-time · nullableOptional
entity_namestring · nullableOptional
service_namestring · nullableOptional
caller_idstring · nullableOptional
phone_numberstring · nullableOptional
directionstring · nullableOptional
turn_countinteger · nullableOptional
completion_reasonstring · nullableOptional
source_call_sidstring · nullableOptional
source_conversation_idstring · uuid · nullableOptional
source_framework_run_idstring · uuid · nullableOptional
get/v1/{workspace_id}/runs/{run_id}
GET /v1/{workspace_id}/runs/{run_id} HTTP/1.1
Host: api.platform.amigo.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
  "run_id": "123e4567-e89b-12d3-a456-426614174000",
  "workspace_id": "123e4567-e89b-12d3-a456-426614174000",
  "kind": "conversation",
  "status": "running",
  "channel": "voice",
  "framework": "claude-agent-sdk",
  "entity_id": "123e4567-e89b-12d3-a456-426614174000",
  "service_id": "123e4567-e89b-12d3-a456-426614174000",
  "started_at": "2026-01-01T00:00:00.000Z",
  "ended_at": "2026-01-01T00:00:00.000Z",
  "entity_name": "text",
  "service_name": "text",
  "caller_id": "text",
  "phone_number": "text",
  "direction": "text",
  "turn_count": 1,
  "completion_reason": "text",
  "source_call_sid": "text",
  "source_conversation_id": "123e4567-e89b-12d3-a456-426614174000",
  "source_framework_run_id": "123e4567-e89b-12d3-a456-426614174000",
  "takeover": {
    "eligible": true,
    "mode_options": [
      "listen"
    ],
    "reason": "text"
  }
}

Get a Framework Trajectory

Returns ordered structural steps for a framework run. Check truncated before treating the returned sequence as complete.

Returns 404 when the run does not exist and 409 when the run is a conversation run. Use conversation detail for per-turn conversation history.

Get a framework run's step-by-step trajectory

get

Ordered structural steps (perception / decision / tool / completion) of a FRAMEWORK run, read from the durable Delta trace source by the run's correlation id. 404 if the run does not exist in this workspace; 409 if the run is a conversation run (use /conversations/{id} for per-turn detail).

Authorizations
AuthorizationstringRequired

API key issued via POST /v1/{workspace_id}/api-keys. Pass the returned api_key value as a Bearer token.

Path parameters
workspace_idstring · uuidRequired
run_idstring · uuidRequired
Responses
200

Successful Response

application/json
truncatedbooleanRequired
get/v1/{workspace_id}/runs/{run_id}/trajectory
GET /v1/{workspace_id}/runs/{run_id}/trajectory HTTP/1.1
Host: api.platform.amigo.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
  "steps": [
    {
      "seq": 1,
      "kind": "text",
      "actor": "text",
      "state": "text",
      "tool_name": "text",
      "tool_input_summary": "text",
      "tool_result_summary": "text",
      "tool_succeeded": true,
      "decision_from_state": "text",
      "decision_to_state": "text",
      "effective_at": "text"
    }
  ],
  "truncated": true
}

Takeover Eligibility

Every run carries a server-computed takeover object that tells a caller whether an operator can act on the run now. Clients should use this field instead of recreating channel and status rules.

Live voice runs expose listen and takeover. Live text, SMS, email, and web runs expose takeover only; an operator drives those channels by staging authored turns rather than joining a live media stream. Framework and non-live runs are not eligible.

Operator Takeover

An operator can take over a live run and hand it back by channel-neutral run_id. Voice takeover uses a live media session and supports listen or drive mode. Text, SMS, email, and web takeover pauses the agent while the operator stages the next outbound turn.

All six operations below require Operator:Update, which the operator, admin, and owner roles carry. The operator_id in the body must match the authenticated operator; impersonation is rejected.

Take Over a Run

Registers the operator on a live run. In takeover mode the agent is suspended so the human drives; in listen mode the operator monitors without driving. Non-voice channels support takeover mode only.

Take over a live run as operator

post

Register the caller's operator identity on a LIVE run and (in takeover mode) suspend the agent so the human drives; listen mode monitors without driving. Addressed by the channel-neutral run_id. Requires admin (Operator:Update), bound to the caller's own operator identity (no impersonation). 404 if the run is not live in this workspace; 409 if its channel does not support live takeover yet. For voice, the response carries the conference/participant SIDs the console needs to attach browser audio.

Authorizations
AuthorizationstringRequired

API key issued via POST /v1/{workspace_id}/api-keys. Pass the returned api_key value as a Bearer token.

Path parameters
workspace_idstring · uuidRequired
run_idstring · uuidRequired
Body
operator_idstring · uuidRequired
modestring · enumOptionalDefault: takeoverPossible values:
Responses
200

Successful Response

application/json
run_idstring · uuidRequired
modestring · enumRequiredPossible values:
participant_call_sidstring · nullableOptional
conference_sidstring · nullableOptional
post/v1/{workspace_id}/runs/{run_id}/takeover
POST /v1/{workspace_id}/runs/{run_id}/takeover HTTP/1.1
Host: api.platform.amigo.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 72

{
  "operator_id": "123e4567-e89b-12d3-a456-426614174000",
  "mode": "takeover"
}
{
  "run_id": "123e4567-e89b-12d3-a456-426614174000",
  "mode": "listen",
  "participant_call_sid": "text",
  "conference_sid": "text"
}

Hand a Run Back

Releases the operator from the run. For non-voice channels, the stored status moves from paused back to active; for voice, the operator leaves the live media session and the agent is resumed. Subsequent behavior uses whatever conversation state and takeover evidence the runtime successfully retained; the handback response does not guarantee a complete transcript of operator activity.

Hand a taken-over run back to the agent

post

Release the caller's operator from a run they took over — the agent resumes. Addressed by run_id. Requires admin (Operator:Update), bound to the caller's own operator identity. 404 if the run is not live in this workspace; 409 if its channel does not support live takeover yet.

Authorizations
AuthorizationstringRequired

API key issued via POST /v1/{workspace_id}/api-keys. Pass the returned api_key value as a Bearer token.

Path parameters
workspace_idstring · uuidRequired
run_idstring · uuidRequired
Body
operator_idstring · uuidRequired
Responses
200

Successful Response

application/json
run_idstring · uuidRequired
successbooleanRequired
post/v1/{workspace_id}/runs/{run_id}/handback
POST /v1/{workspace_id}/runs/{run_id}/handback HTTP/1.1
Host: api.platform.amigo.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 54

{
  "operator_id": "123e4567-e89b-12d3-a456-426614174000"
}
{
  "run_id": "123e4567-e89b-12d3-a456-426614174000",
  "success": true
}

Author a Non-Voice Turn

Stages the next operator-authored reply on a taken-over text, SMS, email, or web run. A run can hold one pending authored reply; staging another before it is consumed replaces the earlier text. The reply is consumed before downstream delivery completes, so a later delivery failure does not restore that pending value automatically. This is not an exactly-once delivery guarantee. Wait for a staged turn to be consumed before staging another.

Voice runs return 409 because the operator drives them through live audio.

Author the next turn on a non-voice run under takeover

post

Stage an operator-authored reply for a NON-voice run (text/sms/email/web) the caller has taken over. The agent-engine send-gate substitutes it for the agent's next outbound (exactly-once), so the caller receives the operator's words while the agent stays suspended. Repeatable — each call stages the next turn. Addressed by the channel-neutral run_id. Requires admin (Operator:Update), bound to the caller's own operator identity (no impersonation). 404 if the run is not live in this workspace; 409 for voice (voice takeover drives the live audio leg — use the conference, not an authored turn).

Authorizations
AuthorizationstringRequired

API key issued via POST /v1/{workspace_id}/api-keys. Pass the returned api_key value as a Bearer token.

Path parameters
workspace_idstring · uuidRequired
run_idstring · uuidRequired
Body
operator_idstring · uuidRequired
textstring · min: 1 · max: 4000Required
Responses
200

Successful Response

application/json
run_idstring · uuidRequired
stagedbooleanRequired
post/v1/{workspace_id}/runs/{run_id}/authored-turn
POST /v1/{workspace_id}/runs/{run_id}/authored-turn HTTP/1.1
Host: api.platform.amigo.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 68

{
  "operator_id": "123e4567-e89b-12d3-a456-426614174000",
  "text": "text"
}
{
  "run_id": "123e4567-e89b-12d3-a456-426614174000",
  "staged": true
}

Switch Mode

Toggles an operator who has already joined a voice run between listen and takeover. Non-voice runs return 409 because they support authored-turn takeover only.

Switch an operator between listen and takeover on a live run

post

Toggle the operator between listen (monitor) and takeover (drive) on a run they have already joined, addressed by the channel-neutral run_id. For voice this mutes/unmutes the operator's conference participant. Requires admin (Operator:Update), bound to the caller's own operator identity (no impersonation). 404 if the run is not live in this workspace; 409 if its channel does not support live takeover yet.

Authorizations
AuthorizationstringRequired

API key issued via POST /v1/{workspace_id}/api-keys. Pass the returned api_key value as a Bearer token.

Path parameters
workspace_idstring · uuidRequired
run_idstring · uuidRequired
Body
operator_idstring · uuidRequired
participant_call_sidstring · max: 64Required
modestring · enumRequiredPossible values:
Responses
200

Successful Response

application/json
run_idstring · uuidRequired
modestring · enumRequiredPossible values:
post/v1/{workspace_id}/runs/{run_id}/switch-mode
POST /v1/{workspace_id}/runs/{run_id}/switch-mode HTTP/1.1
Host: api.platform.amigo.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 100

{
  "operator_id": "123e4567-e89b-12d3-a456-426614174000",
  "participant_call_sid": "text",
  "mode": "listen"
}
{
  "run_id": "123e4567-e89b-12d3-a456-426614174000",
  "mode": "listen"
}

Mint a Browser-Audio Access Token

Mints browser-audio credentials used to attach an operator to a live voice run. Non-voice runs return 409.

Mint a browser-audio access token for an operator on a live run

post

Generate the Twilio browser-audio credentials the console needs to attach the operator's WebRTC leg to a live run, addressed by run_id. This is the media plane companion to /takeover (the control plane). Requires admin (Operator:Update), bound to the caller's own operator identity. 404 if the run is not live in this workspace; 409 if its channel has no browser-audio leg.

Authorizations
AuthorizationstringRequired

API key issued via POST /v1/{workspace_id}/api-keys. Pass the returned api_key value as a Bearer token.

Path parameters
workspace_idstring · uuidRequired
run_idstring · uuidRequired
Body
operator_idstring · uuidRequired
Responses
200

Successful Response

application/json
tokenstringRequired
identitystringRequired
conference_sidstring · nullableOptional
post/v1/{workspace_id}/runs/{run_id}/access-token
POST /v1/{workspace_id}/runs/{run_id}/access-token HTTP/1.1
Host: api.platform.amigo.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 54

{
  "operator_id": "123e4567-e89b-12d3-a456-426614174000"
}
{
  "token": "text",
  "identity": "text",
  "conference_sid": "text",
  "connect_params": {
    "ANY_ADDITIONAL_PROPERTY": "text"
  }
}

Send Guidance

Sends text guidance to a live voice run. Guidance is delivered as a prioritized instructional event that can interrupt current agent speech, unlike a factual external event, which queues behind current speech. The returned delivery status does not guarantee exact response timing or that the model follows the instruction verbatim. Non-voice channels return 409; use authored-turn takeover when an operator must send a reply.

The audit record captures the run, channel, operator identity, and a content fingerprint, never the raw guidance text.

Send operator guidance to a live run

post

Send text guidance to the agent handling a LIVE run, addressed by the channel-neutral run_id. The agent incorporates it into its next response without the operator taking over. Requires admin (Operator:Update) and is bound to the caller's own operator identity (no impersonation). 404 if the run is not a live run in this workspace; 409 if its channel has no live guidance transport yet.

Authorizations
AuthorizationstringRequired

API key issued via POST /v1/{workspace_id}/api-keys. Pass the returned api_key value as a Bearer token.

Path parameters
workspace_idstring · uuidRequired
run_idstring · uuidRequired
Body

Operator guidance for a live run. operator_id is in the body because this router is not under /operators/{operator_id} — it is bound to the authenticated caller by _enforce_operator_identity (no impersonation).

operator_idstring · uuidRequired
messagestring · min: 1 · max: 5000Required
Responses
200

Successful Response

application/json
statusstring · enumRequired

Delivery status

Possible values:
run_idstring · uuidRequired

Run the guidance was sent to

post/v1/{workspace_id}/runs/{run_id}/guidance
POST /v1/{workspace_id}/runs/{run_id}/guidance HTTP/1.1
Host: api.platform.amigo.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 71

{
  "operator_id": "123e4567-e89b-12d3-a456-426614174000",
  "message": "text"
}
{
  "status": "delivered",
  "run_id": "123e4567-e89b-12d3-a456-426614174000"
}

Agent Forge CLI

Agent Forge v0.1.44+ exposes the unified read surface:

Add --json for the raw response. The CLI accepts one value per filter flag and prints --continuation-token when another page is available; pass that token unchanged to the next run list call. The REST API itself supports repeated filter values.

Rate Limits

Each list, summary, detail, and trajectory operation allows 60 requests per minute. Each takeover, handback, authored-turn, mode-switch, access-token, and guidance operation allows 10 requests per minute. Limits are enforced per authenticated credential and operation. Successful limit checks return X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset; a 429 response also returns Retry-After.

Last updated

Was this helpful?