Skip to lesson

AnthropicClaude Certified Architect – Foundations2026-103.6 Integrate Claude Code into CI/CD pipelines

Return findings through a validated schema

Completed by the knowledge check

Learning objective

Output machine-readable review findings with --output-format json and --json-schema.

Core idea

A CI review has two output contracts. Claude Code’s result envelope tells your script what the run returned. Your findings schema tells the script what each review finding contains. --output-format json selects the envelope; --json-schema defines the structured answer inside it.

Without the second contract, a program can parse the outer JSON while still having to interpret prose in its result field. That does not provide dependable file paths, line numbers, or severity values for an automated comment consumer. Pair the flags and consume structured_output rather than extracting findings from narrative text.

See 3.6.1 for execution controls. A correct output schema does not remove the need for permissions, a turn budget, or a successful process outcome.

How it works

Separate the envelope from the answer

Print mode supports --output-format text, json, and stream-json. Text is the default human-readable output. JSON includes the result, session ID, and metadata. Stream JSON emits newline-delimited events for a consumer that needs progress throughout execution.

With --output-format json alone, the text answer sits in result. With --json-schema as well, schema-validated data sits in structured_output, beside request metadata. The structured answer is not the entire result envelope and is not a string your consumer should search for inside result.

--json-schema applies in print mode and requests a validated final output after the agent completes its workflow. The agent can inspect source and use permitted tools during that workflow. The schema governs the answer that the consumer receives, rather than replacing the investigation with a single extraction call.

Define the fields the consumer actually needs

For an inline-review consumer, define a findings array with explicit location, severity, and explanation fields. This example is an application-owned contract, not a built-in Claude Code finding format:

{
  "type": "object",
  "properties": {
    "findings": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "file": { "type": "string" },
          "line": { "type": "integer", "minimum": 1 },
          "severity": { "type": "string", "enum": ["high", "medium", "low"] },
          "message": { "type": "string" }
        },
        "required": ["file", "line", "severity", "message"],
        "additionalProperties": false
      }
    }
  },
  "required": ["findings"],
  "additionalProperties": false
}

Save the contract as review-schema.json. Requiring findings makes an empty array an explicit answer. Requiring each finding’s fields prevents a location-free paragraph from being accepted as a complete finding. The severity enum lets the consumer branch on known values rather than interpret synonyms.

A positive integer line number is still not proof that the line belongs to the checked-out diff. Schema validation establishes shape, not source-code truth. Your review instructions should require a concrete defect and a valid changed-code location; the consumer must verify those locations against the revision it is about to annotate.

Request and consume structured findings

A print-mode invocation can read the supplied diff and schema:

claude -p "Review this diff; return only actionable correctness findings" \
  --output-format json --json-schema "$(cat review-schema.json)" \
  < pr.diff > review-result.json

Here pr.diff contains the pipeline’s selected diff, and review-result.json captures the whole Claude Code result. Apply the permission policy and turn limit from 3.6.1 to the deployed invocation. The snippet isolates the output interface rather than specifying a complete runner configuration.

Read .structured_output.findings from the captured result. Do not feed .result into a second model merely to turn prose into JSON: that adds another interpretation step when the producer already supports a schema. Keeping the whole envelope also preserves session metadata for diagnosing a failed run.

Claude Code reports an invalid schema as an error before it can produce the requested output. The documented diagnostic begins Error: --json-schema is not a valid JSON Schema. Repair the schema instead of weakening the consumer to accept unstructured text. The format keyword is accepted as an annotation without client-side enforcement, so a format such as email is not an extra validation gate supplied by this CLI.

Distinguish missing output from an empty review

The Agent SDK structured-output documentation describes validation and re-prompting after a mismatch. Exhausting structured-output retries produces error_max_structured_output_retries, rather than valid data. It also documents that a result can have subtype success while lacking structured_output.

Require a successful result with the structured value present before consuming findings. A missing value, a failed result, or a non-zero process exit is an execution failure. An explicit findings: [] in a successful structured result is an empty review. Treating both as “no findings” hides a broken producer behind a green CI job.

What the run returned decides between an execution failure, an empty review and findings to verify.

What the run returned decides between an execution failure, an empty review and findings to verifyStarts at the whole Claude Code result and branches three ways on what the run returned. A failed result or a missing structured value is an execution failure. A successful result with an explicit empty findings array is an empty review. A successful result with structured findings goes on to verify its locations against the revision.failed or missingfindings: []structured findingsWhole Claude CoderesultWhat the runreturnedExecution failureEmpty reviewVerify locationsagainst the revision

The CLI supplies schema-validated data; it does not establish that each allegation is correct or that the findings are complete. Require evidence in the prompt, check the cited source locations, and keep the normal tests and human review appropriate to the change. Those are decisions about accepting the review, not reasons to parse free-form output.

Post validated findings through a defined interface

A deterministic consumer can post each accepted finding with GitHub’s “Create a review comment for a pull request” endpoint, POST /repos/{owner}/{repo}/pulls/{pull_number}/comments, mapping the finding to the reviewed commit and diff location. This keeps posting outside the model. Alternatively, anthropics/claude-code-action can let Claude post through mcp__github_inline_comment__create_inline_comment; the action starts that MCP server only when --allowedTools in claude_args names the tool. Choose whether the model produces findings for a separate consumer or also invokes the posting tool.

Key distinctions and trade-offs

A findings schema improves predictable consumption while constraining what the reviewer can express. Add fields only when the consumer or review criteria need them. If the job must distinguish an incomplete investigation from a completed one, give that distinction an explicit place in the application contract rather than hiding it in a message string.

The output choices divide as follows:

ChoiceSuitable consumer
textA person reading a report
json without a schemaA script that needs the envelope and text answer
json with --json-schemaA script that needs defined findings fields
stream-jsonA program processing execution events and final results

Stream events are useful for monitoring, but a progress event is not the completed findings object. A consumer that posts comments should wait for the final successful structured result.

Architecture / decision scenario

A Claude Code CI job reviews a generated checkout change. The posting stage needs a file, line, severity, and message for each finding. The pipeline passes --output-format json and the schema through --json-schema, then captures the result envelope.

If the result succeeds and contains structured_output.findings, the consumer verifies locations against the reviewed revision and prepares comments. If the array is empty, it records that the completed review reported no findings. If schema validation fails, structured retries exhaust, or the value is absent, it marks the review incomplete and posts no fabricated clean result. The posting stage never tries to recover findings from prose in result.

Common exam traps

  • Assuming parseable outer JSON means the review itself has a findings schema.
  • Reading schema-validated findings from result instead of structured_output.
  • Treating schema validation as proof that an allegation is correct.
  • Assuming a successful subtype always includes structured data.
  • Converting missing output into an empty findings array.
  • Assuming the CLI enforces JSON Schema format annotations.

What to remember

--output-format json chooses the result envelope; --json-schema chooses the final answer’s structure. Consume structured_output, require a successful complete result, and validate source locations before automated use. An explicit empty findings array and a failed or missing structured answer are different outcomes.

Knowledge check

References