Reference/LLM APIs
Structured output and JSON schemas
Force {tool, args} or vendor tool_calls; reject extra keys; repair once then fail.
Free prose is for users. Machines get JSON.
Contract
text
{"tool": string, "args": object}or finish payloads with an explicit schema (citations, cannot_answer, refused).
Vendor options (conceptual)
| Style | Notes |
|---|---|
| Prompt "JSON only" | cheapest, flakiest |
| JSON mode / response_format | better, still validate |
| Native tool_calls | best; still allowlist names |
| Grammar / constrained decode | when the runtime supports it |
Joeven fakes all of these with parse_action.
Validation checklist
json.loads- type checks
- exact key set or explicit additionalProperties false
- enum of tool names
- per-tool arg schema (types, ranges, max length)
- extra keys → error, do not silently drop if they look like
execute: true
Repair
- Parse fail → system: "JSON only" → retry
- Cap
max_parse_retries - Then stop / cannot-answer
Do not regex-hope forever.
python
need = {class="tok-s">"tool", class="tok-s">"args"}
if set(obj) != need:
raise ValueError(class="tok-s">"shape")Note:Pydantic is the usual library on a real machine. In-browser Joeven uses hand-written checks so Pyodide stays stdlib-only.