Skip to content

fix: add missing 'json' keyword to graph memory prompts (fixes #4248)#4249

Merged
deshraj merged 4 commits intomem0ai:mainfrom
giulio-leone:fix/graph-memory-json-keyword-4248
Mar 13, 2026
Merged

fix: add missing 'json' keyword to graph memory prompts (fixes #4248)#4249
deshraj merged 4 commits intomem0ai:mainfrom
giulio-leone:fix/graph-memory-json-keyword-4248

Conversation

@giulio-leone
Copy link
Copy Markdown
Contributor

Summary

Fixes #4248 — Graph memory writes fail with OpenAI 400 error because DELETE_RELATIONS_SYSTEM_PROMPT and the entity extraction prompt are missing the required "json" keyword when used with response_format: { type: 'json_object' }.

Problem

OpenAI's API enforces that when response_format: { type: 'json_object' } is set, at least one message in the conversation must contain the word "json". Two prompts in the graph memory pipeline violated this:

  1. DELETE_RELATIONS_SYSTEM_PROMPT in utils.ts — used by _getDeleteEntitiesFromSearchOutput()
  2. Entity extraction prompt in graph_memory.ts — used by _retrieveNodesFromData()

This caused every memory.add() call with enableGraph: true and OpenAI as the LLM provider to fail with:

BadRequestError: 400 'messages' must contain the word 'json' in some form,
to use 'response_format' of type 'json_object'.

Fix

Added "Respond in JSON format." to both prompts, consistent with the existing fix in EXTRACT_RELATIONS_PROMPT which already had "\nPlease provide your response in JSON format." appended.

Changes

  • mem0-ts/src/oss/src/graphs/utils.ts: Added "Respond in JSON format." to DELETE_RELATIONS_SYSTEM_PROMPT
  • mem0-ts/src/oss/src/memory/graph_memory.ts: Added "Respond in JSON format." to the inline entity extraction system prompt in _retrieveNodesFromData()

Testing

Verified that all three json_object response format calls now have the required keyword:

  • _getDeleteEntitiesFromSearchOutput() — ✅ fixed
  • _retrieveNodesFromData() — ✅ fixed
  • _getRelatedEntities() — ✅ already had it (EXTRACT_RELATIONS_PROMPT)

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Mar 7, 2026

CLA assistant check
All committers have signed the CLA.

Copy link
Copy Markdown

@xkonjin xkonjin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quick review pass:

  • Main risk area here is data integrity, transaction boundaries, and backward-compatible persistence.
  • I didn’t see targeted regression coverage in the diff; please add or point CI at a focused test for the changed path in utils.ts, graph_memory.ts.
  • Before merge, I’d smoke-test the behavior touched by utils.ts, graph_memory.ts with malformed input / retry / rollback cases, since that’s where this class of change usually breaks.

@giulio-leone giulio-leone force-pushed the fix/graph-memory-json-keyword-4248 branch from 2bd33cc to 01968b2 Compare March 8, 2026 02:26
@giulio-leone
Copy link
Copy Markdown
Contributor Author

@xkonjin Thanks for the review! To clarify:

  1. Scope: This is a minimal 2-line fix — just adding the word "json" to two existing prompt strings (DELETE_RELATIONS_SYSTEM_PROMPT in utils.ts and the entity extraction prompt in graph_memory.ts). No logic changes, no transaction boundaries affected.

  2. Testing: The fix is straightforward string content — OpenAI's API requires "json" to appear in at least one message when response_format: { type: 'json_object' } is set. Without it, the API returns 400. The existing EXTRACT_RELATIONS_PROMPT already has this pattern.

  3. CLA: Fixed the commit author email to match my GitHub account — the CLA check should clear now.

Happy to add a targeted test if the maintainers want one, but the failure mode here is a hard 400 from OpenAI (not a silent data integrity issue).

@giulio-leone
Copy link
Copy Markdown
Contributor Author

I have read the CLA Document and I hereby sign the CLA

@giulio-leone giulio-leone force-pushed the fix/graph-memory-json-keyword-4248 branch 2 times, most recently from 3f8ff3b to 597d6c6 Compare March 8, 2026 13:21
@giulio-leone
Copy link
Copy Markdown
Contributor Author

@xkonjin Added regression tests as requested — graph-prompts.test.ts verifies that DELETE_RELATIONS_SYSTEM_PROMPT and getDeleteMessages() output contain the "json" keyword required by OpenAI's json_object response format. Both tests pass.

The entity extraction prompt in graph_memory.ts is inline (not exported), so it's tested indirectly through the fix itself — removing "Respond in JSON format." would immediately cause a 400 from OpenAI.

Thanks for the review!

@giulio-leone
Copy link
Copy Markdown
Contributor Author

@xkonjin Thanks for the review! You're right — I'll add focused regression tests for the changed paths in utils.ts and graph_memory.ts, including malformed input and edge cases. Will push shortly.

@giulio-leone giulio-leone force-pushed the fix/graph-memory-json-keyword-4248 branch 2 times, most recently from 0d87c72 to 32a1c68 Compare March 9, 2026 01:01
@giulio-leone
Copy link
Copy Markdown
Contributor Author

Thanks for the review @xkonjin!

Rebased onto latest main — merge conflict is resolved.

Regarding the regression coverage you asked about — the branch already includes two dedicated test suites (48 tests total, all passing):

  • graph-prompts.test.ts — verifies the "json" keyword is present in every prompt that uses json_object response format (DELETE_RELATIONS_SYSTEM_PROMPT, EXTRACT_RELATIONS_PROMPT, and the inline entity extraction prompt). Also covers getDeleteMessages and formatEntities with edge cases: empty strings, special characters, unicode, and very long inputs.

  • graph-memory-parsing.test.ts — mocked MemoryGraph tests exercising all three json_object call sites (_retrieveNodesFromData, _establishNodesRelationsFromData, _getDeleteEntitiesFromSearchOutput). Covers: well-formed responses, plain-string LLM responses, empty/missing tool calls, malformed JSON arguments, missing entities key, unrelated tool names, and prompt construction assertions (confirms response_format: { type: "json_object" } is passed and the system message contains "json").

@giulio-leone giulio-leone force-pushed the fix/graph-memory-json-keyword-4248 branch from 32a1c68 to 4e9f954 Compare March 9, 2026 16:10
@giulio-leone
Copy link
Copy Markdown
Contributor Author

Friendly ping — CI is green, tests pass, rebased on latest. Ready for review whenever convenient. Happy to address any feedback. 🙏

…n_object response format

When using OpenAI with response_format: { type: 'json_object' }, the API
requires at least one message to contain the word 'json'. The
DELETE_RELATIONS_SYSTEM_PROMPT and the entity extraction prompt in
_retrieveNodesFromData() were missing this keyword, causing a 400 error
on every graph memory write.

The EXTRACT_RELATIONS_PROMPT already had 'Please provide your response
in JSON format.' appended — this commit applies the same fix to the two
remaining prompts.

Fixes #4248
Verifies that DELETE_RELATIONS_SYSTEM_PROMPT and getDeleteMessages()
output contain the "json" keyword required by OpenAI's json_object
response format. Without it, the API returns a 400 error.

Signed-off-by: Giulio Leone <6887247+giulio-leone@users.noreply.github.com>
Address reviewer feedback (xkonjin) requesting targeted regression
coverage for the changed paths in utils.ts and graph_memory.ts.

New tests (21 total, up from 2):

- JSON keyword requirement: verify all three json_object call sites
  (DELETE_RELATIONS_SYSTEM_PROMPT, EXTRACT_RELATIONS_PROMPT + suffix,
  inline entity extraction prompt) contain 'json'
- getDeleteMessages: USER_ID substitution, return shape, content
  inclusion, plus malformed/edge-case inputs (empty strings, special
  characters, unicode, very long strings)
- formatEntities: single/multiple entities, empty array, special chars
- Prompt structural invariants: placeholder presence, non-empty guards
Address reviewer feedback (xkonjin) requesting smoke-tests for the
changed code paths in graph_memory.ts with malformed input and edge
cases.

New test file: graph-memory-parsing.test.ts (27 tests)

Mocks neo4j-driver, LLMFactory, and EmbedderFactory to unit-test the
three private methods that use json_object response format:

_retrieveNodesFromData:
  - well-formed tool calls, string responses, undefined/empty toolCalls
  - malformed JSON in arguments, missing entities key
  - unrelated tool call names, entity normalisation
  - json_object format and JSON keyword in system prompt

_establishNodesRelationsFromData:
  - well-formed tool calls, string/empty responses
  - missing entities key in arguments
  - malformed JSON throws (no try/catch in source)
  - prompt suffix with/without custom prompt
  - JSON keyword present in system message

_getDeleteEntitiesFromSearchOutput:
  - well-formed delete calls, string/empty responses
  - filtering by tool call name, multiple deletes
  - empty search output, JSON keyword in prompt

Cross-cutting:
  - JSON keyword present for varied userId values (empty, unicode, special chars)
  - Entity normalisation (spaces→underscores, lowercasing)
@giulio-leone giulio-leone force-pushed the fix/graph-memory-json-keyword-4248 branch from 4e9f954 to 909cf66 Compare March 9, 2026 21:11
@kartik-mem0 kartik-mem0 requested a review from whysosaket March 13, 2026 07:57
@deshraj deshraj merged commit e95090e into mem0ai:main Mar 13, 2026
1 of 2 checks passed
jamebobob pushed a commit to jamebobob/mem0-vigil-recall that referenced this pull request Mar 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Graph memory writes fail with OpenAI 400: DELETE_RELATIONS_SYSTEM_PROMPT missing required "json" keyword

4 participants