Skip to content

docs: clarify filter prefix requirements - #1352

Merged
sscargal merged 1 commit into
MemMachine:mainfrom
haosenwang1018:docs/filter-prefix-doc-audit
May 13, 2026
Merged

docs: clarify filter prefix requirements#1352
sscargal merged 1 commit into
MemMachine:mainfrom
haosenwang1018:docs/filter-prefix-doc-audit

Conversation

@haosenwang1018

Copy link
Copy Markdown
Contributor

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:

  • update Python API docs to use prefixed metadata filter examples
  • clarify m. / metadata. requirements in Python + TS REST docs
  • document 400 behavior for unknown or unqualified filter fields
  • sync integration docs (n8n, FastGPT, CrewAI, LangGraph) and the Python client demo/README with the stricter filter syntax

Fixes/Closes

Fixes #1308
Fixes #1306
Fixes #1307

Type of change

  • Documentation update

How Has This Been Tested?

  • Manual verification (list step-by-step instructions)

Test Results:

  • Ran git diff --check
  • Ran a targeted repository grep over public-facing docs/examples/docstrings to verify the updated filter guidance consistently uses m. / metadata. prefixes and documents the strict 400 behavior, while excluding server/test internals from the docs-only scope.

Checklist

  • I have signed the commit(s) within this pull request
  • I have performed a self-review of my own code
  • I have made corresponding changes to the documentation
  • I have checked my code and corrected any misspellings

Screenshots/Gifs

N/A

Further comments

None.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

Comment thread integrations/fastgpt/README.md Outdated
| 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. |

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

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

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.

Suggested change
| 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. |

Copilot uses AI. Check for mistakes.
| `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. |

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

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

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.

Suggested change
| `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. |

Copilot uses AI. Check for mistakes.
| `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.

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

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

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.

Suggested change
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.

Copilot uses AI. Check for mistakes.
Comment on lines +387 to +391
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.

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
Comment thread packages/client/README.md Outdated
Comment on lines +109 to +113
@@ -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"})

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
Comment thread integrations/n8n/README.md Outdated
| 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. |

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

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

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').

Suggested change
| 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. |

Copilot uses AI. Check for mistakes.
Comment thread docs/install_guide/integrate/n8n.mdx Outdated
| **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. |

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

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

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').

Suggested change
| **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. |

Copilot uses AI. Check for mistakes.

@SarahScargall SarahScargall left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

@SarahScargall SarahScargall left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@SarahScargall

Copy link
Copy Markdown
Contributor

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,
Sarah

@sscargal sscargal added this to the v0.3.9 milestone May 12, 2026

@sscargal sscargal left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@sscargal

Copy link
Copy Markdown
Contributor

@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>
@sscargal
sscargal force-pushed the docs/filter-prefix-doc-audit branch from 3e95289 to a103c12 Compare May 13, 2026 17:40
@sscargal
sscargal requested a review from Copilot May 13, 2026 18:49

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.

@sscargal
sscargal merged commit 78aaf0e into MemMachine:main May 13, 2026
65 of 66 checks passed
sscargal added a commit to haosenwang1018/MemMachine that referenced this pull request May 13, 2026
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>
malatewang added a commit that referenced this pull request May 13, 2026
…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>
sscargal added a commit that referenced this pull request May 15, 2026
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

4 participants