mirror of
https://github.com/langchain-ai/deepagentsjs.git
synced 2026-07-20 19:40:28 -04:00
feat: add CompiledSubAgent back
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"deepagents": minor
|
||||
---
|
||||
|
||||
Add CompiledSubAgent back to `createDeepAgent`
|
||||
+2
-1
@@ -24,6 +24,7 @@ import {
|
||||
import { StateBackend, type BackendProtocol } from "./backends/index.js";
|
||||
import { InteropZodObject } from "@langchain/core/utils/types";
|
||||
import { AnnotationRoot } from "@langchain/langgraph";
|
||||
import { CompiledSubAgent } from "./middleware/subagents.js";
|
||||
|
||||
/**
|
||||
* Configuration parameters for creating a Deep Agent
|
||||
@@ -43,7 +44,7 @@ export interface CreateDeepAgentParams<
|
||||
/** Custom middleware to apply after standard middleware */
|
||||
middleware?: AgentMiddleware[];
|
||||
/** List of subagent specifications for task delegation */
|
||||
subagents?: SubAgent[];
|
||||
subagents?: (SubAgent | CompiledSubAgent)[];
|
||||
/** Structured output response format for the agent */
|
||||
responseFormat?: any; // ResponseFormat type is complex, using any for now
|
||||
/** Optional schema for context (not persisted between invocations) */
|
||||
|
||||
@@ -15,6 +15,7 @@ export {
|
||||
type FilesystemMiddlewareOptions,
|
||||
type SubAgentMiddlewareOptions,
|
||||
type SubAgent,
|
||||
type CompiledSubAgent,
|
||||
type FileData,
|
||||
} from "./middleware/index.js";
|
||||
|
||||
|
||||
@@ -7,5 +7,6 @@ export {
|
||||
createSubAgentMiddleware,
|
||||
type SubAgentMiddlewareOptions,
|
||||
type SubAgent,
|
||||
type CompiledSubAgent,
|
||||
} from "./subagents.js";
|
||||
export { createPatchToolCallsMiddleware } from "./patch_tool_calls.js";
|
||||
|
||||
+31
-14
@@ -170,6 +170,18 @@ When NOT to use the task tool:
|
||||
- Remember to use the \`task\` tool to silo independent tasks within a multi-part objective.
|
||||
- You should use the \`task\` tool whenever you have a complex task that will take multiple steps, and is independent from other tasks that the agent needs to complete. These agents are highly competent and efficient.`;
|
||||
|
||||
/**
|
||||
* Type definitions for pre-compiled agents.
|
||||
*/
|
||||
export interface CompiledSubAgent {
|
||||
/** The name of the agent */
|
||||
name: string;
|
||||
/** The description of the agent */
|
||||
description: string;
|
||||
/** The agent instance */
|
||||
runnable: ReactAgent<any, any, any, any> | Runnable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Type definitions for subagents
|
||||
*/
|
||||
@@ -238,7 +250,7 @@ function getSubagents(options: {
|
||||
defaultTools: StructuredTool[];
|
||||
defaultMiddleware: AgentMiddleware[] | null;
|
||||
defaultInterruptOn: Record<string, boolean | InterruptOnConfig> | null;
|
||||
subagents: Array<SubAgent>;
|
||||
subagents: (SubAgent | CompiledSubAgent)[];
|
||||
generalPurposeAgent: boolean;
|
||||
}): {
|
||||
agents: Record<string, ReactAgent<any, any, any, any> | Runnable>;
|
||||
@@ -285,19 +297,24 @@ function getSubagents(options: {
|
||||
`- ${agentParams.name}: ${agentParams.description}`,
|
||||
);
|
||||
|
||||
const middleware = agentParams.middleware
|
||||
? [...defaultSubagentMiddleware, ...agentParams.middleware]
|
||||
: [...defaultSubagentMiddleware];
|
||||
if ("runnable" in agentParams) {
|
||||
agents[agentParams.name] = agentParams.runnable;
|
||||
} else {
|
||||
const middleware = agentParams.middleware
|
||||
? [...defaultSubagentMiddleware, ...agentParams.middleware]
|
||||
: [...defaultSubagentMiddleware];
|
||||
|
||||
const interruptOn = agentParams.interruptOn || defaultInterruptOn;
|
||||
if (interruptOn) middleware.push(humanInTheLoopMiddleware({ interruptOn }));
|
||||
const interruptOn = agentParams.interruptOn || defaultInterruptOn;
|
||||
if (interruptOn)
|
||||
middleware.push(humanInTheLoopMiddleware({ interruptOn }));
|
||||
|
||||
agents[agentParams.name] = createAgent({
|
||||
model: agentParams.model ?? defaultModel,
|
||||
systemPrompt: agentParams.systemPrompt,
|
||||
tools: agentParams.tools ?? defaultTools,
|
||||
middleware,
|
||||
});
|
||||
agents[agentParams.name] = createAgent({
|
||||
model: agentParams.model ?? defaultModel,
|
||||
systemPrompt: agentParams.systemPrompt,
|
||||
tools: agentParams.tools ?? defaultTools,
|
||||
middleware,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return { agents, descriptions: subagentDescriptions };
|
||||
@@ -311,7 +328,7 @@ function createTaskTool(options: {
|
||||
defaultTools: StructuredTool[];
|
||||
defaultMiddleware: AgentMiddleware[] | null;
|
||||
defaultInterruptOn: Record<string, boolean | InterruptOnConfig> | null;
|
||||
subagents: Array<SubAgent>;
|
||||
subagents: (SubAgent | CompiledSubAgent)[];
|
||||
generalPurposeAgent: boolean;
|
||||
taskDescription: string | null;
|
||||
}) {
|
||||
@@ -406,7 +423,7 @@ export interface SubAgentMiddlewareOptions {
|
||||
/** The tool configs for the default general-purpose subagent */
|
||||
defaultInterruptOn?: Record<string, boolean | InterruptOnConfig> | null;
|
||||
/** A list of additional subagents to provide to the agent */
|
||||
subagents?: Array<SubAgent>;
|
||||
subagents?: (SubAgent | CompiledSubAgent)[];
|
||||
/** Full system prompt override */
|
||||
systemPrompt?: string | null;
|
||||
/** Whether to include the general-purpose agent */
|
||||
|
||||
@@ -258,6 +258,45 @@ describe("Subagent Middleware Integration Tests", () => {
|
||||
},
|
||||
);
|
||||
|
||||
it.concurrent(
|
||||
"should use pre-compiled subagent",
|
||||
{ timeout: 60000 },
|
||||
async () => {
|
||||
const customSubagent = createAgent({
|
||||
model: SAMPLE_MODEL,
|
||||
systemPrompt: "Use the get_weather tool to get the weather in a city.",
|
||||
tools: [getWeather],
|
||||
});
|
||||
|
||||
const agent = createAgent({
|
||||
model: SAMPLE_MODEL,
|
||||
systemPrompt: "Use the task tool to call a subagent.",
|
||||
middleware: [
|
||||
createSubAgentMiddleware({
|
||||
defaultModel: SAMPLE_MODEL,
|
||||
defaultTools: [],
|
||||
subagents: [
|
||||
{
|
||||
name: "weather",
|
||||
description: "This subagent can get weather in cities.",
|
||||
runnable: customSubagent,
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
const expectedToolCalls = [
|
||||
{ name: "task", args: { subagent_type: "weather" } },
|
||||
{ name: "get_weather" },
|
||||
];
|
||||
|
||||
await assertExpectedSubgraphActions(expectedToolCalls, agent, {
|
||||
messages: [new HumanMessage("What is the weather in Tokyo?")],
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
it.concurrent(
|
||||
"should handle multiple subagents without middleware accumulation",
|
||||
{ timeout: 120000 },
|
||||
|
||||
Reference in New Issue
Block a user