From 694a0c81d1fc5425fe1ea0bea9b338c7c094f102 Mon Sep 17 00:00:00 2001 From: Hunter Lovell Date: Wed, 24 Jun 2026 14:38:51 -0700 Subject: [PATCH 1/2] docs(deepagents): rename programmatic subagents to dynamic subagents --- src/docs.json | 12 ++- ...ic-subagents.mdx => dynamic-subagents.mdx} | 34 ++++-- src/oss/deepagents/interpreters.mdx | 18 ++-- src/oss/deepagents/subagents.mdx | 102 ++++++++++++++++++ 4 files changed, 145 insertions(+), 21 deletions(-) rename src/oss/deepagents/{programmatic-subagents.mdx => dynamic-subagents.mdx} (92%) diff --git a/src/docs.json b/src/docs.json index ab5f49c309..2658b2b1c1 100644 --- a/src/docs.json +++ b/src/docs.json @@ -222,7 +222,7 @@ "root": "oss/python/deepagents/interpreters", "expanded": true, "pages": [ - "oss/python/deepagents/programmatic-subagents" + "oss/python/deepagents/dynamic-subagents" ] }, "oss/python/deepagents/profiles", @@ -692,7 +692,7 @@ "root": "oss/javascript/deepagents/interpreters", "expanded": true, "pages": [ - "oss/javascript/deepagents/programmatic-subagents" + "oss/javascript/deepagents/dynamic-subagents" ] }, "oss/javascript/deepagents/profiles", @@ -2299,6 +2299,14 @@ "source": "/oss/deepagents/harness", "destination": "/oss/deepagents/overview" }, + { + "source": "/oss/python/deepagents/programmatic-subagents", + "destination": "/oss/python/deepagents/dynamic-subagents" + }, + { + "source": "/oss/javascript/deepagents/programmatic-subagents", + "destination": "/oss/javascript/deepagents/dynamic-subagents" + }, { "source": "/oss/python/deepagents/harness", "destination": "/oss/python/deepagents/overview" diff --git a/src/oss/deepagents/programmatic-subagents.mdx b/src/oss/deepagents/dynamic-subagents.mdx similarity index 92% rename from src/oss/deepagents/programmatic-subagents.mdx rename to src/oss/deepagents/dynamic-subagents.mdx index e20d3ed7f3..ac62fcad73 100644 --- a/src/oss/deepagents/programmatic-subagents.mdx +++ b/src/oss/deepagents/dynamic-subagents.mdx @@ -1,14 +1,14 @@ --- -title: Programmatic subagents +title: Dynamic subagents description: Use interpreters to dispatch and orchestrate Deep Agents subagents from code --- -Programmatic subagents let an agent dispatch [subagents](/oss/deepagents/subagents) from interpreter code. Instead of asking the model to choose one subagent call at a time, the agent can use JavaScript loops, branches, and parallel batches to route work across configured subagents and synthesize the results. +Dynamic subagents let an agent dispatch [subagents](/oss/deepagents/subagents) from interpreter code. Instead of asking the model to choose one subagent call at a time, the agent can use JavaScript loops, branches, and parallel batches to route work across configured subagents and synthesize the results. Use this pattern when work spans many independent units, needs multiple perspectives, or benefits from recursive analysis. For general interpreter setup, see [Interpreters](/oss/deepagents/interpreters). - Programmatic subagents use the interpreter runtime, which is in [**beta**](/oss/versioning). APIs and lifecycle behavior may change between releases. + Dynamic subagents use the interpreter runtime, which is in [**beta**](/oss/versioning). APIs and lifecycle behavior may change between releases. :::python @@ -52,15 +52,29 @@ const critical = review.issues.filter((issue) => issue.severity === "high"); When you pass `responseSchema`, the resolved value is already a typed JavaScript object; only call `JSON.parse` if a subagent intentionally returned a JSON string. -## Guide orchestration +## Trigger dynamic orchestration -The interpreter middleware ships orchestration guidance in the system prompt, so the agent already knows how to fan out in bounded batches, filter between passes, and synthesize results. You do not hand-write that logic or prompt for it turn by turn. +Dynamic subagents are dispatched implicitly: the agent decides to fan work out from code based on the shape of the task, rather than being switched on by a configuration flag. The interpreter middleware's built-in system prompt already steers the agent toward this behavior for work that spans many independent units. -To shape what the agent orchestrates, work through the inputs it already responds to: +The interpreter system prompt strongly hints that a "workflow" equates to organizing work through the interpreter—dispatching subagents with `task()` and assembling the results, rather than grinding through items one model-chosen tool call at a time. So phrasing a request as a "workflow" nudges the agent toward dynamic orchestration. -- **The subagents you configure.** Their `name` and `description` define the roles available. A `reviewer` paired with a `verifier` invites a two-pass check; a single `analyzer` invites a straight fan-out. -- **The task message.** Phrasing like "I only want confirmed issues, not maybes" or "be exhaustive" nudges the agent toward verification or an open-ended sweep. -- **The system prompt.** Use `systemPrompt` (or the agent's instructions) to add standing guidance when you want a consistent strategy across runs. +:::python +```python +# Phrasing that mentions a "workflow" nudges the agent toward dynamic dispatch. +result = await agent.ainvoke({ + "messages": [{"role": "user", "content": "Run a workflow that reviews every file in src/routes/ and summarizes the top risks."}] +}) +``` +::: + +:::js +```typescript +// Phrasing that mentions a "workflow" nudges the agent toward dynamic dispatch. +const result = await agent.invoke({ + messages: [{ role: "user", content: "Run a workflow that reviews every file in src/routes/ and summarizes the top risks." }], +}); +``` +::: ## Patterns @@ -610,7 +624,7 @@ found; ::: -## Disable programmatic subagents +## Disable dynamic subagents Subagent dispatch is on by default whenever the agent has subagents. Disable it if you want subagents to be available only through the normal `task` tool path. diff --git a/src/oss/deepagents/interpreters.mdx b/src/oss/deepagents/interpreters.mdx index 0f391a5c7f..f37e64ca59 100644 --- a/src/oss/deepagents/interpreters.mdx +++ b/src/oss/deepagents/interpreters.mdx @@ -28,7 +28,7 @@ Interpreters give the agent a runtime for that work. A loop runs every iteration Call selected tools from interpreter code, including loops, retries, branching, and parallel batches. - + Dispatch subagents from code for fan-out, verification, and recursive workflows over large inputs. @@ -48,7 +48,7 @@ Use interpreters for code inside the agent loop: composing tools, preserving sta | One or two simple external calls | Normal tool calling | | A small program that loops, branches, retries, or aggregates results | Interpreter | | Many selected tool calls that should run from code | Interpreter with [programmatic tool calling (PTC)](#programmatic-tool-calling-ptc) | -| Many independent units of work, multiple perspectives, or recursive analysis over large inputs | Interpreter with [programmatic subagents](/oss/deepagents/programmatic-subagents) | +| Many independent units of work, multiple perspectives, or recursive analysis over large inputs | Interpreter with [dynamic subagents](/oss/deepagents/dynamic-subagents) | | Shell commands, package installs, tests, or full OS filesystem access | [Sandboxes](/oss/deepagents/sandboxes) | ## Quickstart @@ -134,7 +134,7 @@ Code runs against [**QuickJS**](https://github.com/quickjs-ng/quickjs), a lightw Two explicit bridges extend that reach: - **Tools**, through [programmatic tool calling (PTC)](#programmatic-tool-calling-ptc). Expose an allowlist of tools as async functions under the `tools` namespace. These can be the agent's own tools or standalone tools you define and pass in. -- **Subagents**, through [programmatic subagents](/oss/deepagents/programmatic-subagents). Dispatch configured subagents from code and orchestrate them in plain JavaScript. +- **Subagents**, through [dynamic subagents](/oss/deepagents/dynamic-subagents). Dispatch configured subagents from code and orchestrate them in plain JavaScript. Programmatic tool calling is off until you [enable it](#enable-ptc). Subagent dispatch is on by default whenever the agent has subagents, and you can turn it off. Nothing else crosses the QuickJS boundary unless you expose it. @@ -205,17 +205,17 @@ results.join("\n\n"); ::: -## Programmatic subagents +## Dynamic subagents -Programmatic subagents let the interpreter dispatch configured [subagents](/oss/deepagents/subagents) from code using the built-in `task()` global. A task that spans many independent units, such as reviewing every file in a directory or triaging a batch of tickets, becomes a loop that fans work out and synthesizes the results. +Dynamic subagents let the interpreter dispatch configured [subagents](/oss/deepagents/subagents) from code using the built-in `task()` global. A task that spans many independent units, such as reviewing every file in a directory or triaging a batch of tickets, becomes a loop that fans work out and synthesizes the results. -Use programmatic subagents for: +Use dynamic subagents for: - **Fan-out and synthesize**: Run the same kind of work across many items in parallel, then combine the results. - **Verification**: Send findings to independent verifier subagents and keep only confirmed results. - **Recursive workflows**: Keep a working set in interpreter variables, select slices, call subagents, and refine the result. -For configuration, examples, orchestration patterns, and safety notes, see [Programmatic subagents](/oss/deepagents/programmatic-subagents). +For configuration, examples, orchestration patterns, and safety notes, see [Dynamic subagents](/oss/deepagents/dynamic-subagents). :::python ## Persistence @@ -314,7 +314,7 @@ Every tool you expose through PTC is an outside capability that interpreter code | `tool_name` | `"eval"` | Name of the interpreter tool exposed to the model. | | `max_result_chars` | `4000` | Maximum characters returned from result and stdout blocks. | | `capture_console` | `True` | Whether `console.log`, `console.warn`, and `console.error` output is captured. | -| `subagents` | `True` | Expose the built-in `task()` global for [programmatic subagents](/oss/deepagents/programmatic-subagents). Set to `False` to require subagent dispatch through the normal `task` tool path. | +| `subagents` | `True` | Expose the built-in `task()` global for [dynamic subagents](/oss/deepagents/dynamic-subagents). Set to `False` to require subagent dispatch through the normal `task` tool path. | | `ptc` | `None` | PTC allowlist: list of tool names or `BaseTool` instances. | | `snapshot_between_turns` | `True` | Whether interpreter state snapshots persist across agent turns. | | `max_snapshot_bytes` | `None` | Maximum serialized snapshot size. Defaults to `memory_limit`. | @@ -334,5 +334,5 @@ Every tool you expose through PTC is an outside capability that interpreter code | `maxResultChars` | `4000` | Maximum characters retained from console output, result, and error strings. | | `toolName` | `"eval"` | Name of the interpreter tool exposed to the model. | | `captureConsole` | `true` | Whether `console.log`, `console.warn`, and `console.error` output is captured. | -| `subagents` | `true` | Expose the built-in `task()` global for [programmatic subagents](/oss/deepagents/programmatic-subagents). Set to `false` to require subagent dispatch through the normal `task` tool path. | +| `subagents` | `true` | Expose the built-in `task()` global for [dynamic subagents](/oss/deepagents/dynamic-subagents). Set to `false` to require subagent dispatch through the normal `task` tool path. | ::: diff --git a/src/oss/deepagents/subagents.mdx b/src/oss/deepagents/subagents.mdx index 940c3a3aba..02ce02088f 100644 --- a/src/oss/deepagents/subagents.mdx +++ b/src/oss/deepagents/subagents.mdx @@ -207,6 +207,108 @@ const agent = createDeepAgent({ ``` ::: +## Dynamic subagents + +By default, the main agent delegates to subagents one call at a time through the `task` tool. With an [interpreter](/oss/deepagents/interpreters) attached, the agent can instead dispatch subagents **from code**—using loops, branches, and parallel batches to fan work out across many items and synthesize the results. This is called [dynamic subagents](/oss/deepagents/dynamic-subagents). + +Reach for dynamic subagents when work spans many independent units (reviewing every file in a directory, triaging a batch of tickets), needs multiple perspectives, or benefits from recursive analysis. + + + Dynamic subagents use the interpreter runtime, which is in [**beta**](/oss/versioning). APIs and lifecycle behavior may change between releases. + + +### Enable dynamic subagents + +Dynamic subagents become available as soon as the agent has both subagents and the interpreter middleware. Install the QuickJS interpreter package, then add `CodeInterpreterMiddleware` to your agent. + +:::python + +```bash pip +pip install -U "deepagents[quickjs]" +``` + +```bash uv +uv add "deepagents[quickjs]" +``` + + +```python +from deepagents import create_deep_agent +from langchain_quickjs import CodeInterpreterMiddleware + +agent = create_deep_agent( + model="openai:gpt-5.5", + subagents=[{ + "name": "reviewer", + "description": "Reviews code for security issues, citing lines and severity", + "system_prompt": "You are a security-focused code reviewer. Report issues with line numbers and severity.", + }], + middleware=[CodeInterpreterMiddleware()], +) +``` + + + Dynamic subagent dispatch is on by default whenever the agent has subagents and the interpreter middleware. Pass `CodeInterpreterMiddleware(subagents=False)` to require dispatch through the normal `task` tool path. Interpreters require `langchain-quickjs>=0.1.0` and Python `>=3.11`. + +::: + +:::js + +```bash npm +npm install deepagents @langchain/quickjs +``` + +```bash pnpm +pnpm add deepagents @langchain/quickjs +``` + +```bash yarn +yarn add deepagents @langchain/quickjs +``` + + +```typescript +import { createDeepAgent } from "deepagents"; +import { createCodeInterpreterMiddleware } from "@langchain/quickjs"; + +const agent = createDeepAgent({ + model: "openai:gpt-5.5", + subagents: [{ + name: "reviewer", + description: "Reviews code for security issues, citing lines and severity", + systemPrompt: "You are a security-focused code reviewer. Report issues with line numbers and severity.", + }], + middleware: [createCodeInterpreterMiddleware()], +}); +``` + + + Dynamic subagent dispatch is on by default whenever the agent has subagents and the interpreter middleware. Pass `createCodeInterpreterMiddleware({ subagents: false })` to require dispatch through the normal `task` tool path. + +::: + +### Trigger dynamic orchestration + +Dynamic dispatch is implicit: the agent decides to fan work out from code based on the shape of the task, not a per-call flag. The built-in interpreter system prompt strongly hints that a "workflow" means organizing work through the interpreter—dispatching subagents with `task()`—so phrasing a request as a "workflow" nudges the agent toward dynamic orchestration. + +:::python +```python +result = await agent.ainvoke({ + "messages": [{"role": "user", "content": "Run a workflow that reviews every file in src/routes/ and summarizes the top risks."}] +}) +``` +::: + +:::js +```typescript +const result = await agent.invoke({ + messages: [{ role: "user", content: "Run a workflow that reviews every file in src/routes/ and summarizes the top risks." }], +}); +``` +::: + +For configuration, advanced orchestration patterns, and safety notes, see [Dynamic subagents](/oss/deepagents/dynamic-subagents). + ## Streaming Deep Agents support streaming updates from both the coordinator and every delegated subagent. From 5fc5fed2d1271100a0f923607021c2a0f5516e18 Mon Sep 17 00:00:00 2001 From: Sydney Runkle Date: Sun, 28 Jun 2026 10:11:52 -0400 Subject: [PATCH 2/2] subagents update --- src/oss/deepagents/subagents.mdx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/oss/deepagents/subagents.mdx b/src/oss/deepagents/subagents.mdx index 02ce02088f..1e9ad0887a 100644 --- a/src/oss/deepagents/subagents.mdx +++ b/src/oss/deepagents/subagents.mdx @@ -209,7 +209,7 @@ const agent = createDeepAgent({ ## Dynamic subagents -By default, the main agent delegates to subagents one call at a time through the `task` tool. With an [interpreter](/oss/deepagents/interpreters) attached, the agent can instead dispatch subagents **from code**—using loops, branches, and parallel batches to fan work out across many items and synthesize the results. This is called [dynamic subagents](/oss/deepagents/dynamic-subagents). +By default, the main agent delegates to subagents through `task` tool calls (it can issue several in a single turn to run them in parallel). With an [interpreter](/oss/deepagents/interpreters) attached, the agent can instead dispatch subagents **from code**—using loops, branches, and parallel batches to fan work out across many items and synthesize the results programmatically. This is called [dynamic subagents](/oss/deepagents/dynamic-subagents). Reach for dynamic subagents when work spans many independent units (reviewing every file in a directory, triaging a batch of tickets), needs multiple perspectives, or benefits from recursive analysis. @@ -289,7 +289,11 @@ const agent = createDeepAgent({ ### Trigger dynamic orchestration -Dynamic dispatch is implicit: the agent decides to fan work out from code based on the shape of the task, not a per-call flag. The built-in interpreter system prompt strongly hints that a "workflow" means organizing work through the interpreter—dispatching subagents with `task()`—so phrasing a request as a "workflow" nudges the agent toward dynamic orchestration. +Dynamic dispatch is implicit: the agent decides to fan work out from code based on the shape of the task, not a per-call flag. + + + **The word "workflow" is a trigger.** The built-in interpreter system prompt treats a "workflow" as a signal to organize work through the interpreter—dispatching subagents with `task()` from code. Phrasing a request as a "workflow" strongly nudges the agent toward dynamic orchestration, so use it deliberately: include it when you want fan-out from code, and avoid it when you want a single, direct delegation. + :::python ```python