Skip to main content
Browse the documentation

Platform concepts

Runs

A run is one piece of work an agent does — how to start one, follow it live, answer it when it stops for you, and pick it up again.

Every time an agent works, the platform records a run: the input, each step, the tools called, the cost and the result. Chat messages, schedules, missions and inbound webhooks all start runs, and so can you, through the API. Runs are asynchronous: creating one queues it and answers at once, and you follow the work by streaming its events, waiting on it, or reading it back.

The life of a run

A run's status tells you where it is.

StatusWhat it means
queuedAccepted and waiting to execute.
runningThe agent is working.
pausedStopped at a step boundary until someone resumes it.
awaiting_approvalA tool call needs a person's decision before it goes ahead.
awaiting_inputThe agent asked a question and is waiting for the answer.
completedFinished; output holds the result.
failed, cancelled, timeout, guardrail_blockedEnded without a normal result; error_code says why.

Start a run

Send the agent's id and an input. message is the conventional field; file_ids attaches up to 20 files you uploaded earlier.

curl -X POST https://api.snaga.ai/api/v1/runs \
  -H "Authorization: Bearer $SNAGA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "agent_id": "<agent_id>",
    "input": { "message": "Summarise this week's support tickets" },
    "resource_limits": { "max_steps": 20, "max_cost_usd": 1.5 }
  }'

The answer is 202 with the run and its run_id. The Idempotency-Key makes a retried request return the same run instead of a second one.

version pins a specific agent version instead of the current one. resource_limits tightens this run's limits — max_duration_ms, max_steps, max_tool_calls, max_tokens_per_run, max_cost_usd — and any other key is refused with 422. A run that crosses max_cost_usd fails with error_code: BUDGET_EXCEEDED.

To see what a run is likely to cost before starting it, call POST /api/v1/runs/estimate. It looks at the agent's recent runs and stores nothing. When it answers pricing: "unknown", the 0 it returns means "no known rate", not "free".

Follow it live

GET /api/v1/runs/{runId}/events is a server-sent event stream. Each frame's event name is the event type (run.started, llm.chunk, tool.call, run.completed …), its id is the event's sequence number, and its data carries a stream_type you can filter on: lifecycle, assistant (the streamed text), tool or other.

curl -N https://api.snaga.ai/api/v1/runs/<run_id>/events \
  -H "Authorization: Bearer $SNAGA_API_KEY"

If the connection drops, reconnect with the Last-Event-ID header and the stream continues from there. When the run ends the server sends a final done event and closes the stream.

A browser EventSource cannot set an Authorization header. Mint a short-lived token with POST /api/v1/auth/sse-tokens (valid for 60 seconds) and pass it as ?token=.

Prefer not to stream?

  • GET /api/v1/runs/{runId}/wait?timeout_sec=60 returns the run as soon as it ends. If time runs out first it answers 202 with status: still_running — call it again.
  • GET /api/v1/runs/{runId} returns the run at any moment.

When a run stops for you

Some tools need a person's approval, and an agent can ask a question. In both cases the run waits, and GET /api/v1/runs/{runId} tells you what it is waiting for, so a client can rebuild the prompt even if its stream dropped.

awaiting_approval — the run carries pending_approvals: each blocked tool call with its name and args. You have three answers:

CallEffect
POST /api/v1/runs/{runId}/approveThe action goes ahead. The body is optional; response passes a note to the agent.
POST /api/v1/runs/{runId}/reviseThe action is not carried out; feedback (required) tells the agent what to change, and the run continues.
POST /api/v1/runs/{runId}/rejectThe action is refused and the run ends as failed with error_code: approval_rejected.

Each decision is recorded in the run's approvals; see Approvals.

awaiting_input — the run carries pending_input with the question, any options and context. Answer it:

curl -X POST https://api.snaga.ai/api/v1/runs/<run_id>/respond \
  -H "Authorization: Bearer $SNAGA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "response": "Use the EU price list" }'

The run goes back to the queue and continues.

Pause, resume, cancel

  • POST /api/v1/runs/{runId}/pause stops a running run at its next step boundary. A step already in flight finishes first.
  • POST /api/v1/runs/{runId}/resume puts it back in the queue. The body is optional; input.note reaches the agent as a message from you.
  • POST /api/v1/runs/{runId}/cancel stops it for good. It always answers 200 — cancelled: false means there was nothing to stop — so repeating it is safe.

Continuing a run that ran out of steps

A run that hits its step budget finishes with output.truncated: true. When the platform can sign one, output also carries a continuation_token; pass it back to pick up where the run stopped:

curl -X POST https://api.snaga.ai/api/v1/runs/<run_id>/continue \
  -H "Authorization: Bearer $SNAGA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "continuation_token": "<token>" }'

This is different from output.output_truncated, which means the model ran out of output tokens mid-answer.

POST /api/v1/runs/{runId}/checkpoint marks a checkpoint on a running run without disturbing it; GET /api/v1/runs/{runId}/checkpoints lists them.

Looking back at a run

CallWhat you get
GET /api/v1/runsRuns in your company, newest first; filter by agent_id, session_id, status.
GET /api/v1/runs/{runId}/stepsEach step with its tokens, cost and tool calls.
GET /api/v1/runs/{runId}/sourcesThe links the agent read or found, which ones the answer cites, and unsourced_links to check first.
GET /api/v1/runs/{runId}/artifactsFiles the run produced.
GET /api/v1/runs/{runId}/events/exportThe whole event log as JSON lines.

See also Pagination and streaming and the API reference.