Skip to content

[bug] POST /api/assistants/search ignores the metadata filter #7634

Open

Description

@BlueX888

Problem summary
POST /api/assistants/search accepts a metadata filter and silently ignores it.

Affected area(s)
Backend API (gateway / endpoints / SSE)

What happened?
AssistantSearchRequest declares metadata: dict[str, Any] | None, and the LangGraph SDK documents that field as an exact-match filter for each key/value pair. The handler filters only on graph_id and name, so {"metadata": {"created_by": "user"}} returns every registered assistant, including ones whose metadata does not match — and a filter that matches nothing still returns everything.

Expected behavior
Only assistants whose metadata matches every requested key/value pair are returned (an empty list when nothing matches). At minimum, a value the endpoint does not implement should be rejected rather than silently ignored.

Steps to reproduce
Add this to backend/tests/test_assistants_compat.py, reusing its _make_app style:

def _assistant_with_meta(name: str, created_by: str) -> assistants_compat.AssistantResponse:
    return assistants_compat.AssistantResponse(
        assistant_id=name,
        graph_id="lead_agent",
        name=name,
        metadata={"created_by": created_by},
    )


def test_search_filters_by_metadata(monkeypatch: pytest.MonkeyPatch) -> None:
    app = FastAPI()
    app.include_router(assistants_compat.router)
    monkeypatch.setattr(
        assistants_compat,
        "_list_assistants",
        lambda: [
            _assistant_with_meta("lead_agent", "system"),
            _assistant_with_meta("researcher", "user"),
            _assistant_with_meta("writer", "user"),
        ],
    )
    with TestClient(app) as client:
        response = client.post(
            "/api/assistants/search", json={"metadata": {"created_by": "user"}}
        )
    assert response.status_code == 200
    assert [a["assistant_id"] for a in response.json()] == ["researcher", "writer"]

Relevant logs

$ pytest -q backend/tests/test_assistants_compat.py -k metadata
status: 200 ids: ['lead_agent', 'researcher', 'writer']   # asked metadata={"created_by": "user"}
status: 200 ids: ['lead_agent', 'researcher', 'writer']   # asked metadata={"created_by": "nobody"}
2 failed

How are you running DeerFlow?
Other (in-process FastAPI TestClient against the router, same setup as the repo's contract tests — not the full make dev stack)

Operating system
Windows

Platform details
Windows 11, Git Bash; Python 3.12

Notes
Searched existing issues for "assistants" / "metadata" first; nothing matches (#1644 is about assistant_id → agent_name mapping).

Activity

  1. Jun516 commented on Oct 28, 2026

    @Jun516
    Contributor

    I can take this as a narrowly scoped compatibility bug fix. The AssistantSearchRequest.metadata field is accepted but search_assistants() currently applies only graph_id and name, so the filter is ignored.

    Proposed fix: apply an exact key/value match for every requested metadata entry before offset/limit slicing; an absent key must not match null, and an empty metadata object should preserve unfiltered behavior. Keep existing graph/name filtering and the response shape unchanged. Add parameterized FastAPI TestClient regressions covering matching/nonmatching values, absent keys, multiple/nested keys, null, and pagination after filtering.

    I reproduced this using the two current upstream source/test files in an isolated local FastAPI test harness: 6 of the new cases failed before the change, and 16 total focused cases passed with the proposed fix (Python 3.13; no live services). This is not a full checkout or full backend-suite pass; Git clone is blocked by DNS in this environment. I'll keep the PR Draft with the AI assistance disclosure and human-review checkbox unchecked until the required review/validation conditions are met. I checked recent open/closed PR search for this exact endpoint and did not find a competing fix.

  2. BlueX888 commented on Oct 28, 2026

    @BlueX888
    ContributorAuthor

    Thanks @Jun516 — I independently ran the reproduction from this report against #7635's head (f33ce09) in a fresh worktree, and it now behaves as described here:

    • {"metadata": {"created_by": "user"}} → ["researcher", "writer"]
    • {"metadata": {"created_by": "nobody"}} → []
    • the PR's own test file passes 16/16 in that checkout.

    The "an absent key must not match null" rule you proposed matches what I saw, and it is stricter than the metadata.get(key) == value shape I had sketched locally, so I'm not carrying a competing patch. Nothing else needed from my side.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-triageAwaiting maintainer triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions