[Bug]: Tool Router: session.search silently omits no-auth toolkits when the session also enables an auth-based toolkit
SDK Language
Python SDK (composio package)
SDK Version
composio==0.15.0
Runtime Environment
Python 3.12 on MacOS
Environment
Production Deployment
Describe the Bug
Summary
In a Tool Router v3.1 session that enables both an auth-based toolkit (e.g.
gmail) and a no-auth toolkit (e.g. hackernews), session.search never
returns the no-auth toolkit's tools — it is absent from results,
tool_schemas, and toolkit_connection_statuses for every query, including
a query containing the literal tool slug. session.execute of the no-auth
toolkit's tools works fine in the same session, and a session containing
only no-auth toolkits searches correctly — so this looks like the search
scope/index build excluding no-auth toolkits whenever an auth-based toolkit
is present.
Steps to Reproduce
- Initialize a tool router session with a no-auth toolkit (e.g. hackernews) and an auth-based toolkit (e.g. gmail)
- Run a tool search for one of the tools in the no-auth toolkit
- Notice that no relevant results are returned
Minimal Reproducible Example
`composio_client` 1.43.0 (also 1.39.0), Python 3.x:
import composio_client
client = composio_client.Composio(api_key="...")
# Case 1 — no-auth toolkit alone: search works.
s1 = client.tool_router.session.create(
user_id="repro_user",
toolkits={"enable": ["hackernews"]},
)
r1 = client.tool_router.session.search(
s1.session_id,
queries=[{"use_case": "get top stories from the hacker news front page"}],
)
# r1.results[0].primary_tool_slugs -> HACKERNEWS_GET_TOP_STORIES, ... ✅
# Case 2 — same toolkit + any auth-based toolkit: hackernews vanishes.
s2 = client.tool_router.session.create(
user_id="repro_user",
toolkits={"enable": ["gmail", "hackernews"]},
)
r2 = client.tool_router.session.search(
s2.session_id,
queries=[{"use_case": "get top stories from the hacker news front page"}],
)
# r2.results[0].primary_tool_slugs -> GMAIL_FETCH_EMAILS, ... ❌
# r2.toolkit_connection_statuses -> gmail only; hackernews absent ❌
# Execute of the "invisible" toolkit works in the same session:
e2 = client.tool_router.session.execute(
s2.session_id,
tool_slug="HACKERNEWS_GET_TOP_STORIES",
arguments={},
)
# e2.data -> {"count": 500, "story_ids": [...]} ✅Error Output / Stack Trace
n/a - this is a behavioural error rather than an exception being raised.Reproducibility
- Always reproducible
- Intermittent / Sometimes
- Happened once, can’t reproduce
Additional Context or Screenshots
What we ruled out
- Explicit tool allowlist: adding
tools={"hackernews": {"enable": [<all 14 slugs>]}}tosession.createdoes not change search behaviour. - Connected-account pinning: pinning or omitting accounts for the authed toolkit makes no difference.
- Connection status: an unconnected auth-based toolkit (fresh
user_id, no connected accounts at all) is still searchable, so search is not gated on active connections — only no-auth toolkits are dropped. - Which authed toolkit: reproduced with
gmail,googlesheets,github,shopifyas the co-enabled toolkit. - Which no-auth toolkit: reproduced with
hackernewsandcomposio. - Query phrasing: a query consisting of the literal slug
HACKERNEWS_GET_TOP_STORIESstill returns only Gmail tools. - SDK version: identical on 1.39.0 and 1.43.0.
Two no-auth toolkits together (hackernews + composio, no authed toolkit)
search fine — the trigger is specifically mixing no-auth with auth-based.
Expected
No-auth toolkits enabled in a session should participate in session.search
regardless of what else the session enables — same as they do in a
single-kind session, and consistent with session.execute accepting their
tools.
Impact
Agents with both connected apps and no-auth apps cannot discover the no-auth
apps' tools via search (the LLM is told to search before executing), so those
toolkits are effectively unusable in mixed sessions without client-side
workarounds. Our current workaround injects the no-auth toolkits' tools via
experimental.custom_toolkits on every search request and rewrites the
LOCAL_* slugs back — happy to share details, but we'd love to delete it.
Aside observed while building the workaround: experimental.custom_toolkits
entries always contribute ~5 results per query even when completely
irrelevant (real toolkits are correctly flushed to zero; customs never are).
A relevance threshold for customs would make that feature much more useful.
Source: ComposioHQ/composio