Overview
Passingresponse_format to answer changes the response from Markdown prose to a JSON string matching a schema you supply. It doesn’t change citations: they come back exactly as they do without response_format, regardless of which scope grounded the search.
This guide walks through building a structured response: identifying the scope your fields live in, designing the schema, writing a query that actually surfaces every field, and parsing the result safely. Each step applies directly to one running example: pulling a company snapshot out of the companies scope.
Why use a structured response
By default,answer returns Markdown prose with inline citations. That’s a fine format for a person or an agent to read, but not one code can consume directly. Asking about a company without response_format might return something like this:
response_format replaces that parsing step: the endpoint instead returns a JSON object that matches your schema instead of prose.
What makes a structured response reliable
response_format only changes the shape of the output. It has no effect on what the grounding search looks for or finds. A schema asking for a field the grounding search never surfaces doesn’t make that field appear; it either comes back as a best guess or breaks the response’s validity.
Getting a reliable structured response comes down to three things: pointing the search at the right data (this step), designing the schema correctly (Step 2), and writing a query whose answer contains what the shape asks for (Step 3).
Step 1: Identify the correct scope.
Every scope has its own native structure. The closer your schema’s fields are to a scope’s native structure, the more reliablyresponse_format can fill them in, because the model is normalizing data that’s actually in front of it rather than inferring something absent.
Example: A research tool needs a company’s legal name, industry, ownership type, headquarters country, and total funding raised. All five live in the
companies scope’s native structure (Company Details and Financials, specifically), so that’s the correct scope to choose, rather than, say, news or wikipedia, which wouldn’t reliably carry all five in one place.
Step 2: Design your schema.
The schema specifies what the endpoint should return. To create the most reliable schema possible, follow these principles:-
Include every piece of data your use case needs. If your code needs a field, name it in your schema, or it never shows up in the response. Work from what your code does with the result.
Applied: the research tool needs five things, so
company_snapshothas five properties:legal_nameandindustryto identify and categorize the company,ownership_typeandhq_countryfor the tool’s own filtering, andtotal_funding_usdas the number it actually reports. -
Use the narrowest matching type. The narrower the type, the less parsing your own code has to do afterward.
Applied: the schema types
total_funding_usdasnumber, notstring. The sample data spells it$12500000, and the schema turns that into a plain12500000you can do arithmetic on directly. -
Write descriptions as instructions, not documentation. A
descriptiontells the model how to derive or normalize the field, not just what it means. A description that just restates the field name gives it nothing to act on. Applied:hq_country’s description spells out the normalization from a full mailing address down to just the country. Without it, the model has no instruction to do anything but copy the address field verbatim. -
Constrain to a fixed set with
enumwhere one exists. If a field can only take one of a handful of known values, declare it as anenumrather than leaving it a free-formstring. This applies to an entity type, a status, a category, or similar fields. Doing so rules out near-miss variants that all mean the same thing. Applied: The example schema constrainsownership_typeto["public_company", "privately_held", "nonprofit", "government_agency"]. Without theenum, one call might return"Private"and another"Privately held company", while a downstream filter matching on an exact string silently misses half of them. -
Mark every field
required. A property left out ofrequiredis optional, and the model can skip it entirely rather than returning it, even asnull. If a field needs to come back on every call, it belongs inrequired. Applied: all five fields go inrequired. None of them is optional here: a snapshot missingownership_typeortotal_funding_usdis exactly the kind of gap this schema exists to prevent. -
Set
additionalProperties: falseon every object, including nested ones. Otherwise, the model can return fields you don’t name. JSON Schema doesn’t let a nested object inherit the setting from its parent, so you have to set it on each object yourself. See Schema validity for what happens when you omit it on a nested object understrict: true. Applied:additionalProperties: falsesits on the single top-level object here. -
Limit the schema to the fields you actually use. Every extra field is another place generation can go wrong, and a schema with unused fields makes truncation more likely on longer answers. See Step 4.
Applied: The
companiesscope’s structure also includes headcount, web traffic, competitors, and a dozen other fields. See the full list. None of them are in this schema, because the research tool in this example doesn’t use them.
Step 3: Write a query whose answer contains every field.
Theresponse_format only shapes output; for the response format to work, the query must elicit the facts that make up the response format. Two practices improve query reliability:
- Ask for exactly the fields your schema names, in roughly the same terms. Don’t rely on the schema alone to imply what you want. Applied: The query below asks for the same five things, in the same order, as the schema’s five properties: “legal name, industry, ownership type, headquarters country, and total funding raised.”
-
Anchor the query with identifying detail. A bare name is a weak query on any scope; the more specific the query, the more likely the grounding search surfaces the one record you mean instead of a similarly named one.
Applied: “Seltz” alone is ambiguous. The
companiesscope also has an unrelated company, Sketz.ai, and thewikipediascope has two places that share the name “Seltz” and aren’t companies at all. The query below anchors on “the web knowledge layer company at seltz.ai” to point the search at the right entity.
Step 4: Parse defensively.
answer doesn’t validate the model’s output against your schema before returning it. A request can still succeed with a 200 and return a value that ends prematurely partway through generation, in which case it doesn’t parse as valid JSON. Always wrap the parse call in a try/catch or equivalent rather than assuming the result is well-formed. See Request a structured response for the full caveat.
Putting the schema, the query, and defensive parsing together:
snapshot comes back matching the schema from Step 2, built from the same sample company profile used throughout this example:
More examples
The same four steps apply to any scope.People
Profiles include a title and location in free-text fields, so the schema has to normalize these. This is the exact schema a customer uses to extract a name, title, and country from a LinkedIn profile. See the people scope’s field list for what else is available to extract. A bare name is too weak an anchor on this scope even with an employer attached, since common names collide with unrelated profiles. The query below anchors on Seltz’s own founder instead, whose profile is unambiguous:Python
News
Articles already carry apublishedDate field, but the schema below has the model reformat it and pull an array out of the article body. See the full sample.
Python
Wikipedia
Articles in this scope are closer to raw prose than the other scopes, so schema fields need to point at facts the article actually states, not facts you assume. Anenum keeps the entity-type field from drifting across near-duplicate values like "Village" or "town". See the full sample.
Python
Beyond Answer
Chat completions accepts the sameresponse_format and scope combination. See Structured outputs if that’s your integration surface instead of answer directly. Agent takes the same JSON-schema shape too, as output_schema, but runs its own open-ended multi-step research rather than a single grounding search scoped to one of these four verticals. See Structured output for when that’s the better fit.
Next steps
- Data Concepts: How scopes work across Seltz endpoints
- Request a structured response: Full
response_formatparameter contract for Answer - Structured outputs: The same feature over chat completions
- Structured output: The same feature over the Agent API
- Companies, People, News, Wikipedia: Full field list and sample response for each scope