Open
Conversation
|
🤖 Devin AI is starting automated code review... |
1 similar comment
|
🤖 Devin AI is starting automated code review... |
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.
This PR introduces a declarative mechanism for spawning large batches of subagent tasks (10-1000+) through shell scripts, bypassing the need for models to make repeated individual tool calls. Instead of relying on the LLM to call
taskN times (which is unreliable at scale), agents can now use a simplespawn_subagentbash command within theexecutetool to declare tasks that get executed in parallel with configurable concurrency.The Problem
When you have a CSV with 1000 tasks that need to be delegated to subagents, the current approach of having the model call the
tasktool 1000 times is:ToolMessageresponses would blow up the context windowDeclarative Batch Spawning
This PR introduces a new architecture where:
/batch_results/<timestamp>/Architecture Overview
sequenceDiagram participant Model as LLM participant Execute as execute tool participant State as Agent State participant WrapModel as wrapModelCall participant BatchTask as batch_task tool participant Subagents as Subagent Pool participant FS as Filesystem Model->>Execute: execute shell script with spawn_subagent Note right of Execute: Script outputs SUBAGENT_TASK markers Execute->>Execute: Parse markers from stdout Execute->>State: Set pendingBatchTask via Command Execute-->>Model: ToolMessage with exit code rect rgb(240, 248, 255) Note over Model,WrapModel: Interception Phase WrapModel->>State: Check pendingBatchTask State-->>WrapModel: tasks array found WrapModel-->>Model: Inject synthetic batch_task call end Model->>BatchTask: batch_task with tasks array rect rgb(240, 255, 240) Note over BatchTask,Subagents: Parallel Execution loop Concurrent workers (default 10) BatchTask->>Subagents: Execute task Subagents-->>BatchTask: Result end end BatchTask->>FS: Write summary.json, results.jsonl BatchTask->>State: Clear pendingBatchTask BatchTask-->>Model: Summary message Note right of Model: Model sees concise summaryComponent Interaction
flowchart TB subgraph FilesystemMiddleware ET[execute tool] MP[Marker Parser] end subgraph SubAgentMiddleware WMC[wrapModelCall hook] BT[batch_task tool] TT[task tool] end subgraph SharedState PBT[(pendingBatchTask)] end subgraph Execution WP[Worker Pool] S1[Subagent 1] S2[Subagent 2] SN[Subagent N] end ET -->|detects markers| MP MP -->|sets| PBT WMC -->|reads| PBT WMC -->|injects call to| BT BT -->|spawns| WP WP --> S1 WP --> S2 WP --> SN BT -->|clears| PBT TT -.->|single task| S1Key Design Decisions
1. Why
spawn_subagentInstead of a New Tool?We inject a bash function rather than creating a separate
batch_task_from_filetool because:jq,awk,cut, etc.)2. Why Synthetic Tool Call Injection?
The
wrapModelCallhook intercepts the model call and returns a syntheticAIMessagewith abatch_tasktool call. This approach:3. Why File-Based Results?
With 1000 tasks, individual results would explode the context window. Instead:
/batch_results/<timestamp>/results.jsonlfailures.jsonlfor easy inspection4. State Schema for Cross-Middleware Communication
The
pendingBatchTaskstate channel is defined in BOTHFilesystemMiddleware(which sets it) andSubAgentMiddleware(which reads it). This enables:executetool (in FilesystemMiddleware) to declare pending taskswrapModelCall(in SubAgentMiddleware) to intercept and trigger batch executionChanges
libs/deepagents/src/middleware/subagents.ts(+479 lines)New exports for marker parsing:
SUBAGENT_MARKER_PREFIX- Constant for marker detectionSubagentTask,ParseSubagentMarkersResult- Types for parsed tasksparseSubagentMarkers(),hasSubagentMarkers()- Parser functionsPendingBatchTask,BatchTaskResult,BatchTaskSummary- Batch execution typesNew batch execution infrastructure:
SubAgentStateSchema- DeclarespendingBatchTaskstate channelexecuteSingleTask()- Runs one subagent and captures resultexecuteBatchTasks()- Worker pool with configurable concurrencywriteBatchResults()- Persists results to filesystemcreateBatchTaskTool()- The batch_task tool definitionModified
createSubAgentMiddleware:backendoption for writing resultsbatchConcurrencyoption (default: 10)wrapModelCallhook for synthetic batch_task injectionbatch_tasktool when backend is providedRefactored
createTaskTool:libs/deepagents/src/middleware/fs.ts(+196 lines)New constants:
SPAWN_SUBAGENT_FUNCTION- Bash function injected into every commandEXECUTE_TOOL_DESCRIPTION_BASE- Base description without batch docsEXECUTE_BATCH_SPAWNING_DOCS- Documentation for spawn_subagent usageEXECUTE_TOOL_DESCRIPTION- Full description with batch supportNew state schema:
PendingBatchTaskSchema- Shared schema for pendingBatchTask channelpendingBatchTasktoFilesystemStateSchemaModified
createExecuteTool:SPAWN_SUBAGENT_FUNCTIONprefix to all commandsSUBAGENT_TASK:markers in outputCommandthat setspendingBatchTaskin stateNew helper:
formatExecuteOutput()- Formats command output with exit code/truncation infolibs/deepagents/src/agent.ts(+3 lines)backend: filesystemBackendtocreateSubAgentMiddlewarelibs/deepagents/src/middleware/index.ts(+9 lines)libs/deepagents/src/middleware/subagents.int.test.ts(+211 lines)New test describe block: "Batch Spawning Integration Tests"
should parse spawn_subagent markers from execute outputshould handle malformed markers gracefullyshould invoke batch_task tool when spawn_subagent markers are detected with createDeepAgentlibs/deepagents/src/middleware/__fixtures__/subagent_tasks.csv(new)Test fixture with 1000 sample tasks for batch testing.
Usage Examples
Basic CSV Processing
The model will generate something like:
Custom Concurrency
Specifying Subagent Types
Testing