Sandbox API

Observability and correlation

x-correlation-id, logs, Cloud Trace, and Langfuse LLM tracing for integrators.

Every Sandbox API request can carry a correlation id so your eval platform, harbor workers, and LLM observability share one key.

Request header

HeaderRequiredBehavior
x-correlation-idNoIf you send a non-empty value, Sandbox uses it verbatim everywhere. If omitted, the gateway generates a ULID and echoes it on the response.
export SANDBOX_GATEWAY_URL="${SANDBOX_GATEWAY_URL:-http://localhost:8780}"

curl -sS \
  -H "X-Api-Key: dev-local-key" \
  -H "x-correlation-id: prism-eval-run-42" \
  -H "Content-Type: application/json" \
  -d '{"task_slug":"my-task","metadata":{"task_archive_url":"https://..."},"agents":[{"name":"a","harbor_agent":"oracle"}]}' \
  "$SANDBOX_GATEWAY_URL/sandbox/harbor/v2/jobs/execute-tasks"

Check the response headers — you should see the same x-correlation-id value.

ID mapping

IdWho sets itWhere it appears
correlation_idYour client (preferred) or gateway ULIDLogs (correlation_id field), OTEL span attribute, Langfuse trace.id
job_idHarbor (202 response, poll URL)Langfuse session_id (groups all LLM calls in one run)
otel trace_idAutomatic HTTP instrumentationCloud Trace; also Langfuse metadata otel_trace_id when enabled

Rule: pick one stable correlation id per eval run (e.g. Prism trial id, CTP job id) and send it on the initial enqueue request.

Async harbor jobs

For POST /sandbox/harbor/v2/jobs/execute-tasks (and Agent Runtime POST /sandbox/agent/v1/runs):

  1. Gateway/harbor API reads x-correlation-id from the HTTP request.
  2. The id is stored on the Pub/Sub job payload (correlation_id).
  3. The worker restores it for logs and passes it into harbor subprocess env (SANDBOX_CORRELATION_ID, HARBOR_TRACE_ID).

You can filter Pub/Sub messages in GCP by attribute correlation_id.

Langfuse (LLM eval plane)

When the platform has Langfuse keys configured (LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY, hosted at https://langfuse.turing.com):

  • LiteLLM generations from harbor/agent runs are traced in Langfuse.
  • trace.id = your x-correlation-id (search the Langfuse UI by the same id you sent).
  • session_id = harbor job_id.

This is separate from Cloud Trace (HTTP/SLO plane). Both can share the same correlation id for cross-linking.

Local make up works without Langfuse keys — tracing bootstrap is a no-op.

Python client

SandboxClient sends x-correlation-id when you pass correlation_id= (or legacy request_id=):

await client.submit_execute_tasks(
    body,
    correlation_id="prism-eval-run-42",
)

See Python SandboxClient.

OpenAPI

The platform spec documents x-correlation-id on every /sandbox/* operation:

Next steps