Ingest API
Report a run in one call
When your agent finishes a run, send one authenticated POST to agentspeed.com/api/v1/runs. Agents auto-provision on first use. Generate a key under any project’s API keys tab.
Privacy: AgentSpeed is metadata-first. The API has no field for prompts or model output, rejects unknown fields, and strips any content-bearing keys before storing. We keep metrics about your runs, never their contents.
curl
curl -X POST https://agentspeed.com/api/v1/runs \
-H "Authorization: Bearer $AGENTSPEED_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent": "checkout-assistant",
"status": "succeeded",
"model": "claude-opus-4-8",
"inputTokens": 1200,
"outputTokens": 340,
"costUsd": 0.0185,
"score": 0.92,
"durationMs": 4200,
"idempotencyKey": "run_123",
"spans": [
{
"name": "vector search",
"type": "retrieval",
"status": "ok",
"durationMs": 180,
"order": 0
},
{
"name": "completion",
"type": "llm",
"status": "ok",
"durationMs": 4000,
"order": 1,
"inputTokens": 1200,
"outputTokens": 340
}
],
"events": [
{
"level": "info",
"message": "order #4823 placed"
}
]
}'TypeScript / Node
// Node 18+ / TypeScript: report one run after your agent finishes.
const res = await fetch("https://agentspeed.com/api/v1/runs", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.AGENTSPEED_API_KEY}`,
"Content-Type": "application/json",
// Optional: dedupe retries. Re-sending the same key upserts the run.
"Idempotency-Key": runId,
},
body: JSON.stringify({
agent: "checkout-assistant",
status: "succeeded", // "succeeded" | "failed" | "timeout"
model: "claude-opus-4-8",
inputTokens: 1200,
outputTokens: 340,
costUsd: 0.0185,
score: 0.92, // quality score 0–1 (any number you compute)
durationMs: 4200,
spans: [
{ type: "retrieval", name: "vector search", status: "ok", durationMs: 180, order: 0 },
{ type: "llm", name: "completion", status: "ok", durationMs: 4000, order: 1 },
],
events: [{ level: "info", message: "order #4823 placed" }],
}),
});
if (!res.ok) throw new Error(`ingest failed: ${res.status} ${await res.text()}`);
const { run } = await res.json();
console.log("reported run", run.id);Python
# Python 3: report one run after your agent finishes.
import os, requests
resp = requests.post(
"https://agentspeed.com/api/v1/runs",
headers={
"Authorization": f"Bearer {os.environ['AGENTSPEED_API_KEY']}",
# Optional: dedupe retries. Re-sending the same key upserts the run.
"Idempotency-Key": run_id,
},
json={
"agent": "checkout-assistant",
"status": "succeeded", # "succeeded" | "failed" | "timeout"
"model": "claude-opus-4-8",
"inputTokens": 1200,
"outputTokens": 340,
"costUsd": 0.0185,
"score": 0.92, # quality score 0-1 (any number you compute)
"durationMs": 4200,
"spans": [
{"type": "retrieval", "name": "vector search", "status": "ok", "durationMs": 180, "order": 0},
{"type": "llm", "name": "completion", "status": "ok", "durationMs": 4000, "order": 1},
],
"events": [{"level": "info", "message": "order #4823 placed"}],
},
timeout=10,
)
resp.raise_for_status()
print("reported run", resp.json()["run"]["id"])Fields
Send a quality score
score is the one field worth adding even if you skip the rest. Attach any deterministic number in 0–1 that you already compute — a rubric pass/fail, a schema-validation result, a thumbs-up rate, a downstream conversion — and we roll it up into average quality per agent and per model over time. That is how you catch the silent regression where success holds at 99% but answer quality slid.
We aggregate the number you send. We don’t run a judge, manage a dataset, or see your prompts or outputs — it’s quality monitoring on live production traffic, not evals.
Responses
- 201: stored. Body: { run: { id, agent }, agentProvisioned, creditsConsumed }
- 401: missing/invalid/revoked API key.
- 403: monthly event credit limit reached (upgrade).
- 413: body exceeds 512KB.
- 422: invalid payload (field-level issues in the body).
- 429: rate limited; honor the Retry-After header.