feat(deepagents): async subagent execution by background streaming#235
Open
Hunter Lovell (hntrl) wants to merge 6 commits intomainfrom
Open
feat(deepagents): async subagent execution by background streaming#235Hunter Lovell (hntrl) wants to merge 6 commits intomainfrom
Hunter Lovell (hntrl) wants to merge 6 commits intomainfrom
Conversation
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Instead of blocking on each subagent until it finishes (
await subagent.invoke()), the supervisor now fires off subagents as background streams and continues working while they run. Results are delivered back to the supervisor as[Task Result]messages when each subagent completes.This branch includes two things:
createSubAgentMiddlewarefrom synchronous invoke to async streamingexamples/async-subagents/) — a React + Hono app with a real supervisor agent dispatching researcher and analyst subagents1. Supervisor calls the
tasktoolThe model emits a tool call like
task({ subagent_type: "researcher", description: "Research LeBron James" }). The task tool:subagent.stream(input, config)to get anIterableReadableStreamSubagentExecution— a class that eagerly consumes the stream in the backgroundCommandthat puts the execution into graph state under atasksmap and sends back aToolMessage("Task initiated")The
SubagentExecutionconstructor starts consuming the stream immediately. The stream drains in the background via afor awaitloop inside the class.2. The supervisor continues working
Because the tool returned instantly, the model gets back "Task initiated" and can decide what to do next. It might launch more tasks, call other tools, or start composing a response.
3.
afterAgent— waiting for resultsWhen the supervisor's agent loop would normally end (the model stops calling tools), the
afterAgenthook fires. It checks: are there still pending tasks?This is the critical piece:
Promise.raceresolves as soon as any task finishes (or instantly if one already finished). The hook collects the result, removes the completed task from state, injects a[Task Result]message, and usesjumpTo: "model"to loop the supervisor back for another turn.Remaining tasks keep draining in the background. On the next iteration,
beforeModelandafterAgentpick up any additional completions.4.
beforeModel— catching results between turnsThe
beforeModelhook runs before every model call and sweeps for tasks that completed while the model was generating its previous response:This ensures the model always sees the latest results when it starts thinking.
5. Loop terminates naturally
The agent loop ends when the model stops calling tools and there are no pending tasks. The
afterAgenthook returnsundefined(nojumpTo), so the graph completes.The demo example -
examples/async-subagents/A complete application you can run and interact with:
agent.ts— defines a supervisor withresearcherandanalystsubagents usingcreateDeepAgentserver.ts— a Hono HTTP server that exposesPOST /api/streamusing the LangGraph SSE streaming protocolvite.config.ts— a Vite dev server with a custom plugin that proxies/api/*requests to the Hono handler in-processsrc/App.tsx— a React frontend using@langchain/langgraph-sdk/react'suseStreamhook withfilterSubagentMessagesand a sidebar showing live subagent status cardsThe frontend shows messages in a chat interface, and when the supervisor dispatches subagents, they appear in a sidebar with live status badges (pending → running → complete). When results come back, the supervisor synthesizes them into a final response.