Background jobs and retries

Pick the right route for an agent call, run long work as a background job, and retry without running a turn twice.

2 min read · Updated Oct 29, 2026

Every published agent answers on three routes. Pick the one that fits the work, and retry an unanswered request safely.

Choose a route

All three run the same agent and share keys, user and learner_group.

/runs /jobs /chat/completions
You send input, optional conversation_id The same, plus Idempotency-Key model (the slug) and messages
You get The result, or a stream 202 and a job to poll choices[0].message.content
Time 60 s, or the agent's 10–120 5 minutes or more As /runs
In the dashboard API · runs API · background job API · chat completions

Start with /runs when someone is waiting; "stream": true streams the reply. Use /jobs for long research, image generation, or a host that cuts requests short. For OpenAI-compatible SDKs, set the base URL to https://api.viablelab.org/v1/agents/{slug}; agents with Ask user steps need /runs.

Run a background job

bash
curl https://api.viablelab.org/v1/agents/YOUR_AGENT_SLUG/jobs \
  -H "Authorization: Bearer $VIABLE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: my-app-turn-8f2c-0004" \
  -d '{"input": "Draft a reading list on photosynthesis.", "user": "my-app:student-0001"}'

# Then poll its status_url with the same key:
curl https://api.viablelab.org/v1/agents/YOUR_AGENT_SLUG/jobs/agtj_... \
  -H "Authorization: Bearer $VIABLE_API_KEY"

The 202 has an id (agtj_…), a status_url and a Retry-After header. Wait that long between polls.

  • queued or running: poll again.
  • completed: result is the body /runs returns.
  • failed: error has the code. To try again, submit a new job with a new key. A job not started within 15 minutes fails with agent_job_expired, and one that stopped before its run began with agent_job_interrupted: nothing ran, so send the turn again.
  • recovery_required: the run had started, and completion is uncertain: it may have drawn an image or called a web address. Check Run history; don't submit the turn again.

Keep one job per conversation at a time.

Retry safely

Send an Idempotency-Key with every turn: 8–128 letters, digits, dots, underscores, colons or hyphens. Save the route, body and key on your server. If no answer arrives, resend the same body to the same route with the same key.

  • The run completed: you get the same result.
  • Still going: 409 agent_request_pending. Retry later with the same key.
  • The body differs: 409 idempotency_conflict.
  • It started, then failed (such as provider_timeout): the key keeps that error. Retry with a new key.
  • Rejected before it started (validation, 401, 403, 404, 413, rate or spending limits): nothing was recorded. Reuse the key once fixed.

Warning

Never change the key to get past a pending or uncertain turn: that can run it twice. Never switch a pending turn between /runs and /jobs.

Limits and errors

  • Size: 12 MiB per request, context up to 128 KiB, up to 400 messages.
  • Rate: a key's per-minute limit covers all your users: thirty learners in one class share it.
  • 429: wait for Retry-After. For token, cost or credit limits, don't retry in a loop.

Branch on error.code, and never show an error as the agent's reply. The API reference lists every code.

This page is also plain Markdown at /docs/connect/jobs-and-retries.md. Point your AI at /llms.txt to find every page.