Skip to content

feat: guide adaptive search limits and raise default to 15 - #80

Merged
imonroe merged 3 commits into
mainfrom
claude/adaptive-search-limit
Jul 29, 2026
Merged

feat: guide adaptive search limits and raise default to 15#80
imonroe merged 3 commits into
mainfrom
claude/adaptive-search-limit

Conversation

@imonroe

@imonroe imonroe commented Jul 29, 2026

Copy link
Copy Markdown
Owner

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 (MCP search_memories(limit=…), REST POST /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 the search_memories docstring (the model reads it as the tool description) to size limit to 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.
  • Default limit 10 → 15 on both the MCP tool and the REST SearchRequest, reflecting that asymmetry. (The list default stays 50.)
  • docs/USER_GUIDE.md — update the search-endpoint reference to default 15 + sizing guidance, and add an adaptive-limit line to both the CLAUDE.md and AGENTS.md prompt blocks under "Prompting agents to use memory."
  • Tests — assert the new default (15) on both MCP and REST search; updated the one existing test that pinned the old default.

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-small vs nomic-embed-text don'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

ruff clean; full suite 245 passing (pytest -q), including the two new default-limit assertions. Default behavior for callers that pass an explicit limit is unchanged.

🤖 Generated with Claude Code


Generated by Claude Code

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

Copilot AI left a comment

Copy link
Copy Markdown

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 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 limit to 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.

Comment thread docs/USER_GUIDE.md
Comment thread docs/USER_GUIDE.md Outdated
Comment thread app/mcp_server.py
claude added 2 commits July 29, 2026 16:47
- 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

Copilot AI left a comment

Copy link
Copy Markdown

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 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_memories tool still shows an agent_id parameter and passes limit via kwargs, but the current MCP implementation searches the shared store across all agents and calls memory.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 limit above 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).

@imonroe
imonroe merged commit 5744ecd into main Jul 29, 2026
2 checks passed
@imonroe
imonroe deleted the claude/adaptive-search-limit branch July 29, 2026 19:07
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.

3 participants