docs: clarify filter prefix requirements - #1352
Conversation
There was a problem hiding this comment.
Pull request overview
This PR audits and updates user-facing documentation/examples to align with PR #1291’s stricter filter validation and the requirement to prefix user-metadata filter fields with m. / metadata..
Changes:
- Updates Python client docstrings and docs-site API references to explicitly document
m./metadata.prefixing and strict 400 behavior. - Updates integration READMEs (n8n, FastGPT) and examples to use prefixed metadata filter keys.
- Updates TS REST API docs to clarify prefixing/validation behavior for filter strings.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/client/src/memmachine_client/memory.py | Updates search() docstring to describe prefixed metadata filters and strict validation behavior. |
| packages/client/src/memmachine_client/langgraph.py | Updates tool docstring guidance for prefixed metadata fields and 400 behavior. |
| packages/client/README.md | Updates README example to use m.-prefixed filter_dict keys. |
| integrations/n8n/README.md | Updates n8n integration docs to explain m. / metadata. prefixing and strict 400 behavior. |
| integrations/fastgpt/README.md | Updates FastGPT integration docs to explain prefixed metadata fields and strict validation behavior. |
| integrations/crewai/tool.py | Updates tool docstring guidance for prefixed metadata filters and 400 behavior. |
| examples/memmachine_client_demo.py | Updates demo code to use m.-prefixed metadata filter keys. |
| docs/install_guide/integrate/n8n.mdx | Updates docs-site n8n integration guide with prefixing and strict validation notes. |
| docs/api_reference/ts-rest/interfaces/SearchMemoriesOptions.mdx | Updates TS REST docs to clarify prefixed metadata fields and strict 400 behavior. |
| docs/api_reference/python/semantic_api.mdx | Updates Python semantic API docs to mention prefixing and strict validation behavior. |
| docs/api_reference/python/memory_api.mdx | Updates Python memory API docs/examples and adds an explicit note about prefixing + strict validation. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| | query | string | - | **Required** Natural language query for memory retrieval | | ||
| | limit | number | 10 | **Required** Maximum number of search results | | ||
| | filter | string | - | Condition to filter memories | | ||
| | filter | string | - | Condition to filter memories. Prefix user metadata fields with `m.` / `metadata.` (for example `m.source = "chat_v3"`). Unknown or misspelled fields now return a 400 error. | |
There was a problem hiding this comment.
The filter example uses double quotes (m.source = "chat_v3"), but the server filter parser only treats single-quoted values as string literals. Update the example to m.source = 'chat_v3' to match the actual syntax.
| | filter | string | - | Condition to filter memories. Prefix user metadata fields with `m.` / `metadata.` (for example `m.source = "chat_v3"`). Unknown or misspelled fields now return a 400 error. | | |
| | filter | string | - | Condition to filter memories. Prefix user metadata fields with `m.` / `metadata.` (for example `m.source = 'chat_v3'`). Unknown or misspelled fields now return a 400 error. | |
| | `top_k` | `number` | The maximum number of relevant memories to return. | | ||
| | `score_threshold` | `number` | The minimum similarity score required for a memory to be included in results. | | ||
| | `filter` | `string` | A metadata-based filter string to narrow the search scope. | | ||
| | `filter` | `string` | A metadata-based filter string to narrow the search scope. User metadata fields must be prefixed with `m.` / `metadata.` (for example `m.user_id = "123"`). Unknown or misspelled fields return a 400 error. | |
There was a problem hiding this comment.
The filter example uses double quotes (m.user_id = "123"), but the server filter parser only recognizes single-quoted string literals. Update the example to use single quotes (e.g., m.user_id = '123') to avoid incorrect parsing.
| | `filter` | `string` | A metadata-based filter string to narrow the search scope. User metadata fields must be prefixed with `m.` / `metadata.` (for example `m.user_id = "123"`). Unknown or misspelled fields return a 400 error. | | |
| | `filter` | `string` | A metadata-based filter string to narrow the search scope. User metadata fields must be prefixed with `m.` / `metadata.` (for example `m.user_id = '123'`). Unknown or misspelled fields return a 400 error. | |
| | `timeout` | `int` | `None` | Request timeout in seconds. Uses client default if omitted. | | ||
|
|
||
| <Note> | ||
| When constructing filters, always prefix user metadata fields with `m.` or `metadata.`. For example, use `{"m.user_id": "123"}` instead of `{"user_id": "123"}`. Filters that reference unknown or unqualified fields now fail fast with a 400 error instead of being ignored. |
There was a problem hiding this comment.
This note says “unknown or unqualified fields” fail fast with 400. Built-in (non-metadata) fields can be unprefixed and still valid; it’s specifically unqualified user metadata fields (missing m./metadata.) that now fail. Consider rewording to avoid implying that all unprefixed fields are invalid.
| When constructing filters, always prefix user metadata fields with `m.` or `metadata.`. For example, use `{"m.user_id": "123"}` instead of `{"user_id": "123"}`. Filters that reference unknown or unqualified fields now fail fast with a 400 error instead of being ignored. | |
| When constructing filters, always prefix user metadata fields with `m.` or `metadata.`. For example, use `{"m.user_id": "123"}` instead of `{"user_id": "123"}`. Filters that reference unknown fields, or user metadata fields without the required `m.` / `metadata.` prefix, now fail fast with a 400 error instead of being ignored. Built-in non-metadata fields may still be used without a prefix when supported. |
| filter_dict: Additional metadata filters for the search (key-value pairs as strings). | ||
| User metadata keys must be prefixed with `m.` / `metadata.`. | ||
| These filters will be merged with built-in filters from metadata. | ||
| User-provided filters take precedence over built-in filters | ||
| if there are key conflicts. | ||
| if there are key conflicts. Unknown or misspelled fields return a 400 error. |
There was a problem hiding this comment.
The added guidance encourages using either m. or metadata. prefixes, but search() merges filter_dict with get_default_filter_dict() (which always uses metadata. keys) before converting to a filter string. If a caller tries to override a built-in metadata filter using the m. alias (e.g., m.user_id), it will not override at merge time and can produce contradictory conditions once the server normalizes m. to metadata. (e.g., metadata.user_id='A' AND metadata.user_id='B'). Consider normalizing m. -> metadata. in client code before merging, or update this docstring to recommend metadata. when overriding built-in metadata filters.
| @@ -110,7 +110,7 @@ print(f"Episodic memory: {results.get('episodic_memory', [])}") | |||
| print(f"Profile memory: {results.get('profile_memory', [])}") | |||
|
|
|||
| # Search with filters | |||
| work_results = memory.search("Tell me about work", filter_dict={"category": "work"}) | |||
| work_results = memory.search("Tell me about work", filter_dict={"m.category": "work"}) | |||
There was a problem hiding this comment.
This README example treats memory.search() results as a dict (using .get(...)), but the Python client Memory.search() returns a SearchResult Pydantic model. The snippet will raise an AttributeError when copied. Consider updating the example to use results.content..., results.model_dump(), or the provided format_search_result(results) helper.
| | query | string | - | **Required.** Natural language query used to search for relevant memories. | | ||
| | limit | number | 50 | Maximum number of results to return. | | ||
| | filter | string | - | Filter expression to refine memory search results. | | ||
| | filter | string | - | Filter expression to refine memory search results. Prefix user metadata fields with `m.` / `metadata.` (for example `m.user_id = "123"`). Unknown or misspelled fields now return a 400 error. | |
There was a problem hiding this comment.
The filter expression example uses double quotes (m.user_id = "123"), but the server filter parser only recognizes single-quoted string literals. With double quotes, the quotes are ignored during tokenization and numeric values may be parsed as ints, changing semantics. Update the example to use single quotes (e.g., m.user_id = '123').
| | filter | string | - | Filter expression to refine memory search results. Prefix user metadata fields with `m.` / `metadata.` (for example `m.user_id = "123"`). Unknown or misspelled fields now return a 400 error. | | |
| | filter | string | - | Filter expression to refine memory search results. Prefix user metadata fields with `m.` / `metadata.` (for example `m.user_id = '123'`). Unknown or misspelled fields now return a 400 error. | |
| | **limit** | Number | 50 | Maximum number of memory results to return. | | ||
| | **scoreThreshold** | Number | - | Minimum relevance score required to include a memory. | | ||
| | **filter** | String | - | Filter expression to refine memory search results. | | ||
| | **filter** | String | - | Filter expression to refine memory search results. Prefix user metadata fields with `m.` / `metadata.` (for example `m.user_id = "123"`). Unknown or misspelled fields return a 400 error. | |
There was a problem hiding this comment.
The filter expression example uses double quotes (m.user_id = "123"), but the server filter language only supports single-quoted string literals. Using double quotes can change parsing (e.g., numbers become ints). Update the example to use single quotes (e.g., m.user_id = '123').
| | **filter** | String | - | Filter expression to refine memory search results. Prefix user metadata fields with `m.` / `metadata.` (for example `m.user_id = "123"`). Unknown or misspelled fields return a 400 error. | | |
| | **filter** | String | - | Filter expression to refine memory search results. Prefix user metadata fields with `m.` / `metadata.` (for example `m.user_id = '123'`). Unknown or misspelled fields return a 400 error. | |
SarahScargall
left a comment
There was a problem hiding this comment.
The resulting text may seem very long in the existing tables. We'll approve, and if necessary, I may pull this to a callout at a future time.
|
Hi @haosenwang1018! For this PR (and all your other PRs) to merge, we need you to sign your commits. Also, please take a look at the feedback that CoPilot has generated and respond to it accordingly. Kind Regards, |
|
@haosenwang1018 Please sign your commits. It's blocking the merge. Thanks. |
Audit user-facing filter documentation after PR MemMachine#1291 so examples and parameter descriptions consistently reflect the new metadata prefix requirement and strict validation behavior. Public-facing docs/examples/docstrings that still implied bare metadata keys were valid in filters now: - use prefixed metadata filter examples (`m.` / `metadata.`) - clarify `m.` / `metadata.` requirements in Python + TS REST docs - document 400 behavior for unknown or unqualified user metadata fields - sync integration docs (n8n, FastGPT, CrewAI, LangGraph) and the Python client demo/README with the stricter filter syntax Address Copilot review feedback: - Use single-quoted string literals in filter examples (`m.user_id = '123'`, `m.source = 'chat_v3'`) — the server filter parser only treats single-quoted values as string literals, so double-quoted examples could change parsing semantics for numeric strings (`"123"` would tokenize as the integer 123). - Reword the Python `<Note>` callout to specify that only *unqualified user metadata fields* (and misspelled built-in fields) trigger the new 400 error — built-in non-metadata fields can still be unprefixed. - Fix the Python client README `Memory.search()` example: the method returns a `SearchResult` Pydantic model, so use `results.content.episodic_memory` / `.semantic_memory` instead of `results.get(...)`. - Expand the `Memory.search()` docstring to call out that mixing `m.<key>` with a built-in `metadata.<key>` does not override at the client-side merge step and can produce a contradictory `metadata.<key>=A AND metadata.<key>=B` filter after server normalization. Fixes MemMachine#1308 Fixes MemMachine#1306 Fixes MemMachine#1307 Signed-off-by: haosenwang1018 <haosenwang1018@users.noreply.github.com> Co-authored-by: Steve Scargall <37674041+sscargal@users.noreply.github.com> Signed-off-by: Steve Scargall <37674041+sscargal@users.noreply.github.com>
3e95289 to
a103c12
Compare
Update the API docstrings and the TypeScript `ListMemoriesOptions` reference to document the `m.` / `metadata.` prefix requirement for user-defined metadata fields in the filter expression language. Unknown or unsupported fields are now rejected by the server (see MemMachine#1291), so referencing user metadata without a prefix returns a 400 instead of being silently ignored. Files updated: - `packages/common/src/memmachine_common/api/doc.py` — `SEARCH_MEMORIES` and `LIST_MEMORIES` endpoint docstrings. - `docs/api_reference/ts-rest/interfaces/ListMemoriesOptions.mdx` — `filter` property description + `m.source = "chat_v3"` example in the usage snippet. - `docs/openapi.json` — regenerated from the updated doc.py via `docs/tools/generate_openapi.py`. The original PR (MemMachine#1333) also touched `docs/api_reference/python/memory_api.mdx` and `docs/api_reference/ts-rest/interfaces/SearchMemoriesOptions.mdx`, but `main` has since received equivalent (and slightly more detailed) wording in both files via the merge of MemMachine#1352 and the related cleanup. Those hunks have been dropped during rebase to avoid no-op conflicts. Refs: MemMachine#1333 Co-authored-by: Steve Scargall <steve.scargall@gmail.com> Signed-off-by: Steve Scargall <37674041+sscargal@users.noreply.github.com>
…ion (#1403) * feat(client+langgraph): raw filter strings and EpisodeType normalization Add three small features to the Python client and its LangGraph wrapper so callers can pass structured filter expressions and either-enum-or-string episode types directly. 1. `Memory.search(filter=...)` and `Memory.list(filter=...)` Accept an optional raw filter string alongside `filter_dict`. When both are provided, the two are combined with `AND`. The raw filter is passed through to the v2 `SearchMemoriesSpec.filter` / `ListMemoriesSpec.filter` fields unchanged. 2. `MemMachineTools.search_memory(filter=...)` Pipes the same raw filter through the LangGraph search-memory tool. 3. `MemMachineTools.add_memory(episode_type=...)` Accept either an `EpisodeType` enum or its string value (e.g. `"message"`), normalizing strings via `EpisodeType(...)` before delegating to `Memory.add`. The factory tool's return-type annotation was widened to match. The `filter` parameter shadows the Python builtin, which is the same trade-off `memmachine_common.api.SearchMemoriesSpec` already made for its `filter:` field — keeping the parameter name aligned with the API field. `# noqa: A002` is applied at the three call sites with a comment pointing at the API spec. This commit consolidates the substantive work from haosenwang1018's 9-commit stack (#1341 → #1349) into a single rebased+linted commit against current `main`. The original stack's prefix-style doc and test changes have been omitted because they have already landed on `main` via #1352 and #1311. The original commits authored by haosenwang1018: - 921b55f feat(client): support raw filter strings - e0849bb feat(langgraph): support raw filter strings - 53b489e fix(langgraph): normalize episode type strings Closes #1341, #1342, #1343, #1344, #1345, #1346, #1347, #1348, #1349 Co-authored-by: Steve Scargall <steve.scargall@gmail.com> Signed-off-by: Steve Scargall <37674041+sscargal@users.noreply.github.com> * docs(langgraph): document filter and episode type support --------- Signed-off-by: Steve Scargall <37674041+sscargal@users.noreply.github.com> Co-authored-by: haosenwang1018 <haosenwang1018@users.noreply.github.com> Co-authored-by: Shu Wang <33640803+malatewang@users.noreply.github.com>
Update the API docstrings and the TypeScript `ListMemoriesOptions` reference to document the `m.` / `metadata.` prefix requirement for user-defined metadata fields in the filter expression language. Unknown or unsupported fields are now rejected by the server (see #1291), so referencing user metadata without a prefix returns a 400 instead of being silently ignored. Files updated: - `packages/common/src/memmachine_common/api/doc.py` — `SEARCH_MEMORIES` and `LIST_MEMORIES` endpoint docstrings. - `docs/api_reference/ts-rest/interfaces/ListMemoriesOptions.mdx` — `filter` property description + `m.source = "chat_v3"` example in the usage snippet. - `docs/openapi.json` — regenerated from the updated doc.py via `docs/tools/generate_openapi.py`. The original PR (#1333) also touched `docs/api_reference/python/memory_api.mdx` and `docs/api_reference/ts-rest/interfaces/SearchMemoriesOptions.mdx`, but `main` has since received equivalent (and slightly more detailed) wording in both files via the merge of #1352 and the related cleanup. Those hunks have been dropped during rebase to avoid no-op conflicts. Refs: #1333 Signed-off-by: Steve Scargall <37674041+sscargal@users.noreply.github.com> Co-authored-by: haosenwang1018 <haosenwang1018@users.noreply.github.com> Co-authored-by: Steve Scargall <steve.scargall@gmail.com>
Purpose of the change
Audit the user-facing filter documentation after PR #1291 so examples and parameter descriptions consistently reflect the new metadata prefix requirement and strict validation behavior.
Description
This PR updates public-facing docs/examples/docstrings that still implied bare metadata keys were valid in filters.
Changes included:
m./metadata.requirements in Python + TS REST docsFixes/Closes
Fixes #1308
Fixes #1306
Fixes #1307
Type of change
How Has This Been Tested?
Test Results:
git diff --checkm./metadata.prefixes and documents the strict 400 behavior, while excluding server/test internals from the docs-only scope.Checklist
Screenshots/Gifs
N/A
Further comments
None.