Trigger and wait

Start a run for a platform-managed agent and block the HTTP response until the run reaches a terminal state — or until a bounded wait window elapses. Designed for agents whose value is the output payload itself: AI-rendered responses, structured reports, generated documents whose contents live inside a JSON payload. The agent output is returned in the same response, so the caller can hand it straight to the end user (download, render, forward).

Endpoint

POST /api/agents/{agentId}/runs/trigger-and-wait

Auth: Authorization: Bearer <ingest_api_key>

Eligibility

Same as /trigger:

  • managed_by = 'platform'
  • status = 'active'
  • allow_external_triggers = true

Runtime support

Both supported runtimes accept this endpoint, but they reach the result differently:

  • n8n — the workflow must terminate in a Respond to Webhook node returning the agent output as JSON. The platform invokes the webhook synchronously and treats the response body as output_data.
  • Trigger.dev — the platform triggers the task and subscribes to its real-time state via the Trigger.dev SDK. When the run reaches a terminal state the platform reads the task's return value as the agent output and surfaces it to the caller. Tasks invoked synchronously must return their output — values reported only via the run callback won't appear in the synchronous response.

For both runtimes, the response shape and timeout semantics are identical.

Reporting the outputs metric

The response includes an outputs field (see the example below) — a non-negative integer count of agent-defined output units, used for billing and dashboards (see Run metrics if your SDK consumer is unfamiliar).

To populate it on the synchronous endpoint, include a top-level outputs: <integer> in your response (n8n) or return value (Trigger.dev), alongside the rest of the agent output:

jsonc
// n8n "Respond to Webhook" body, or Trigger.dev task return value
{
  "pdfUrl": "https://files.example.com/report.pdf",
  "pages": 42,
  "outputs": 1               // ← lifted into the dedicated metric column
}

The platform lifts the outputs value into the response's outputs field and into the runs.outputs column. The field is not stripped from output_data — anything reading it there continues to work. Anything that isn't a non-negative integer is silently dropped (same validation rule as the async callback flow).

Request

json
{
  "input": { "topic": "Q3 financial summary" },
  "timeoutMs": 120000
}
FieldTypeRequiredDescription
inputobjectnoMerged on top of the agent's saved default input; caller's values win.
userIduuidnoAttribution for runs.created_by. Unknown / non-member values are dropped silently.
timeoutMsnumbernoMaximum time the server may wait, in milliseconds. Server further caps at the agent's running_timeout_ms and a platform hard ceiling. Defaults to 60 000 ms when omitted.

Response — 200 OK (terminal)

The run reached a terminal state inside the wait window.

json
{
  "runId": 1234,
  "agentId": 42,
  "status": "completed",
  "output_data": { "pdfUrl": "https://files.example.com/report.pdf" },
  "outputs": 1,
  "error": null,
  "duration_ms": 4231,
  "started_at": "2026-05-26T12:00:00.123Z",
  "completed_at": "2026-05-26T12:00:04.354Z",
  "created_at": "2026-05-26T12:00:00.001Z"
}

status is one of "completed", "failed", or "cancelled". On "failed", output_data may still carry intermediate output the runtime wrote before failing; error carries the short failure reason.

Response — 202 Accepted (wait window elapsed)

The run did not reach a terminal state in time. It is still in flight — the existing async pipeline (callback + per-run poller) continues to drive it. The caller should fall back to polling.

json
{
  "runId": 1234,
  "agentId": 42,
  "status": "running",
  "timedOut": true
}

status is one of "queued", "running", or "waiting". Poll GET /api/agents/{agentId}/runs/{runId} (or, for zones, the equivalent zone endpoint) until terminal.

Response — 504 Gateway Timeout

The upstream runtime itself did not respond within the wait window (n8n only — Trigger.dev does not block on the trigger call). The run row is marked failed. The terminal-state guard on the callback endpoint prevents a late workflow completion from resurrecting it.

json
{
  "error": "Runtime did not respond within the wait window",
  "runId": 1234
}

Other errors

StatusReason
401Missing or invalid bearer token.
403Agent not eligible.
422Agent is not platform-managed or not active.
429Per-agent rate limit exceeded (stricter than /trigger because each call holds a connection).
500Runtime invocation failed before the wait could begin.

Choosing between /trigger and /trigger-and-wait

Use /trigger whenUse /trigger-and-wait when
The caller doesn't need the output in the responseThe caller hands the output straight to the end user
The run may take longer than ~5 minutesThe run completes in seconds or low minutes
You'll poll, subscribe, or wait for a callback yourselfYou want a single HTTP request that returns the result

SDK

ts
import { triggerRunAndWait } from '@cxpa/sdk/agent'

const result = await triggerRunAndWait({
  baseUrl: process.env.CXPA_API_URL!,
  ingestApiKey: process.env.CXPA_INGEST_KEY!,
  agentId: 42,
  input: { topic: 'Q3 financial summary' },
  timeoutMs: 120_000,
})

if (result.timedOut) {
  // Fall back to polling /api/agents/{agentId}/runs/{runId}
  return { status: 202, runId: result.runId }
}

if (result.status === 'completed') {
  // result.output_data has the agent payload
  return { pdfUrl: result.output_data?.pdfUrl as string }
}

throw new Error(`Run ${result.status}: ${result.error}`)