Skip to content

Async & Background Runs

Base URL: https://agent-api.auteryn.ai

There are two ways to run an agent without holding an SSE connection open:

Approach When to use
POST /api/run with stream: false Interactive clients that will reconnect to the stream. Returns 202 and runs in the background. See Run an Agent.
POST /api/run/async Server-to-server / webhook-driven background work. Returns 202 immediately; you read the result with the follow-up endpoints. Documented below.

Accepts a run, returns 202 Accepted immediately, then executes in the background. Auteryn’s Loops use it for messaging Channels (Telegram, WhatsApp, etc.), and external systems use it for async processing.

Not available to guests. Guests must use POST /api/run. Messaging trigger sources (telegram, whatsapp, twilio, sms) require a customer-facing agent.

With an agent token, send X-Agent-Id for the agent the token was exchanged for, leave out flow_id and customer_id, and give each new task_id a fresh UUID. See Agent token scope.

POST https://agent-api.auteryn.ai/api/run/async
Authorization: Bearer <jwt>
X-Agent-Id: your-agent-uuid
Content-Type: application/json

Body:

{
"query": "Summarize today's new support tickets",
"messages": [],
"task_id": "3f0e6c1a-8d52-4b77-9a41-6c2d5e7f1a90",
"mode": "auto",
"async_callback_context": {
"connection_id": "",
"customer_id": null,
"trigger_source": "internal",
"job_id": "job_456"
}
}
Field Required Description
query ✅* The user’s message. *If empty, it is taken from the last user message in messages.
messages ❌ Conversation history ([{role, content}]).
task_id ✅ Task/thread ID. If no task has this ID, one is created, so use a fresh UUID for a new task. An ID that another organization already holds answers 409 (That task_id is unavailable.) to every caller.
run_id ❌ Provide to set the run ID; auto-generated if omitted. An ID already in use answers 409.
mode ❌ auto, fast, or deep (default: auto).
flow_id ❌ The Loop this run belongs to. A new task keeps it, so a reply on a messaging Channel goes to the customer. An agent token must leave it out (403).
async_callback_context ✅ Who the run is for and, for a Channel run, where the reply goes (see below).
user_timezone ❌ IANA timezone (e.g. America/New_York) used for date-aware answers.
attachments ❌ Files for the agent: [{id, url, filename, mimetype, size}], where url is a link the agent can download.

async_callback_context:

Field Required Description
connection_id ✅ The Connection a Channel reply goes out on when the Loop does not set one. An agent token run has no Channel to reply on; send an empty string.
customer_id ❌ Customer identifier. null when the run doesn’t serve a customer (identity comes from the JWT). An agent token must leave it null (403).
trigger_source ❌ Source that triggered the run (e.g. telegram, internal). Default unknown.
job_id ❌ External job-tracking ID.
metadata ❌ Arbitrary passthrough (chat_id, etc.).
{
"id": "run_abc123",
"task_id": "3f0e6c1a-8d52-4b77-9a41-6c2d5e7f1a90",
"status": "accepted",
"execution_mode": "fast",
"routing_reason": "Customer-facing agent → fast",
"message": "Request accepted for background processing"
}

The final agent result is not in this response, and Auteryn does not call you back with it: read it with the endpoints below. A run that belongs to a Loop on a messaging Channel (it has a flow_id and a customer_id) also sends its reply to that customer on the Channel.

If a person on your team has taken over the conversation, nothing runs: the response is 200 with "status": "skipped", and the message is saved to the task.


These work for any background run, whether started via /api/run/async or /api/run with stream: false.

Is there an active run for this task, and what’s its progress? Used by clients to decide whether to reconnect after a refresh.

{
"active": true,
"run_id": "run_abc",
"status": "running",
"progress": {
"tools_count": 2,
"thoughts_count": 5,
"has_content": true,
"content": "…partial answer…",
"started_at": "1783080000000",
"agent_mode": "deep"
}
}

status may be running, pending, planning, executing, cancelling, complete, or error. started_at comes either as milliseconds since the epoch or as an ISO 8601 timestamp, so accept both. When nothing is active you get {"active": false}.

Reconnect to an in-progress or recently completed run. Behaves in four ways:

  • Active run → returns current state and an SSE stream of the remaining events.
  • Pending run (not started yet) → returns an SSE stream that waits, then streams.
  • Complete run → returns the final state as JSON.
  • No run → 404.

Supports resuming from a cursor: send the standard Last-Event-ID header (what a browser EventSource sends automatically on reconnect), or the last_event_id query param for hand-built clients.

SSE stream of the task’s live events (same AG-UI event types as POST /api/run). See Tasks & Runs.

Paginated JSON history of a run’s events (durable). Good for polling clients that can’t hold an SSE connection. See Tasks & Runs.


  • Interactive UI, may refresh → POST /api/run (stream: true), or stream: false then GET /api/run/{task_id}/reconnect.
  • Webhook / worker that does not wait for the result → POST /api/run/async.
  • Polling without SSE → GET /api/runs/{run_id}/events with cursor.

See also the Errors & rate limits reference.