Skip to main content
CONCEPTS

Runs

A run is the complete unit of agent work. Budgets, policies, and audit trails apply to the run, not the individual API call.

A run is the central concept in Rungate. It represents the complete unit of agent work — first model call, every tool invocation, every retry, every approval gate, the final output. Governance applies to the run as a whole.

This page covers how to group calls into runs, what happens when a run auto-closes, how to handle long-horizon workflows that span hours or days, and how runs interact with the rest of the system.

Grouping calls into a run

You tell Rungate what run a call belongs to via the x-rungate-run-id header (or the equivalent body field under a rungate key for SDKs that strip unknown headers).

x-rungate-run-id: run_customer_refund_2026_04_26

Pick a stable, meaningful ID. The format is up to you — Rungate just uses it as a string key. Common patterns:

  • run_{feature}_{date} — readable for humans scanning the dashboard.
  • run_{uuid} — easiest if your agent already generates UUIDs.
  • run_{customer_id}_{timestamp} — if you want runs scoped to a customer.

What Rungate does with the ID

On every call:

  • If a run with that ID does not exist, Rungate creates a new run.
  • If a run with that ID exists and is open, Rungate appends the call to it.
  • If a run with that ID exists and is closed, Rungate returns 409 Conflict. Start a new run with a different ID.

If you don't pass an ID, Rungate auto-groups calls by the agent's idle window — calls within the idle timeout (default 15 minutes) get grouped into one auto-run. This is fine for one-shot evaluations but explicit IDs are recommended for production workflows.

Closing a run

Three ways a run closes:

  • Idle timeout — no calls for 15 minutes (default; configurable per policy). Run is marked completed.
  • Explicit completion — call POST /v1/runs/{id}/complete. Idempotent; calling it on an already-closed run returns 200 with the same run object.
  • Hard stop — a budget or policy violation closes the run with status blocked. The agent receives the relevant 4xx response on the next call.

Long-horizon workflows

The 15-minute idle timeout is a fallback, not a hard cap. As long as the agent keeps sending calls with the same x-rungate-run-id, the run stays open indefinitely. Budgets and policies span the entire life of the run.

The auto-close exists for one reason: to recover from agents that crashed or forgot to send a completion. It is not a deadline you need to design around.

Overnight pipelines, multi-day research runs, batch jobs — all fine. Pass the run ID on every call, optionally call /v1/runs/{id}/complete when done.

Inspecting a run

Your agent (or operator tooling) can read run data through /v1 endpoints scoped to the agent's token:

GET    /v1/runs/mine?limit=20      Your recent runs
GET    /v1/runs/current             The run in progress, if any
GET    /v1/runs/{id}                Full run object
GET    /v1/runs/{id}/steps          Step-by-step reconstruction
POST   /v1/runs/{id}/complete       Close the run (idempotent)
POST   /v1/runs/current/complete    Close whatever run is current
POST   /v1/runs/complete-all        Bulk-close (recovery utility)

Special headers

Beyond x-rungate-run-id, a few related headers tune run behavior:

HeaderPurpose
x-rungate-new-run Boolean. Force a new run on this call even if a run is in-flight.
x-rungate-policy Override the agent's default policy for this run (policy id or name).
x-rungate-user End-user identifier — surfaces in analytics filters and webhook payloads.
x-rungate-tags Comma-separated tags — surface in analytics + webhooks.

Example: a multi-step workflow

# Same x-rungate-run-id across all calls — one run, cumulative budget
RUN_ID="run_research_$(uuidgen)"

# Step 1: planning
curl -X POST https://api.rungate.dev/v1/chat/completions \
  -H "Authorization: Bearer rg_agt_..." \
  -H "x-rungate-run-id: $RUN_ID" \
  -d '{ "model": "gpt-4", "messages": [...] }'

# Step 2: research
curl -X POST https://api.rungate.dev/v1/chat/completions \
  -H "Authorization: Bearer rg_agt_..." \
  -H "x-rungate-run-id: $RUN_ID" \
  -d '{ "model": "claude-sonnet-4", "messages": [...] }'

# Step 3: synthesis (might trigger budget alert)
curl -X POST https://api.rungate.dev/v1/chat/completions \
  -H "Authorization: Bearer rg_agt_..." \
  -H "x-rungate-run-id: $RUN_ID" \
  -d '{ "model": "claude-opus-4", "messages": [...] }'

# Done
curl -X POST https://api.rungate.dev/v1/runs/$RUN_ID/complete \
  -H "Authorization: Bearer rg_agt_..."