Skip to content
← Free FDE training guides

Free learning / 40-minute structured-output lab

Your first output contract: shape is not truth

Connect ordinary response fields to real JSON Schema validation, then compare a valid shape with the source that should support it.

No account needed. Use your own copy for writing and keep the original as a reference.

Engineering lab library / Run locally

Make the output contract visible.

Run real JSON parsing and schema validation against nine small responses. Compare shape failures with a correct-looking response that the source does not support.

Synthetic records. No provider key or model inference. Package setup needs package-registry access.

  1. Start here / Real library, SDK or framework · Scripted inputs

    First output contract

    Reproduce nine responses and explain the first boundary that holds each one.

    Python 3.11+ · Pinned jsonschema validator · No model

An assistant extracts a machine's condition from a note. Another program needs to know which source was used, which version it was, what was observed and what supports the observation. A paragraph may be readable to a person without being a stable interface for that program.

This original 40-minute exercise teaches that interface using a small JSON response, an actual JSON Schema validator and one fictional source. There is no model call, external action or claim of measured model accuracy.

1. Give the answer a usable shape

Structured output is data arranged to an agreed contract. Prompting describes a task and context to a model. Asking for a shape and validating the returned value are different jobs.

Think of a typed function result. A caller expects particular fields, but an annotation in your code cannot prove that incoming text from an external service has those fields. A runtime validator inspects the actual value.

JSON, JavaScript Object Notation, is a text data format used across languages. JSON Schema describes rules for JSON values. Neither is an AI model, a database or a guarantee that a statement is true.

Here is the complete fictional source:

Text example
NOTE-7 · revision 3
Pump P7 is running. Temperature is 41 C. No shutdown is recorded.

Here is the supported response in this exercise. Save it as answer.json when you reach the local setup:

Code example
{
  "source_id": "NOTE-7",
  "source_revision": 3,
  "condition": "running",
  "evidence": "Pump P7 is running."
}

The four fields answer four questions: which note, which version, what condition, and what evidence? This is a draft finding. It does not operate a machine.

2. Run the local contract

Download these files into one folder:

Use Python 3.11 or later. On macOS or Linux:

Code example
python3 -m venv .venv-schema
. .venv-schema/bin/activate
python -m pip install -r fde-first-schema-requirements.txt
python fde-first-schema.py test
python fde-first-schema.py compare

On Windows, use Command Prompt:

Code example
py -3 -m venv .venv-schema
.venv-schema\Scripts\activate.bat
python -m pip install -r fde-first-schema-requirements.txt
python fde-first-schema.py test
python fde-first-schema.py compare

Installation needs internet access. The exercise commands block socket connections and DNS lookup. The actual jsonschema 4.26.0 validator uses a local Draft 2020-12 schema with no remote references. It needs no provider account, key, collector or model.

Eight checks cover stage order, downstream skips, different failure reasons, type handling, source mismatch, parser limits, diagnostic privacy and local repeatability. The report is deterministic for the pinned environment.

3. Read before validating

The first boundary is a parser:

Text example
Response text
      |
      v
Read JSON ---- unreadable or ambiguous ----> hold
      |
      v
Check shape -- violates the contract ------> hold
      |
      v
Compare note - unsupported or old source --> hold
      |
      v
Supported draft within this fixture

A parser turns text into values. JSON object property names are quoted strings; the values may be strings, numbers, booleans, null, arrays or objects. The number 3 and the string "3" are different.

The supplied parser refuses a trailing comma, duplicate property names and nonstandard NaN or Infinity values. It does not silently choose one of two conflicting duplicate fields. Inputs are limited to 4 KiB.

Run:

Code example
python fde-first-schema.py run --case syntax

Read first_stop: "parse". The schema and source stages say not-run. That is neither a pass nor a second diagnosis of the response.

4. Make the field rules explicit

The schema's properties entry describes the fields:

FieldShape ruleWhat that rule cannot establish
source_idNonempty string, at most 40 charactersWhether the note exists or is accessible
source_revisionInteger, at least 1Whether this is the current version
conditionString: running, stopped or unknownWhether the source supports that value
evidenceNonempty string, at most 180 charactersWhether the quote supports the claim

All four fields also appear in required. Merely describing a property does not make it mandatory. additionalProperties is false here, so an unexpected execute property is refused.

Run these examples and predict the rule keyword first:

Code example
python fde-first-schema.py run --case wrong-type
python fde-first-schema.py run --case missing
python fde-first-schema.py run --case null
python fde-first-schema.py run --case extra
python fde-first-schema.py run --case enum
ChangeFirst stopRule keyword
Revision is "3"Schematype
Evidence is omittedSchemarequired
Evidence is nullSchematype
Extra execute fieldSchemaadditionalProperties
Condition is idleSchemaenum

Null is a value, not an omitted property. An enum is a permitted-value list, not a truth test. Validation does not fill missing knowledge or coerce a quoted number into an integer. The path /evidence identifies that field; / identifies a rule on the object itself.

5. Challenge a perfectly shaped response

Code example
python fde-first-schema.py run --case unsupported
python fde-first-schema.py run --case stale

The first response says stopped. That word is in the enum, so the schema passes. The note says running, so the separate source comparison holds it.

The second names revision 2. It is a valid positive integer, so the schema passes. The supplied source is revision 3, so the source check holds it.

This comparison is intentionally narrow: it checks the identifier, revision, condition and quote against explicit values for one fixture. It is not a general semantic evaluator, and it cannot determine whether arbitrary prose is true. In a real system, a quote may occur in a document without supporting the conclusion. The receiving workflow needs appropriate evidence and review.

The accepted outcome is supported-draft, not an executed action. Schema validity does not authenticate a caller, authorize a tool or prove that an external operation completed.

6. Change one value and explain the boundary

Save the example from section 1 as answer.json, then run:

Code example
python fde-first-schema.py check --file answer.json

Change one thing at a time:

  1. Change 3 to "3". Predict a type failure.
  2. Restore the number, then change it to 2. Predict a source revision failure.
  3. Restore revision 3, then omit evidence. Predict a required-field failure.
  4. Restore evidence, then use null. Predict a type failure.
  5. Restore the quote, then add an execute field. Predict an additional-field failure.

The check command returns bounded diagnostics without echoing the submitted text. Its exit code indicates whether the command ran. Inspect first_stop and outcome for the response decision; a successful process exit is not acceptance of the response.

Keep the contract and source unchanged during this comparison. Changing the schema to make a failing response green changes what you are claiming to test.

7. Connect the exercise to a real model integration

A provider's structured-output feature may constrain generation to a supported shape. That differs from a prompt that simply says “return JSON.” This lab tests the local receiving checks with supplied responses; it does not exercise provider generation or measure a model.

When integrating a provider, verify its current schema support and completion states. Explicitly handle refusal and incomplete generation. A successful HTTP response does not alone establish complete usable content. Keep a bounded repair policy instead of retrying indefinitely.

Final structured responses and structured tool arguments have different consumers. The latter proposes a function's arguments; it grants no permission to run that function. Current access, source support and action policy remain application responsibilities.

8. Keep a receiving-engineer note

Keep:

  • The schema version and meaning of each field.
  • A response that stops at parsing, one at shape validation, and one at source comparison.
  • A supported draft and an explanation of what it still cannot authorize.
  • A proposed negative test for changed sources or a changed consumer contract.

The next lesson develops source acceptance and human review: Open structured-results practice. The advanced structured agent output lab uses actual LangChain ToolStrategy validation and repair.

Primary references

Checked 20 October 2026. These references support the concepts; the fictional note, exercise and teaching sequence are original LockedIn Labs material.

Before you move on

Keep the evidence of your work.

  • A small output contract with explicit field meanings.
  • Recorded parser, schema and source-comparison outcomes.
  • A receiving note that separates supported drafts from action authority.

Keep these in your own working copy. Reading this page does not save work or record completion.

Suggested next free session

Turn a sentence into a search result

See how a source can be found before its content is used. This is a suggested sequence; choose the practice that addresses your current gap.

Open the next free guide
Have Academy access?

Continue with worked explanations, practice and review in the related lesson.

Open the related Academy lesson →
Back to top ↑