Understand the request and response
An API defines how software requests an operation and receives a result. HTTP commonly carries the request and response, while JSON represents structured data such as named fields and arrays. This separates an application's interface from the model behind it. [source]
A model returning valid JSON has satisfied a formatting condition. The values inside it may still be wrong. Treat syntax validation, schema validation, and source verification as separate stages.
Prepare a local smoke test
First complete the local-model lesson. You need a running Ollama service and a downloaded local model. Copy its exact tag from ollama ls. Save the script below as local_request.py. Replace YOUR_LOCAL_MODEL_TAG before running it with Python 3.
The script sends a fictional sentence only to the loopback address. It does not upload a document or call a cloud API.
import json
from urllib.request import Request, urlopen
payload = {
"model": "YOUR_LOCAL_MODEL_TAG",
"prompt": "Summarize: Delivery is proposed for 20 March, subject to inspection.",
"stream": False
}
request = Request(
"http://127.0.0.1:11434/api/generate",
data=json.dumps(payload).encode("utf-8"),
headers={"Content-Type": "application/json"},
method="POST"
)
with urlopen(request, timeout=120) as response:
result = json.load(response)
print(result["response"])Python's JSON module handles encoding and decoding; urllib.request sends the request. Ollama documents its local API and streaming behavior. Disabling streaming here lets the introductory example read one response object. [source] [source] [source]
Inspect the layers
The payload defines the model, input, and response mode. The request defines the address, method, headers, and body. The response object contains the model's generated text and other fields. Printing response is different from validating its substantive content.
If the connection is refused, check whether the local service is running and whether its configured address differs. If the model is missing, check its tag and download status. If the request times out, inspect the service before retrying repeatedly. The example is a learning script, not a production retry policy.
Ask for output a program can use
By default a model writes prose. When a program needs to act on the result, such as filling a table, creating a calendar entry, or showing a button, ask for a serialization format. JSON and YAML work well. Always show the exact shape you want, and say what must not appear in the human-readable part. [source]
Produce your output as JSON in exactly this format:
{
"message": "Text to show the lawyer",
"proposed_date": "YYYY-MM-DD or null",
"source_ids": ["A02"]
}
Do not include document IDs inside "message".The application can then display message as ordinary text and use proposed_date to pre-fill a form, while keeping source_ids for the audit trail.
Ask for the sources as data
The same approach improves citations. Instead of links scattered through prose, ask for the answer plus a list of every source item used: [source]
{
"answer": "Total courier and transcript disbursements were $460.85.",
"used": ["D1", "D2"]
}You will not know which part of the sentence each source supports, but you will know exactly which records to check, and a program can confirm that every listed ID exists. Note what this does and does not show: in this example the model reports a total but lists the individual items, so you can recompute the total yourself. [source]
Enforce the format where you can
Asking politely for JSON usually works, but not always: a model may add a preamble, omit a field, or invent one. Many APIs now offer structured outputs, where you supply a JSON schema and the service constrains generation so the response always matches it. OpenAI describes its Structured Outputs as the evolution of an older JSON mode: both produce valid JSON, but only Structured Outputs ensures the schema is followed. [source] Anthropic documents structured outputs and strict tool use that guarantee schema-compliant responses through constrained decoding. [source]
Schema enforcement solves the format problem only. A field that must contain a date will contain a date; nothing guarantees it is the right date.
Design a structured extraction
For a chronology, you might request fields for document ID, event date, source passage, and uncertainty. Validate that required fields exist and that dates have the permitted form. Then compare the event and passage with the original. A field called verified: true is a model-generated claim unless an actual verification process sets it.