Repository navigation
KBLibrarianAgent.search_knowledge silently returns no results (Enhanced-mode dict vs expected list) #13025
Description
Activity
- added a commit that references this issue
on Jul 30, 2026 github-actions commented
on Jul 30, 2026 on Jul 30, 2026 – with GitHub ActionsContributorMore actionsFixed by PR #13038, merged to
Dev_new_guias129617080(batched with #13024, #13025, #13026, #13027 — all four fully delivered).All four premises confirmed against the canonical signature read directly (
knowledge/search.py:194,SearchMixin.search— no**kwargs, non_results, nosearch_mode), rather than inferred:- Stale n_results/search_mode kwargs against canonical KnowledgeBase.search() silently break several call sites #13024 — 4 call sites.
api/chat_knowledge.py:456is live (wired toPOST /search);services/grounded_agent.py:420-423is live viaapi/knowledge_grounding.py(Tier-4 claim classifier);agents/kb_librarian/librarian.py:236,358andagents/knowledge_retrieval_agent.py:241,275are dead — zero callers anywhere, not even tests. - KBLibrarianAgent.search_knowledge silently returns no results (Enhanced-mode dict vs expected list) #13025 —
agents/kb_librarian_agent.py:132:limit=limitselects the Enhanced dict-returning path while the caller iterates it as aList, raisingAttributeErroron every non-empty result. Live viaapi/kb_librarian.py:92,api/workflow.py:61,agent_orchestration/agent_execution.py:292,311. - api/knowledge_mcp.py get_knowledge_base() always raises TypeError (config_manager kwarg not accepted) #13026 —
api/knowledge_mcp.py:62:KnowledgeBase.__init__(knowledge/_composed.py:54) takes zero parameters, soconfig_manager=raisedTypeErroron every call — masked by a broadexceptin all 10 MCP handlers. - tools/tool_registry.py singleton never receives knowledge_base — search_knowledge_base/get_fact tools always report KB unavailable #13027 —
tools/tool_registry.py:874:lazy_singleton(ToolRegistry)is constructed with no args from every production caller, soknowledge_basestayedNonepermanently.
Two defects the issues did not mention, found by reading and fixed in-scope:
services/grounded_agent.pyneededtop_k=rather than merely dropping the stale kwarg —limit=routes to the Enhanced dict path this caller cannot consume, so a kwarg rename alone would have left it broken in a new way.tool_registry's dead-injection defect also affectedadd_file_to_knowledge_baseandstore_fact, not just the two methods reported. A_resolve_knowledge_base()helper (lazy fallback toknowledge_factory.get_knowledge_base_async()) now covers all four KB-touching methods.
Quarantine gap closed as a consequence. PR #13029 deliberately skipped applying
RESEARCH_QUARANTINE_FILTERto these files — layering a quarantine filter onto code that never returns content would have been meaningless. Now that these paths work, the filter is applied at every repaired general-purpose read; research-internal readers left untouched.Test technique worth noting. The 29 new regression tests use
create_autospec(KnowledgeBase, instance=True)rather than bare mocks. A bareMockaccepts any keyword argument silently — which is precisely hown_results=andconfig_manager=survived in this codebase. The autospec reproduces the real productionTypeError/AttributeError, so these tests would have caught the original defects. Each asserts real content is returned, not merely that no exception was raised — the failure mode here is silent emptiness, so "it didn't throw" proves nothing.Verification:
cp-swapped baseline (nevergit stash) 141 passed / 1 pre-existing failure → 156 passed / same 1 pre-existing failure, identical failing set;tests/test_startup_imports.py350/350 unchanged;py_compile/flake8 --max-line-length=120/black --check --line-length=120clean across all 14 files.Filed separately: #13037 (
tools/tool_registry_debug_e2e_test.py:25assertsOrchestrator.tool_registry, an attribute that class has never had). #13028 was deliberately excluded from this batch — dead-code removal versus wire-in is a separate decision under the never-delete rule.- Stale n_results/search_mode kwargs against canonical KnowledgeBase.search() silently break several call sites #13024 — 4 call sites.
Context
Discovered while auditing every
kb.search()call site for #13009 (research-quarantine leak audit).autobot-backend/agents/kb_librarian_agent.py:132(KBLibrarianAgent.search_knowledge) calls:KnowledgeBase.search()(autobot-backend/knowledge/search.py:194) dispatches on parameter presence: passinglimit(notNone) setsenhanced = True(knowledge/search.py:253), which routes to the "Enhanced" search path and returns aDict[str, Any], not aList[Dict].The caller then does:
Iterating a
dictyields its keys (strings), soresult.get(...)raisesAttributeErroron every non-empty result. This is caught by the method's broadexcept Exception, logged, and[]is returned — soKBLibrarianAgent.search_knowledge()never surfaces real KB content in production, it just silently returns empty results every time it's called with a non-empty KB.Reachability
KBLibrarianAgentis live:api/kb_librarian.py:92,api/workflow.py:56/61, andagents/agent_orchestration/agent_execution.py:292/311(theAgentType.KNOWLEDGE_RETRIEVALandRAGhandlers in the multi-agent orchestration engine) all call.process_query()/.search_knowledge()on it.Suggested fix
Call
.search(query, top_k=limit)instead oflimit=limit(matching the "Basic" search-path contract this method's return-type handling expects), or explicitly handle the Enhanced dict shape if Enhanced-mode features (tags/category/min_score) are actually wanted here. Add a regression test with a non-empty mock KB asserting real content is returned, not[].Model Used
Claude Sonnet 5