-
Notifications
You must be signed in to change notification settings - Fork 2
bug(memory): graph extraction 400 Bad Request with OpenAI -- strict mode schema incompatibility #1656
Description
Bug
Graph entity extraction fails with 400 Bad Request when using OpenAI providers (gpt-4o-mini, gpt-4o).
Root Cause
GraphExtractor::extract() calls chat_typed_erased::<ExtractionResult> which uses cached_schema::<T>() to generate a JSON Schema via schemars::schema_for!(). The generated schema is sent as response_format: {type: "json_schema", strict: true, ...} to OpenAI.
OpenAI's structured output requirements for strict: true mode mandate:
additionalProperties: falseon all object schemas —schemarsdoes not add this- All fields must appear in
required— optional fields (summary,temporal_hint: Option<String>) are generated as non-required byschemars
When these conditions are violated, OpenAI returns 400 Bad Request.
Reproduction
Run graph test with extract_model = "gpt-4o-mini" via ACP. Both conversation turns trigger extraction; all extraction calls fail with:
WARN zeph_memory::semantic: graph extraction failed: LLM error: OpenAI API request failed (status 400 Bad Request)
Graph works in CLI mode with Claude Haiku (Claude handles $defs/optional differently).
Fix
cached_schema::<T>() must post-process the generated schema before sending to OpenAI:
- Recursively add
"additionalProperties": falseto alltype: "object"schemas - Move all properties to
required, and forOption<T>fields useanyOf: [{...T schema}, {"type": "null"}]
The Gemini provider already handles schema normalization via normalize_schema() in gemini.rs (PR #1635). A similar transform is needed for OpenAI's structured output path.
Alternatively: use response_format: {type: "json_object"} (no-strict mode) with explicit schema in system prompt for extraction — this avoids strict-mode requirements and works with all OpenAI models.
Impact
- All graph extraction via OpenAI providers is broken (silently fails with 400)
- Claude providers unaffected (structured output schema requirements differ)
- Discovered after fix(acp): apply graph memory config to ACP sessions #1645 fix made graph config reachable in ACP sessions
Severity
High — graph memory feature non-functional with OpenAI providers