feat: guide adaptive search limits and raise default to 15 - #80
Merged
Conversation
Both search surfaces already expose `limit`; this makes it useful adaptively rather than a fixed compromise. - mcp_server.py: enrich the search_memories docstring (the model reads it as the tool description) to size `limit` to query breadth — ~5 for a narrow lookup, ~20-25 for a broad/exploratory one — noting atomic-fact memories make a larger limit cheap and under-fetching a broad query costs more than over-fetching a narrow one. - Raise the default search limit 10 -> 15 on both the MCP tool and REST SearchRequest, reflecting that asymmetry. (List default stays 50.) - USER_GUIDE: update the search reference to default 15 + sizing guidance, and add an adaptive-limit line to the CLAUDE.md and AGENTS.md prompt blocks. - Tests: assert the new default (15) on both MCP and REST search. No server-side auto-sizing: score-threshold/elbow approaches are brittle to calibrate (and now embed-model-dependent with Ollama), and the calling agent already holds the query-breadth intent the server would have to guess. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XQXUARh5h5hRFg67toenEX
There was a problem hiding this comment.
Pull request overview
This PR updates the default search result limit from 10 → 15 for both the REST and MCP search surfaces, and adds documentation guidance encouraging callers (especially agent/tool callers) to size limit adaptively based on query breadth.
Changes:
- Raised default search
limitto 15 in REST (SearchRequest) and MCP (search_memories) and updated tests to assert the new defaults. - Expanded end-user/operator docs with adaptive-sizing guidance and updated endpoint reference text to reflect the new default.
- Added explicit guidance in the MCP tool docstring so model/tool callers pick smaller limits for narrow lookups and larger limits for broad/exploratory queries.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| app/mcp_server.py | Raises MCP search_memories default limit to 15 and enriches the tool description with adaptive sizing guidance. |
| app/rest.py | Raises REST SearchRequest.limit default to 15 and documents rationale inline. |
| docs/USER_GUIDE.md | Updates REST search endpoint reference to default 15 and adds adaptive sizing guidance text. |
| tests/test_mcp.py | Updates assertions to expect top_k == 15 and adds a new default-limit test. |
| tests/test_rest.py | Adds a new test asserting the REST default top_k == 15 when limit is omitted. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- mcp_server.py: enforce 1-100 on search_memories' limit, mirroring list_memories and the REST pydantic bound. The docstring claimed the range but nothing checked it, so a 0 or huge limit reached the backend. Adds a test. - USER_GUIDE: reword "documented to size it this way automatically" — the server does not auto-resize limit; the tool description guides the agent. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XQXUARh5h5hRFg67toenEX
The PRD is the source of truth for design; update its SearchRequest and search_memories snippets to the new default so the spec doesn't drift from the code (PR review follow-up). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XQXUARh5h5hRFg67toenEX
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (2)
docs/PRD.md:407
- The PRD’s example
search_memoriestool still shows anagent_idparameter and passeslimitviakwargs, but the current MCP implementation searches the shared store across all agents and callsmemory.search(..., filters={...}, top_k=limit). This snippet is now misleading (especially since MCP reads should not be agent-scoped).
def search_memories(
query: str,
agent_id: str | None = None,
limit: int = 15,
) -> dict:
"""Search long-term memory by semantic similarity."""
kwargs = {"user_id": default_user, "limit": limit}
if agent_id:
kwargs["agent_id"] = agent_id
return memory.search(query=query, **kwargs)
tests/test_mcp.py:107
- This test comment says the default is sized for broad queries, but the tool docstring guidance says broad/exploratory queries should typically raise
limitabove the default. Align the comment with the documented behavior to avoid confusing future readers.
# Default sized for broad queries; the model narrows it explicitly when
# doing a specific lookup (see the tool docstring).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Makes the number of memories a search returns adapt to the breadth of the query — small for a narrow lookup, larger for a broad/exploratory one — without adding brittle server-side machinery.
Both surfaces already expose
limit(MCPsearch_memories(limit=…), RESTPOST /api/v1/memories/search), so the capability existed; what was missing was guidance to use it adaptively and a default that wasn't a fixed 10 compromise.Changes
app/mcp_server.py— enrich thesearch_memoriesdocstring (the model reads it as the tool description) to sizelimitto query breadth: ~5 for a narrow lookup about one specific thing, ~20–25 for a broad question (a person's overall preferences, everything about a project). Notes that atomic-fact memories make a larger limit cheap and that under-fetching a broad query costs more than over-fetching a narrow one.SearchRequest, reflecting that asymmetry. (Thelistdefault stays 50.)docs/USER_GUIDE.md— update the search-endpoint reference to default 15 + sizing guidance, and add an adaptive-limit line to both theCLAUDE.mdandAGENTS.mdprompt blocks under "Prompting agents to use memory."Why not server-side auto-sizing
Considered and deliberately skipped. Score-threshold/elbow ("dynamic-k") approaches depend on cosine scores being calibrated across queries — they aren't, and with the just-merged Ollama support they're now embed-model-dependent (
text-embedding-3-smallvsnomic-embed-textdon't share a scale), so a fixed threshold would misbehave silently. A query-breadth classifier would spend an extra LLM call to guess intent the calling agent already holds. Putting the choice where the context lives (the caller) is both cheaper and more correct.Verification
ruffclean; full suite 245 passing (pytest -q), including the two new default-limit assertions. Default behavior for callers that pass an explicitlimitis unchanged.🤖 Generated with Claude Code
Generated by Claude Code