Task mode

task is run with a contract: the final answer must match your JSON schema. Tools run as usual along the way. Providers constrain the answer natively where they can, and the result is validated client-side everywhere, so the guarantee holds on all three providers.

schema = {
type: "object",
properties: {
"calories" => { type: "integer" },
"macros" => {
type: "object",
properties: {
"protein_g" => { type: "number" },
"carbs_g" => { type: "number" },
"fat_g" => { type: "number" },
},
required: %w[protein_g carbs_g fat_g],
},
},
required: %w[calories macros],
}
result = agent.task("Analyze the nutrition of this recipe.", schema: schema)
result.output # => { "calories" => 540, "macros" => {...} }, parsed and validated

The fix loop

A validation failure goes back to the model with the exact violations, once by default (fixes: 1), then raises. Nothing silently passes through:

agent.task(input, schema: schema, fixes: 2)

A structured task is a real turn each time, so the fix exchange is visible in the session like everything else.