Skip to main content
GET /analyses/:analysisId returns more than 30 fields. This page is not about field definitions — it is about the order to read them in and how to interpret them. For the field list and types, see the API reference; for terminology, see core concepts.

The order to read in

1

Check status

Do not go further unless it is completed. On failed, record error.code and error.message and check the item statuses.
2

Check outputFormatting.status

extractedData follows the output-schema structure only when systemMetadata.outputFormatting.status is formatted or validation_failed. On skipped or fallback_raw there is no envelope (see below).
3

Branch on verificationStatus

verified → approve automatically, pending_review → review queue, rejected → reject. The detailed verdicts come after that.
4

Read extractedData and details[]

Values are in the envelope’s value, the reason is in reasoning, and the cause of an empty field is the reasonCode in details[].
5

Go to agentAuditLog if you need to

Which step decided what, on what grounds, and whether the external engine calls succeeded — that is all in the audit log.

The extractedData envelope

Every leaf field of the output schema carries an object with three keys instead of a bare value. Intermediate objects and array structures follow your schema exactly.
The rules:
  • A field that got no value still holds its place, as value: null. The field list in extractedData always matches the output schema.
  • When a parent object itself was not produced, the paths beneath it are not created. In that case details[] carries one entry for the parent with reasonCode: "PARENT_MISSING".
  • reasoning is stored at the moment the analysis completes. Reading the analysis again never changes it.
  • sourceStep is an execution order number, so it can differ from the next analysis onward if you edit the workflow. To point at a step reliably, use agentAuditLog.steps[].work_id.
  • 0 and false are valid values. Emptiness means null / "" / [] / {}.

When there is no envelope

fallback_raw is the most common reason for “every field in the output schema looks empty”. Branch on status before you look for values by schema key. validation_failed means assembly succeeded but some entries do not validate against the schema — the envelope is normal, and the mismatches are listed in ajvErrors[].
Analyses that completed before 2026-08-14 have no outputFormatting. For those, decide whether there is an envelope by checking whether outputSchema is null.

Why a field is empty

A field that received no value stays in the envelope as value: null, and a category: "JSON_OUTPUT" entry is added to details[], lowering outputCompleteness in the Analysis Score.
  • reasonCode is an extensible enum. Handle a value outside the table without erroring. It is a separate axis from type (a fixed set of six, such as OUTPUT_MISSING and OUTPUT_EMPTY).
  • reasonCode, message, and stepId appear only on JSON_OUTPUT entries, never on STEP or TOOL entries.
  • message is the grounds the responsible step recorded, while the envelope’s reasoning gives the reason at the field level. The two sentences can differ, so read reasoning first for field-level context.
  • target is a real instance path. Arrays are expanded by index, one per element (ubo_register[0].name). An empty array, or a missing array key, counts as a single ubo_register entry.
  • Omni does not re-examine the original document. It never claims “the value was not in the document”; the strongest statement it makes is “it was not included in the extraction result” (NOT_IN_FINAL_OUTPUT).

When no reason can be supplied

reasoning: null does not mean “there were no grounds” — it means “no reason could be supplied”. Reasons are not generated retroactively for past analyses.

Do not use extractionStatus

extractionStatus is a deprecated field kept for backward compatibility. It works at the level of top-level schema keys (extracted / missing), so it cannot distinguish nested fields or array elements. New integrations should use the envelope’s value together with details[]. Its emptiness rule matches the envelope (0 and false count as extracted). For an analysis with no output schema, it returns a map keyed by the top-level keys of extractedData.

Reading the verdict values

The response holds three levels of similarly named verdicts, each with a different value set. The top-level verdict aggregates the action results. One failed makes it rejected, all passed makes it verified, and anything else is pending_review. summary.overall_decision is the same aggregate, so passedverified, needs_reviewpending_review, and failedrejected. findings[].result is that same action result mapped for the UI (needs_reviewwarning).

confidence vs confidenceScore

A high confidenceScore can accompany a low confidence.score. The classic case is every step passing while the output schema comes back empty. Put confidence.score and details[] alongside verificationStatus in your auto-approval conditions. The weights and level bands are in core concepts.

Which playbook produced this verdict

An analysis freezes the playbook as it was at run time and returns it as playbookSnapshot. Editing the workflow afterwards leaves the grounds of past analyses untouched. If you keep the grounds for audit purposes, store playbookSnapshot from analyses marked frozen. outputSchema is frozen at run time in the same way.

Reading the audit log

agentAuditLog is the step-by-step execution record. Unlike the top-level fields, it uses snake_case (work_id, executed_at, duration_ms).
  • Identifying a step: step is the execution order and work_id is the fixed ID of the playbook action. It corresponds to workflowActions[].workId from GET /workflows/:workflowId.
  • Step verdicts: status (passed / needs_review / failed) and reasoning are what the Summary tab shows as the reasoning line in the dashboard. rule is the instruction that step carried out.
  • External engine calls: judge failure from success and error_code in mcpcalls[]. There is no HTTP status code. fallback_to_rag: true means it fell back to document search after the engine failed.
  • To see the same calls organized by action, use rawActionResults.{action}.mcpResults[]. That side uses camelCase (durationMs, errorCode, fallbackToRag).
  • A step that never ran does not appear in systemMetadata.workflowHistory[] either. The full step definitions are in workflowActions on the workflow response, and an unexecuted step is recorded in details[] as STEP_NOT_EXECUTED.

A pattern for downstream handling

  • Showing a reviewer the target, reasonCode, and message from details[] alongside the envelope’s reasoning makes the cause much faster to find.
  • Re-analyzing the same profile after improving the items issues a new analysisId. The earlier result is kept, and you can compare them with the run selector in the dashboard.
  • When you need a report a person can read, get the PDF from GET /analyses/:analysisId/report.