Agents: this page is also Markdown; every page is in llms.txt.

Return structured output

Every Task says what it Returns: plain text, fields you name, or JSON of any shape. Facet holds every answer to that shape, so your code can parse it the same way every time.

Pick the shape

On the draft, open Returns and choose Text, Fields or JSON:

Returns Answers look like Use it for
Text Refund issued on 3 March. Rewriting, summaries, replies
Fields {"label": "billing", "urgent": true} Labels, extraction, anything your code reads
JSON Any JSON object Answers whose shape each input sets, such as "pull out whatever fields this form has"

Describe each field in a few words: Facet uses the description when it writes examples and checks answers. A field can be text, one of a list of values, yes or no, a number, a whole number, a score from 0 to 1, a date and time, a link, or a list of text. Mark a field optional when an answer may leave it out.

Read the answer

The answer is in the message content, as JSON text. Parse it as usual:

import json

reply = client.chat.completions.create(
    model="invoice-fields",
    messages=[{"role": "user", "content": invoice_text}],
)
fields = json.loads(reply.choices[0].message.content)
print(fields["total"])
const reply = await client.chat.completions.create({
  model: "invoice-fields",
  messages: [{ role: "user", content: invoiceText }],
});
const fields = JSON.parse(reply.choices[0].message.content ?? "{}");
console.log(fields.total);

You don't send a response_format: Facet adds the Task's shape to every call. A Task that returns JSON also takes your own response_format, of type json_object or json_schema, to set the shape for one call; a Text Task takes one too. A Fields Task always answers in its own fields.

Change the shape later

You can add a field to what a Task returns at any time; callers that ignore it keep working. Removing or renaming a field would break callers, so for that make a new Task, with its own name and its own v1 build.

Next steps