SyntheticOutput (Phase 79.3)
SyntheticOutput forces a goal to terminate with a JSON value that
matches a caller-provided JSONSchema. Closes the gap between "model
produces free prose" and "downstream consumer needs a struct" —
direct input for Phase 19/20 pollers, Phase 51 eval harness, and any
future contract-shaped goal.
Lift from
upstream agent CLI.
Diff vs upstream
The upstream CLI builds one tool per schema via
createSyntheticOutputTool(jsonSchema) so the model's input is the
schema. Nexo-rs runs as a daemon — building a fresh tool per call
breaks tool-registry semantics. We ship a single tool whose input
carries BOTH the schema and the value:
{
"schema": { "type": "object", "properties": { "name": { "type": "string" } }, "required": ["name"] },
"value": { "name": "ana" }
}
Pollers and eval harnesses inject the schema via prompt template;
ad-hoc callers pass it inline. The terminal_schema follow-up
(tracked in FOLLOWUPS.md) lets the runtime carry the schema and only
the model's value flows on the wire — closer to the upstream
single-input shape.
Tool shape
| Arg | Type | Required | Notes |
|---|---|---|---|
schema | object | yes | JSONSchema (Draft 7 / 2019-09 / 2020-12). Must be a JSON object. |
value | any | yes | The value to validate. Object / array / scalar — any shape the schema permits. |
Response
{
"ok": true,
"structured_output": <value>,
"instructions": "Output validated. The goal can terminate now — do not call any other tool this turn unless the goal contract calls for it explicitly."
}
On failure the call returns an error whose body lists every violation with its JSONPath:
SyntheticOutput: value does not match schema (2 errors): /age: 30 is not of type "string"; /tags/0: "purple" is not one of ["red","green"]
Validation
Uses jsonschema = "0.20" — already an optional dep on
nexo-core (default-on via the schema-validation Cargo feature
that Phase 9.2 introduced). Builds without the feature compile, but
SyntheticOutput returns a clear "feature disabled" error rather
than silently passing through — synthesised output without
validation is worse than no synthesis.
Plan-mode classification
Classified ReadOnly in nexo_core::plan_mode::READ_ONLY_TOOLS.
The tool only validates and echoes; it never touches workspace,
broker, or external state. Safe to call while plan mode is on.
References
- PRIMARY:
upstream agent CLI. - SECONDARY: OpenClaw
research/— no equivalent. Single-process TS reference shapes its outputs via Zod parsing inline; no separate "force structured output" tool. - Plan + spec:
proyecto/PHASES.md::79.3.