Structured Output
Generate schema-validated JSON objects with the generate_object tool.
Structured Output
The built-in generate_object tool asks the configured LLM for a JSON object,
validates the response against a JSON Schema you supply, and returns the
validated object only on a zero-exit result. Use it whenever you need
machine-readable results: extraction, classification, config generation, or
feeding another program.
You can call it directly through session.tool('generate_object', ...). The
tool result carries the validated object as JSON on result.output — parse it
and read the object field. The same tool also supports agent-driven
invocation, where the model decides to call it during a send.
Direct tool call
The simplest path: call generate_object directly, check the tool exit code,
and parse the validated object out of the result.
import { Agent } from '@a3s-lab/code';
const agent = await Agent.create('agent.acl');
const session = agent.session('.');
const result = await session.tool('generate_object', {
schema: {
type: 'object',
required: ['name', 'age', 'skills'],
properties: {
name: { type: 'string' },
age: { type: 'integer', minimum: 0 },
skills: {
type: 'array',
items: { type: 'string' },
minItems: 1,
},
},
},
prompt: 'Extract: "Alice is 28, skilled in Rust, TypeScript, and Python."',
schema_name: 'developer',
mode: 'tool',
});
if (result.exitCode !== 0) {
throw new Error(result.output);
}
const { object } = JSON.parse(result.output);
console.log(object);
// { name: "Alice", age: 28, skills: ["Rust", "TypeScript", "Python"] }
session.close();import json
from a3s_code import Agent
agent = Agent.create('agent.acl')
session = agent.session('.')
result = session.tool("generate_object", {
"schema": {
"type": "object",
"required": ["name", "age", "skills"],
"properties": {
"name": {"type": "string"},
"age": {"type": "integer", "minimum": 0},
"skills": {
"type": "array",
"items": {"type": "string"},
"minItems": 1,
},
},
},
"prompt": 'Extract: "Alice is 28, skilled in Rust, TypeScript, and Python."',
"schema_name": "developer",
"mode": "tool",
})
if result.exit_code != 0:
raise RuntimeError(result.output)
obj = json.loads(result.output)["object"]
print(obj)
# {"name": "Alice", "age": 28, "skills": ["Rust", "TypeScript", "Python"]}
session.close()The validated value lives on the object key of the parsed output. When
result.exitCode (Node) / result.exit_code (Python) is zero, fields declared
in required have passed runtime validation. If the model cannot satisfy the
schema after repair attempts, the tool reports a non-zero exit code.
Enum classification
Constrain a field to a fixed set with enum. This turns a free-form model
classification into a schema-gated result.
const result = await session.tool('generate_object', {
schema: {
type: 'object',
required: ['sentiment', 'confidence'],
properties: {
sentiment: { type: 'string', enum: ['positive', 'negative', 'neutral'] },
confidence: { type: 'number', minimum: 0, maximum: 1 },
},
},
prompt: 'Classify sentiment: "This is the worst product I have ever used."',
schema_name: 'sentiment',
});
const { object } = JSON.parse(result.output);
console.log(object.sentiment, object.confidence); // "negative" 0.97result = session.tool("generate_object", {
"schema": {
"type": "object",
"required": ["sentiment", "confidence"],
"properties": {
"sentiment": {"type": "string", "enum": ["positive", "negative", "neutral"]},
"confidence": {"type": "number", "minimum": 0, "maximum": 1},
},
},
"prompt": 'Classify sentiment: "This is the worst product I have ever used."',
"schema_name": "sentiment",
})
obj = json.loads(result.output)["object"]
print(obj["sentiment"], obj["confidence"]) # "negative" 0.97Nested schemas and arrays
Schemas can nest objects and arrays to any depth, and the runtime validates the whole structure. This models real config files, manifests, or API payloads in one call.
const result = await session.tool('generate_object', {
schema: {
type: 'object',
required: ['items'],
properties: {
items: {
type: 'array',
minItems: 3,
maxItems: 5,
items: {
type: 'object',
required: ['name', 'category'],
properties: {
name: { type: 'string' },
category: { type: 'string', enum: ['fruit', 'vegetable', 'grain'] },
},
},
},
},
},
prompt: 'List 3 food items with their categories.',
schema_name: 'food_list',
});
const { items } = JSON.parse(result.output).object;
console.log(items.length, items.map((i) => i.name));result = session.tool("generate_object", {
"schema": {
"type": "object",
"required": ["items"],
"properties": {
"items": {
"type": "array",
"minItems": 3,
"maxItems": 5,
"items": {
"type": "object",
"required": ["name", "category"],
"properties": {
"name": {"type": "string"},
"category": {"type": "string", "enum": ["fruit", "vegetable", "grain"]},
},
},
},
},
},
"prompt": "List 3 food items with their categories.",
"schema_name": "food_list",
})
items = json.loads(result.output)["object"]["items"]
print(len(items), [i["name"] for i in items])Agent-driven invocation
You can also let the agent decide when to use structured output. Ask it to call generate_object during a send; it gathers context first, then emits the object.
const result = await session.send(
'Use the generate_object tool to extract the following into an object ' +
'with fields "title" (string), "year" (integer), "genre" (string): ' +
'The movie "Inception" was released in 2010 and is a sci-fi thriller.'
);
console.log(`tool calls: ${result.toolCallsCount}, tokens: ${result.totalTokens}`);result = session.send(
'Use the generate_object tool to produce a JSON object with schema '
'{"type":"object","required":["language","paradigm"],"properties":'
'{"language":{"type":"string"},"paradigm":{"type":"string"}}} '
'for: "Rust is a systems programming language with a focus on safety."'
)
print(f"tool calls: {result.tool_calls_count}, tokens: {result.total_tokens}")Schema validation coverage
The built-in validator supports:
type(including nullable arrays like["string", "null"])required,properties,additionalPropertiesenum,constanyOf,oneOfminLength,maxLength,patternminimum,maximum,exclusiveMinimum,exclusiveMaximumminItems,maxItems,items- Nested object and array validation
Notes
- The validated value is on the
objectkey of the parsedresult.output. Passmode: 'tool'for the current cross-provider default, ormode: 'prompt'for a prompt-only fallback.auto,strict, andjsoncurrently resolve totoolin this runtime path. - List every field you depend on in
required— the runtime enforces it, so missing or mistyped fields fail validation instead of silently returning partial data. generate_objectis a built-in tool registered independently of built-in skills.- Direct
session.tool(...)calls are host control-plane calls. UsepermissionPolicywhen you let the model choose tools insidesend/run/stream; use host authorization before direct SDK calls.
A runnable version ships at crates/code/sdk/node/examples/basic/test_generate_object.ts and crates/code/sdk/python/examples/test_generate_object.py.