Summary
Add an opt-in strict=True path to chainweaver/export/openai.py so exported function payloads satisfy OpenAI's structured-outputs requirements: strict: true on the function plus additionalProperties: false on every object schema (recursively), with all properties marked required as the spec demands.
Why this matters
OpenAI's structured-outputs / strict function calling guarantees the model returns arguments matching the schema, which is exactly the determinism story ChainWeaver sells. Today _build_payload emits a plain function schema (no strict, no additionalProperties: false), so users who paste the export into a strict tool definition get a runtime rejection. Closing this makes the export adapter a drop-in for the most reliability-conscious OpenAI users.
Current evidence
chainweaver/export/openai.py _build_payload produces {"type": "function", "function": {name, description, parameters}} and only schema.pop("title", None) — no strict flag and no additionalProperties: false injection.
chainweaver/export/_schema.py (model_input_schema_json) is the shared schema emitter where recursive transformation would live.
examples/export_openai_anthropic.py and docs/ (## Export adapters in README) demonstrate the adapter, so a strict variant has an obvious documentation home.
External context
OpenAI's structured-outputs guide requires additionalProperties: false on every object and all keys listed in required when strict: true; passing a schema that violates this is rejected at request time.
Proposed implementation
- Add
strict: bool = False to flow_to_openai_function/tool_to_openai_function; thread into _build_payload.
- Implement a pure recursive schema transformer (in
_schema.py) that, on every object node, sets additionalProperties: false and promotes all properties to required, handling $defs/$ref, anyOf/oneOf, and arrays.
- Document the constraint that optional fields must use nullable-with-default patterns under strict mode (OpenAI requirement) and surface a clear
ExportError when a schema cannot be made strict-compatible.
- Mirror any reusable transform for the Anthropic adapter if applicable (note relation, do not over-scope).
AI-agent execution notes
Inspect chainweaver/export/openai.py, chainweaver/export/_schema.py, chainweaver/export/anthropic.py, existing export tests under tests/. Keep the transform pure and deterministic (no network). Edge cases: nested models via $ref, lists of models, enums, fields with existing additionalProperties. Do not change the default (non-strict) output shape.
Acceptance criteria
flow_to_openai_function(flow, strict=True) produces strict: true and additionalProperties: false on every object including nested $defs.
- A round-trip test validates the payload against OpenAI's documented strict constraints (structural assertions, offline).
- Default behavior is byte-for-byte unchanged.
Test plan
Unit tests for flat/nested/array/$ref/enum schemas under strict mode; assertion that every object node has additionalProperties: false; regression test for the non-strict default; example script update run in CI.
Documentation plan
README ## Export adapters section, examples/export_openai_anthropic.py, a cookbook note, CHANGELOG.
Migration and compatibility notes
Not expected to require migration (opt-in flag; default unchanged).
Risks and tradeoffs
Strict mode forbids genuinely-optional fields, which can surprise users with optional tool inputs — document the nullable-with-default pattern and fail loudly rather than silently producing an invalid schema.
Suggested labels
integrations, ecosystem, product
Summary
Add an opt-in
strict=Truepath tochainweaver/export/openai.pyso exported function payloads satisfy OpenAI's structured-outputs requirements:strict: trueon the function plusadditionalProperties: falseon every object schema (recursively), with all properties marked required as the spec demands.Why this matters
OpenAI's structured-outputs / strict function calling guarantees the model returns arguments matching the schema, which is exactly the determinism story ChainWeaver sells. Today
_build_payloademits a plain function schema (nostrict, noadditionalProperties: false), so users who paste the export into a strict tool definition get a runtime rejection. Closing this makes the export adapter a drop-in for the most reliability-conscious OpenAI users.Current evidence
chainweaver/export/openai.py_build_payloadproduces{"type": "function", "function": {name, description, parameters}}and onlyschema.pop("title", None)— nostrictflag and noadditionalProperties: falseinjection.chainweaver/export/_schema.py(model_input_schema_json) is the shared schema emitter where recursive transformation would live.examples/export_openai_anthropic.pyanddocs/(## Export adaptersin README) demonstrate the adapter, so a strict variant has an obvious documentation home.External context
OpenAI's structured-outputs guide requires
additionalProperties: falseon every object and all keys listed inrequiredwhenstrict: true; passing a schema that violates this is rejected at request time.Proposed implementation
strict: bool = Falsetoflow_to_openai_function/tool_to_openai_function; thread into_build_payload._schema.py) that, on every object node, setsadditionalProperties: falseand promotes all properties torequired, handling$defs/$ref,anyOf/oneOf, and arrays.ExportErrorwhen a schema cannot be made strict-compatible.AI-agent execution notes
Inspect
chainweaver/export/openai.py,chainweaver/export/_schema.py,chainweaver/export/anthropic.py, existing export tests undertests/. Keep the transform pure and deterministic (no network). Edge cases: nested models via$ref, lists of models, enums, fields with existingadditionalProperties. Do not change the default (non-strict) output shape.Acceptance criteria
flow_to_openai_function(flow, strict=True)producesstrict: trueandadditionalProperties: falseon every object including nested$defs.Test plan
Unit tests for flat/nested/array/
$ref/enum schemas under strict mode; assertion that every object node hasadditionalProperties: false; regression test for the non-strict default; example script update run in CI.Documentation plan
README
## Export adapterssection,examples/export_openai_anthropic.py, a cookbook note, CHANGELOG.Migration and compatibility notes
Not expected to require migration (opt-in flag; default unchanged).
Risks and tradeoffs
Strict mode forbids genuinely-optional fields, which can surprise users with optional tool inputs — document the nullable-with-default pattern and fail loudly rather than silently producing an invalid schema.
Suggested labels
integrations, ecosystem, product