Skip to content

Commit 8fb2ca5

Browse files
bloveclaude
andauthored
fix(examples-chat-python): research tool passes subagent_type so SubagentTracker registers (#225)
The @ngaf/langgraph SubagentTracker silently skips tool calls whose args do not include a valid `subagent_type` string (matching the canonical LangGraph `task` tool shape). Without it, `agent.subagents()` stays empty and `<chat-subagents>` never surfaces a card during the research run. Adds `subagent_type: str = "research"` to the tool signature (consumed only as a UI hint — the body deletes it before invoking the subgraph) and instructs the parent in SYSTEM_PROMPT to pass it. The result: the SubagentTracker registers the subagent on tool-call dispatch, the panel mounts during the active window, and (per the existing primitive's active-only filter) the card hides cleanly once the subagent completes. Verified live: agent.subagents() reports size=1 with the research tool call id and status transitions through to 'complete' as the subagent returns. End-state panel wrapper still renders because the tracker map retains the entry; the inner @for filters complete subagents out. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 1e91bf5 commit 8fb2ca5

1 file changed

Lines changed: 15 additions & 5 deletions

File tree

examples/chat/python/src/graph.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,11 @@
5858
"When the user asks for in-depth research on a focused topic (history, "
5959
"motivation, comparison, deep-dive on something they want explained), "
6060
"call the `research` tool to dispatch a subagent that focuses on that "
61-
"topic. Pass the topic verbatim or as a concise rephrasing. Use the "
62-
"subagent's returned summary to compose your final answer. Do not "
63-
"call `research` for trivial chit-chat or simple lookups — those are "
64-
"handled by `search_documents`."
61+
"topic. Pass the topic verbatim or as a concise rephrasing, and pass "
62+
"`subagent_type=\"research\"` so the UI surfaces a subagent card while "
63+
"the child runs. Use the subagent's returned summary to compose your "
64+
"final answer. Do not call `research` for trivial chit-chat or simple "
65+
"lookups — those are handled by `search_documents`."
6566
)
6667

6768
# Reasoning-capable model prefixes. We only attach the ``reasoning``
@@ -178,11 +179,20 @@ async def research_node(state: ResearchState) -> dict:
178179

179180

180181
@tool
181-
async def research(topic: str) -> str:
182+
async def research(topic: str, subagent_type: str = "research") -> str:
182183
"""Dispatch a research subagent to gather facts on a focused topic.
183184
The subagent returns a concise summary; pass that summary back to
184185
the user, citing it with the inline citation syntax if appropriate.
186+
187+
`subagent_type` is a free-form label the parent uses to identify the
188+
subagent in the UI (the @ngaf/langgraph SubagentTracker keys on it
189+
to populate `agent.subagents()` for the chat-subagents primitive).
190+
Always pass a stable identifier like "research".
185191
"""
192+
# subagent_type is intentionally accepted but unused server-side —
193+
# it travels in the tool call args so the SubagentTracker can
194+
# register the dispatch and surface a card while the child graph runs.
195+
del subagent_type
186196
result = await research_subgraph.ainvoke({"topic": topic, "messages": []})
187197
msgs = result.get("messages") if isinstance(result, dict) else None
188198
if not msgs:

0 commit comments

Comments
 (0)