Skip to main content
POST
Runs an LLM analysis over the run’s scored results and stores a structured narrative report: overall summary, consistency, instruction adherence, response patterns, reasoning quality, tool usage, and prioritized recommendations. Fetch the stored report with Get Report. The analysis prompt samples the worst 12 and best 5 rated results (all of them when the run has 17 or fewer), and each sampled result is independently re-scored by up to 3 judge models to produce per-item agreement evidence.
On the self-host engine this endpoint is synchronous: it returns only once the judges are done, so the response status is already terminal ("completed" or "failed"), and the first GET /runs/:runId/analyze-status poll reads that same terminal status. The mode: "sync" field says so on the wire. (Hosted AgentX queues a durable job and returns "pending" instead; the SDK’s poll loop handles both.) Re-running analysis overwrites the stored row.

Authentication

string
required
Project API key.

Path Parameters

string
required
Run ID. Analyze after finalizing, so the analysis covers every result.

Body

array
Judge models to score the evidence sample with, up to 3: [{ "model": string }]. Model ids come from the model catalog. Duplicate models are deduplicated before the 3-model cap is applied. The first entry also writes the narrative. Omit to use the default judge model alone.
string
default:"\"balanced\""
"balanced" or "quality_first". Echoed back in the response; not persisted with the stored report.
A second analyze request for the same run while one is already in flight joins the running analysis and returns its result instead of starting a duplicate - so an immediate retry does not double your judge spend or re-run the analysis.

Response

string
The run ID (analysis is keyed by run).
string
Same value as evaluationId, kept for SDK compatibility with the hosted job queue.
string
"completed", or "failed" (for example, when the run has no scored results yet, or the judge model returned no analysis - the failure reason is readable from GET /runs/:runId/analyze-status).
string
Always "sync" on self-host.
string
Echoed back.

Errors

Checking status

GET /api/v1/custom-agent-evaluations/runs/{runId}/analyze-status returns { evaluationId, jobId, status, progress, failureReason, warnings, cost, etaUpdatedAt, overflowStats }. status is "not_started" before any analysis, "running" while one is in flight for the run (a concurrent or retried analyze), otherwise the stored row’s terminal "completed" or "failed"; a failure carries failureReason: { code: "ANALYSIS_FAILED", message, retryable: true }. Poll loops must treat any non-terminal value as “keep waiting”, not just "not_started". All three shapes carry the same keys; running and terminal rows carry jobId set to the run ID, and only not_started carries jobId: null. On terminal rows the progress/cost/overflow fields exist for wire compatibility with the hosted job queue and are static on self-host. An unknown run returns 404 { "error": "Run not found" }.