@agentforge/patterns 0.6.2 → 0.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +108 -53
- package/dist/index.d.cts +72 -24
- package/dist/index.d.ts +72 -24
- package/dist/index.js +108 -53
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1642,26 +1642,35 @@ var RoutingStrategySchema = import_zod7.z.enum([
|
|
|
1642
1642
|
]);
|
|
1643
1643
|
var RoutingDecisionSchema = import_zod7.z.object({
|
|
1644
1644
|
/**
|
|
1645
|
-
* Target agent to route to
|
|
1645
|
+
* Target agent to route to (single agent routing)
|
|
1646
|
+
* @deprecated Use targetAgents for parallel routing support
|
|
1646
1647
|
*/
|
|
1647
|
-
targetAgent: import_zod7.z.string().describe("Agent to route the task to"),
|
|
1648
|
+
targetAgent: import_zod7.z.string().nullable().default(null).describe("Agent to route the task to (single routing)"),
|
|
1649
|
+
/**
|
|
1650
|
+
* Target agents to route to (parallel routing)
|
|
1651
|
+
* When multiple agents are specified, they execute in parallel
|
|
1652
|
+
*/
|
|
1653
|
+
targetAgents: import_zod7.z.array(import_zod7.z.string()).nullable().default(null).describe("Agents to route the task to (parallel routing)"),
|
|
1648
1654
|
/**
|
|
1649
1655
|
* Reasoning for the routing decision
|
|
1650
1656
|
*/
|
|
1651
|
-
reasoning: import_zod7.z.string().
|
|
1657
|
+
reasoning: import_zod7.z.string().default("").describe("Explanation for routing decision"),
|
|
1652
1658
|
/**
|
|
1653
1659
|
* Confidence in the routing decision (0-1)
|
|
1654
1660
|
*/
|
|
1655
|
-
confidence: import_zod7.z.number().min(0).max(1).
|
|
1661
|
+
confidence: import_zod7.z.number().min(0).max(1).default(0.8).describe("Confidence score"),
|
|
1656
1662
|
/**
|
|
1657
1663
|
* Strategy used for routing
|
|
1658
1664
|
*/
|
|
1659
|
-
strategy: RoutingStrategySchema.describe("Strategy used for this decision"),
|
|
1665
|
+
strategy: RoutingStrategySchema.default("llm-based").describe("Strategy used for this decision"),
|
|
1660
1666
|
/**
|
|
1661
1667
|
* Timestamp of the routing decision
|
|
1662
1668
|
*/
|
|
1663
|
-
timestamp: import_zod7.z.number().
|
|
1664
|
-
})
|
|
1669
|
+
timestamp: import_zod7.z.number().default(() => Date.now()).describe("Timestamp of the decision")
|
|
1670
|
+
}).refine(
|
|
1671
|
+
(data) => data.targetAgent || data.targetAgents && data.targetAgents.length > 0,
|
|
1672
|
+
{ message: "Either targetAgent or targetAgents must be provided" }
|
|
1673
|
+
);
|
|
1665
1674
|
var WorkerCapabilitiesSchema = import_zod7.z.object({
|
|
1666
1675
|
/**
|
|
1667
1676
|
* Skills/capabilities the agent has
|
|
@@ -1929,16 +1938,33 @@ var DEFAULT_SUPERVISOR_SYSTEM_PROMPT = `You are a supervisor agent responsible f
|
|
|
1929
1938
|
Your job is to:
|
|
1930
1939
|
1. Analyze the current task and context
|
|
1931
1940
|
2. Review available worker capabilities
|
|
1932
|
-
3. Select the most appropriate worker for the task
|
|
1941
|
+
3. Select the most appropriate worker(s) for the task
|
|
1933
1942
|
4. Provide clear reasoning for your decision
|
|
1934
1943
|
|
|
1935
|
-
|
|
1944
|
+
**IMPORTANT: You can route to MULTIPLE workers for parallel execution when:**
|
|
1945
|
+
- The task requires information from multiple domains (e.g., code + documentation)
|
|
1946
|
+
- Multiple workers have complementary expertise
|
|
1947
|
+
- Parallel execution would provide a more comprehensive answer
|
|
1948
|
+
|
|
1949
|
+
**Response Format:**
|
|
1950
|
+
|
|
1951
|
+
For SINGLE worker routing:
|
|
1936
1952
|
{
|
|
1937
1953
|
"targetAgent": "worker_id",
|
|
1938
1954
|
"reasoning": "explanation of why this worker is best suited",
|
|
1939
1955
|
"confidence": 0.0-1.0,
|
|
1940
1956
|
"strategy": "llm-based"
|
|
1941
|
-
}
|
|
1957
|
+
}
|
|
1958
|
+
|
|
1959
|
+
For PARALLEL multi-worker routing:
|
|
1960
|
+
{
|
|
1961
|
+
"targetAgents": ["worker_id_1", "worker_id_2", ...],
|
|
1962
|
+
"reasoning": "explanation of why these workers should work in parallel",
|
|
1963
|
+
"confidence": 0.0-1.0,
|
|
1964
|
+
"strategy": "llm-based"
|
|
1965
|
+
}
|
|
1966
|
+
|
|
1967
|
+
Choose parallel routing when the task benefits from multiple perspectives or data sources.`;
|
|
1942
1968
|
var llmBasedRouting = {
|
|
1943
1969
|
name: "llm-based",
|
|
1944
1970
|
async route(state, config) {
|
|
@@ -1961,7 +1987,7 @@ var llmBasedRouting = {
|
|
|
1961
1987
|
Available workers:
|
|
1962
1988
|
${workerInfo}
|
|
1963
1989
|
|
|
1964
|
-
Select the best worker for this task and explain your reasoning.`;
|
|
1990
|
+
Select the best worker(s) for this task and explain your reasoning.`;
|
|
1965
1991
|
const conversationHistory = [];
|
|
1966
1992
|
let attempt = 0;
|
|
1967
1993
|
while (attempt < maxRetries) {
|
|
@@ -1983,19 +2009,33 @@ Select the best worker for this task and explain your reasoning.`;
|
|
|
1983
2009
|
attempt++;
|
|
1984
2010
|
continue;
|
|
1985
2011
|
}
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
2012
|
+
let decision;
|
|
2013
|
+
if (response && typeof response === "object" && ("targetAgent" in response || "targetAgents" in response)) {
|
|
2014
|
+
decision = response;
|
|
2015
|
+
} else if (response.content) {
|
|
2016
|
+
if (typeof response.content === "string") {
|
|
2017
|
+
try {
|
|
2018
|
+
decision = JSON.parse(response.content);
|
|
2019
|
+
} catch (error) {
|
|
2020
|
+
throw new Error(`Failed to parse routing decision from LLM. Expected JSON but got: ${response.content}`);
|
|
2021
|
+
}
|
|
2022
|
+
} else if (typeof response.content === "object") {
|
|
2023
|
+
decision = response.content;
|
|
2024
|
+
} else {
|
|
2025
|
+
throw new Error(`Unexpected response content type: ${typeof response.content}`);
|
|
2026
|
+
}
|
|
2027
|
+
} else {
|
|
2028
|
+
throw new Error(`Unexpected response format: ${JSON.stringify(response)}`);
|
|
1998
2029
|
}
|
|
2030
|
+
const result = {
|
|
2031
|
+
targetAgent: decision.targetAgent,
|
|
2032
|
+
targetAgents: decision.targetAgents,
|
|
2033
|
+
reasoning: decision.reasoning,
|
|
2034
|
+
confidence: decision.confidence,
|
|
2035
|
+
strategy: "llm-based",
|
|
2036
|
+
timestamp: Date.now()
|
|
2037
|
+
};
|
|
2038
|
+
return result;
|
|
1999
2039
|
}
|
|
2000
2040
|
throw new Error(`Max tool retries (${maxRetries}) exceeded without routing decision`);
|
|
2001
2041
|
}
|
|
@@ -2011,6 +2051,7 @@ var roundRobinRouting = {
|
|
|
2011
2051
|
const targetAgent = availableWorkers[lastRoutingIndex];
|
|
2012
2052
|
return {
|
|
2013
2053
|
targetAgent,
|
|
2054
|
+
targetAgents: null,
|
|
2014
2055
|
reasoning: `Round-robin selection: worker ${lastRoutingIndex + 1} of ${availableWorkers.length}`,
|
|
2015
2056
|
confidence: 1,
|
|
2016
2057
|
strategy: "round-robin",
|
|
@@ -2040,6 +2081,7 @@ var skillBasedRouting = {
|
|
|
2040
2081
|
}
|
|
2041
2082
|
return {
|
|
2042
2083
|
targetAgent: firstAvailable[0],
|
|
2084
|
+
targetAgents: null,
|
|
2043
2085
|
reasoning: "No skill matches found, using first available worker",
|
|
2044
2086
|
confidence: 0.5,
|
|
2045
2087
|
strategy: "skill-based",
|
|
@@ -2050,6 +2092,7 @@ var skillBasedRouting = {
|
|
|
2050
2092
|
const confidence = Math.min(best.score / 5, 1);
|
|
2051
2093
|
return {
|
|
2052
2094
|
targetAgent: best.id,
|
|
2095
|
+
targetAgents: null,
|
|
2053
2096
|
reasoning: `Best skill match with score ${best.score} (skills: ${best.skills.join(", ")})`,
|
|
2054
2097
|
confidence,
|
|
2055
2098
|
strategy: "skill-based",
|
|
@@ -2069,6 +2112,7 @@ var loadBalancedRouting = {
|
|
|
2069
2112
|
const confidence = targetWorker.workload === 0 ? 1 : Math.max(0.5, 1 - targetWorker.workload / (avgWorkload * 2));
|
|
2070
2113
|
return {
|
|
2071
2114
|
targetAgent: targetWorker.id,
|
|
2115
|
+
targetAgents: null,
|
|
2072
2116
|
reasoning: `Lowest workload: ${targetWorker.workload} tasks (avg: ${avgWorkload.toFixed(1)})`,
|
|
2073
2117
|
confidence,
|
|
2074
2118
|
strategy: "load-balanced",
|
|
@@ -2124,10 +2168,7 @@ function wrapReActAgent(workerId, agent, verbose = false) {
|
|
|
2124
2168
|
);
|
|
2125
2169
|
if (!currentAssignment) {
|
|
2126
2170
|
logger.debug("No active assignment found", { workerId });
|
|
2127
|
-
return {
|
|
2128
|
-
currentAgent: "supervisor",
|
|
2129
|
-
status: "routing"
|
|
2130
|
-
};
|
|
2171
|
+
return {};
|
|
2131
2172
|
}
|
|
2132
2173
|
const result = await agent.invoke(
|
|
2133
2174
|
{
|
|
@@ -2159,9 +2200,7 @@ function wrapReActAgent(workerId, agent, verbose = false) {
|
|
|
2159
2200
|
}
|
|
2160
2201
|
};
|
|
2161
2202
|
return {
|
|
2162
|
-
completedTasks: [taskResult]
|
|
2163
|
-
currentAgent: "supervisor",
|
|
2164
|
-
status: "routing"
|
|
2203
|
+
completedTasks: [taskResult]
|
|
2165
2204
|
};
|
|
2166
2205
|
} catch (error) {
|
|
2167
2206
|
if (error && typeof error === "object" && "constructor" in error && error.constructor.name === "GraphInterrupt") {
|
|
@@ -2232,7 +2271,7 @@ function createSupervisorNode(config) {
|
|
|
2232
2271
|
};
|
|
2233
2272
|
}
|
|
2234
2273
|
const allCompleted = state.activeAssignments.every(
|
|
2235
|
-
(
|
|
2274
|
+
(assignment) => state.completedTasks.some((task2) => task2.assignmentId === assignment.id)
|
|
2236
2275
|
);
|
|
2237
2276
|
if (allCompleted && state.activeAssignments.length > 0) {
|
|
2238
2277
|
if (verbose) {
|
|
@@ -2245,20 +2284,29 @@ function createSupervisorNode(config) {
|
|
|
2245
2284
|
}
|
|
2246
2285
|
const routingImpl = getRoutingStrategy(strategy);
|
|
2247
2286
|
const decision = await routingImpl.route(state, config);
|
|
2287
|
+
const targetAgents = decision.targetAgents && decision.targetAgents.length > 0 ? decision.targetAgents : decision.targetAgent ? [decision.targetAgent] : [];
|
|
2288
|
+
if (targetAgents.length === 0) {
|
|
2289
|
+
throw new Error("Routing decision must specify at least one target agent");
|
|
2290
|
+
}
|
|
2248
2291
|
if (verbose) {
|
|
2249
|
-
|
|
2292
|
+
if (targetAgents.length === 1) {
|
|
2293
|
+
console.log(`[Supervisor] Routing to ${targetAgents[0]}: ${decision.reasoning}`);
|
|
2294
|
+
} else {
|
|
2295
|
+
console.log(`[Supervisor] Routing to ${targetAgents.length} agents in parallel [${targetAgents.join(", ")}]: ${decision.reasoning}`);
|
|
2296
|
+
}
|
|
2250
2297
|
}
|
|
2251
|
-
const
|
|
2298
|
+
const task = state.messages[state.messages.length - 1]?.content || state.input;
|
|
2299
|
+
const assignments = targetAgents.map((workerId) => ({
|
|
2252
2300
|
id: `task_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
|
2253
|
-
workerId
|
|
2254
|
-
task
|
|
2301
|
+
workerId,
|
|
2302
|
+
task,
|
|
2255
2303
|
priority: 5,
|
|
2256
2304
|
assignedAt: Date.now()
|
|
2257
|
-
};
|
|
2258
|
-
const
|
|
2305
|
+
}));
|
|
2306
|
+
const messages = assignments.map((assignment) => ({
|
|
2259
2307
|
id: `msg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
2260
2308
|
from: "supervisor",
|
|
2261
|
-
to: [
|
|
2309
|
+
to: [assignment.workerId],
|
|
2262
2310
|
type: "task_assignment",
|
|
2263
2311
|
content: assignment.task,
|
|
2264
2312
|
timestamp: Date.now(),
|
|
@@ -2266,13 +2314,15 @@ function createSupervisorNode(config) {
|
|
|
2266
2314
|
assignmentId: assignment.id,
|
|
2267
2315
|
priority: assignment.priority
|
|
2268
2316
|
}
|
|
2269
|
-
};
|
|
2317
|
+
}));
|
|
2270
2318
|
return {
|
|
2271
|
-
currentAgent:
|
|
2319
|
+
currentAgent: targetAgents.join(","),
|
|
2320
|
+
// Store all agents (for backward compat)
|
|
2272
2321
|
status: "executing",
|
|
2273
2322
|
routingHistory: [decision],
|
|
2274
|
-
activeAssignments:
|
|
2275
|
-
|
|
2323
|
+
activeAssignments: assignments,
|
|
2324
|
+
// Multiple assignments for parallel execution!
|
|
2325
|
+
messages,
|
|
2276
2326
|
iteration: state.iteration + 1
|
|
2277
2327
|
};
|
|
2278
2328
|
} catch (error) {
|
|
@@ -2307,10 +2357,7 @@ function createWorkerNode(config) {
|
|
|
2307
2357
|
if (verbose) {
|
|
2308
2358
|
console.log(`[Worker:${id}] No active assignment found`);
|
|
2309
2359
|
}
|
|
2310
|
-
return {
|
|
2311
|
-
currentAgent: "supervisor",
|
|
2312
|
-
status: "routing"
|
|
2313
|
-
};
|
|
2360
|
+
return {};
|
|
2314
2361
|
}
|
|
2315
2362
|
if (executeFn) {
|
|
2316
2363
|
if (verbose) {
|
|
@@ -2385,9 +2432,7 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
|
|
|
2385
2432
|
return {
|
|
2386
2433
|
completedTasks: [taskResult],
|
|
2387
2434
|
messages: [message],
|
|
2388
|
-
workers: updatedWorkers
|
|
2389
|
-
currentAgent: "supervisor",
|
|
2390
|
-
status: "routing"
|
|
2435
|
+
workers: updatedWorkers
|
|
2391
2436
|
};
|
|
2392
2437
|
} catch (error) {
|
|
2393
2438
|
if (error && typeof error === "object" && "constructor" in error && error.constructor.name === "GraphInterrupt") {
|
|
@@ -2500,10 +2545,16 @@ function createMultiAgentSystem(config) {
|
|
|
2500
2545
|
} = config;
|
|
2501
2546
|
const workflow = new import_langgraph4.StateGraph(MultiAgentState);
|
|
2502
2547
|
let supervisorConfig = { ...supervisor, maxIterations, verbose };
|
|
2503
|
-
if (supervisor.model
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2548
|
+
if (supervisor.model) {
|
|
2549
|
+
let configuredModel = supervisor.model;
|
|
2550
|
+
if (supervisor.strategy === "llm-based") {
|
|
2551
|
+
configuredModel = configuredModel.withStructuredOutput(RoutingDecisionSchema);
|
|
2552
|
+
}
|
|
2553
|
+
if (supervisor.tools && supervisor.tools.length > 0) {
|
|
2554
|
+
const langchainTools = (0, import_core9.toLangChainTools)(supervisor.tools);
|
|
2555
|
+
configuredModel = configuredModel.bindTools(langchainTools);
|
|
2556
|
+
}
|
|
2557
|
+
supervisorConfig.model = configuredModel;
|
|
2507
2558
|
}
|
|
2508
2559
|
const supervisorNode = createSupervisorNode(supervisorConfig);
|
|
2509
2560
|
workflow.addNode("supervisor", supervisorNode);
|
|
@@ -2531,6 +2582,10 @@ function createMultiAgentSystem(config) {
|
|
|
2531
2582
|
return "aggregator";
|
|
2532
2583
|
}
|
|
2533
2584
|
if (state.currentAgent && state.currentAgent !== "supervisor") {
|
|
2585
|
+
if (state.currentAgent.includes(",")) {
|
|
2586
|
+
const agents = state.currentAgent.split(",").map((a) => a.trim());
|
|
2587
|
+
return agents;
|
|
2588
|
+
}
|
|
2534
2589
|
return state.currentAgent;
|
|
2535
2590
|
}
|
|
2536
2591
|
return "supervisor";
|
package/dist/index.d.cts
CHANGED
|
@@ -1860,40 +1860,70 @@ declare const RoutingStrategySchema: z.ZodEnum<["llm-based", "rule-based", "roun
|
|
|
1860
1860
|
type RoutingStrategy = z.infer<typeof RoutingStrategySchema>;
|
|
1861
1861
|
/**
|
|
1862
1862
|
* Schema for routing decision
|
|
1863
|
+
*
|
|
1864
|
+
* Supports both single-agent and parallel multi-agent routing:
|
|
1865
|
+
* - Single: Use `targetAgent` field
|
|
1866
|
+
* - Parallel: Use `targetAgents` array field
|
|
1867
|
+
*
|
|
1868
|
+
* If both are provided, `targetAgents` takes precedence.
|
|
1869
|
+
*
|
|
1870
|
+
* Note: Uses .nullable() instead of .optional() for OpenAI structured output compatibility
|
|
1863
1871
|
*/
|
|
1864
|
-
declare const RoutingDecisionSchema: z.ZodObject<{
|
|
1872
|
+
declare const RoutingDecisionSchema: z.ZodEffects<z.ZodObject<{
|
|
1865
1873
|
/**
|
|
1866
|
-
* Target agent to route to
|
|
1874
|
+
* Target agent to route to (single agent routing)
|
|
1875
|
+
* @deprecated Use targetAgents for parallel routing support
|
|
1867
1876
|
*/
|
|
1868
|
-
targetAgent: z.ZodString
|
|
1877
|
+
targetAgent: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
1878
|
+
/**
|
|
1879
|
+
* Target agents to route to (parallel routing)
|
|
1880
|
+
* When multiple agents are specified, they execute in parallel
|
|
1881
|
+
*/
|
|
1882
|
+
targetAgents: z.ZodDefault<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
1869
1883
|
/**
|
|
1870
1884
|
* Reasoning for the routing decision
|
|
1871
1885
|
*/
|
|
1872
|
-
reasoning: z.
|
|
1886
|
+
reasoning: z.ZodDefault<z.ZodString>;
|
|
1873
1887
|
/**
|
|
1874
1888
|
* Confidence in the routing decision (0-1)
|
|
1875
1889
|
*/
|
|
1876
|
-
confidence: z.
|
|
1890
|
+
confidence: z.ZodDefault<z.ZodNumber>;
|
|
1877
1891
|
/**
|
|
1878
1892
|
* Strategy used for routing
|
|
1879
1893
|
*/
|
|
1880
|
-
strategy: z.ZodEnum<["llm-based", "rule-based", "round-robin", "skill-based", "load-balanced"]
|
|
1894
|
+
strategy: z.ZodDefault<z.ZodEnum<["llm-based", "rule-based", "round-robin", "skill-based", "load-balanced"]>>;
|
|
1881
1895
|
/**
|
|
1882
1896
|
* Timestamp of the routing decision
|
|
1883
1897
|
*/
|
|
1884
|
-
timestamp: z.
|
|
1898
|
+
timestamp: z.ZodDefault<z.ZodNumber>;
|
|
1885
1899
|
}, "strip", z.ZodTypeAny, {
|
|
1886
|
-
|
|
1900
|
+
timestamp: number;
|
|
1901
|
+
reasoning: string;
|
|
1902
|
+
confidence: number;
|
|
1903
|
+
targetAgent: string | null;
|
|
1904
|
+
targetAgents: string[] | null;
|
|
1887
1905
|
strategy: "llm-based" | "rule-based" | "round-robin" | "skill-based" | "load-balanced";
|
|
1906
|
+
}, {
|
|
1888
1907
|
timestamp?: number | undefined;
|
|
1889
1908
|
reasoning?: string | undefined;
|
|
1890
1909
|
confidence?: number | undefined;
|
|
1891
|
-
|
|
1892
|
-
|
|
1910
|
+
targetAgent?: string | null | undefined;
|
|
1911
|
+
targetAgents?: string[] | null | undefined;
|
|
1912
|
+
strategy?: "llm-based" | "rule-based" | "round-robin" | "skill-based" | "load-balanced" | undefined;
|
|
1913
|
+
}>, {
|
|
1914
|
+
timestamp: number;
|
|
1915
|
+
reasoning: string;
|
|
1916
|
+
confidence: number;
|
|
1917
|
+
targetAgent: string | null;
|
|
1918
|
+
targetAgents: string[] | null;
|
|
1893
1919
|
strategy: "llm-based" | "rule-based" | "round-robin" | "skill-based" | "load-balanced";
|
|
1920
|
+
}, {
|
|
1894
1921
|
timestamp?: number | undefined;
|
|
1895
1922
|
reasoning?: string | undefined;
|
|
1896
1923
|
confidence?: number | undefined;
|
|
1924
|
+
targetAgent?: string | null | undefined;
|
|
1925
|
+
targetAgents?: string[] | null | undefined;
|
|
1926
|
+
strategy?: "llm-based" | "rule-based" | "round-robin" | "skill-based" | "load-balanced" | undefined;
|
|
1897
1927
|
}>;
|
|
1898
1928
|
type RoutingDecision = z.infer<typeof RoutingDecisionSchema>;
|
|
1899
1929
|
/**
|
|
@@ -2166,31 +2196,49 @@ declare const MultiAgentStateConfig: {
|
|
|
2166
2196
|
* Accumulates all routing decisions
|
|
2167
2197
|
*/
|
|
2168
2198
|
routingHistory: {
|
|
2169
|
-
schema: z.ZodArray<z.ZodObject<{
|
|
2170
|
-
targetAgent: z.ZodString
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2199
|
+
schema: z.ZodArray<z.ZodEffects<z.ZodObject<{
|
|
2200
|
+
targetAgent: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
2201
|
+
targetAgents: z.ZodDefault<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
2202
|
+
reasoning: z.ZodDefault<z.ZodString>;
|
|
2203
|
+
confidence: z.ZodDefault<z.ZodNumber>;
|
|
2204
|
+
strategy: z.ZodDefault<z.ZodEnum<["llm-based", "rule-based", "round-robin", "skill-based", "load-balanced"]>>;
|
|
2205
|
+
timestamp: z.ZodDefault<z.ZodNumber>;
|
|
2175
2206
|
}, "strip", z.ZodTypeAny, {
|
|
2176
|
-
|
|
2207
|
+
timestamp: number;
|
|
2208
|
+
reasoning: string;
|
|
2209
|
+
confidence: number;
|
|
2210
|
+
targetAgent: string | null;
|
|
2211
|
+
targetAgents: string[] | null;
|
|
2177
2212
|
strategy: "llm-based" | "rule-based" | "round-robin" | "skill-based" | "load-balanced";
|
|
2213
|
+
}, {
|
|
2178
2214
|
timestamp?: number | undefined;
|
|
2179
2215
|
reasoning?: string | undefined;
|
|
2180
2216
|
confidence?: number | undefined;
|
|
2181
|
-
|
|
2182
|
-
|
|
2217
|
+
targetAgent?: string | null | undefined;
|
|
2218
|
+
targetAgents?: string[] | null | undefined;
|
|
2219
|
+
strategy?: "llm-based" | "rule-based" | "round-robin" | "skill-based" | "load-balanced" | undefined;
|
|
2220
|
+
}>, {
|
|
2221
|
+
timestamp: number;
|
|
2222
|
+
reasoning: string;
|
|
2223
|
+
confidence: number;
|
|
2224
|
+
targetAgent: string | null;
|
|
2225
|
+
targetAgents: string[] | null;
|
|
2183
2226
|
strategy: "llm-based" | "rule-based" | "round-robin" | "skill-based" | "load-balanced";
|
|
2227
|
+
}, {
|
|
2184
2228
|
timestamp?: number | undefined;
|
|
2185
2229
|
reasoning?: string | undefined;
|
|
2186
2230
|
confidence?: number | undefined;
|
|
2231
|
+
targetAgent?: string | null | undefined;
|
|
2232
|
+
targetAgents?: string[] | null | undefined;
|
|
2233
|
+
strategy?: "llm-based" | "rule-based" | "round-robin" | "skill-based" | "load-balanced" | undefined;
|
|
2187
2234
|
}>, "many">;
|
|
2188
2235
|
reducer: (left: RoutingDecision[], right: RoutingDecision[]) => {
|
|
2189
|
-
|
|
2236
|
+
timestamp: number;
|
|
2237
|
+
reasoning: string;
|
|
2238
|
+
confidence: number;
|
|
2239
|
+
targetAgent: string | null;
|
|
2240
|
+
targetAgents: string[] | null;
|
|
2190
2241
|
strategy: "llm-based" | "rule-based" | "round-robin" | "skill-based" | "load-balanced";
|
|
2191
|
-
timestamp?: number | undefined;
|
|
2192
|
-
reasoning?: string | undefined;
|
|
2193
|
-
confidence?: number | undefined;
|
|
2194
2242
|
}[];
|
|
2195
2243
|
default: () => never[];
|
|
2196
2244
|
description: string;
|
|
@@ -2606,7 +2654,7 @@ interface RoutingStrategyImpl {
|
|
|
2606
2654
|
/**
|
|
2607
2655
|
* Default system prompt for LLM-based routing
|
|
2608
2656
|
*/
|
|
2609
|
-
declare const DEFAULT_SUPERVISOR_SYSTEM_PROMPT = "You are a supervisor agent responsible for routing tasks to specialized worker agents.\n\nYour job is to:\n1. Analyze the current task and context\n2. Review available worker capabilities\n3. Select the most appropriate worker for the task\n4. Provide clear reasoning for your decision\n\
|
|
2657
|
+
declare const DEFAULT_SUPERVISOR_SYSTEM_PROMPT = "You are a supervisor agent responsible for routing tasks to specialized worker agents.\n\nYour job is to:\n1. Analyze the current task and context\n2. Review available worker capabilities\n3. Select the most appropriate worker(s) for the task\n4. Provide clear reasoning for your decision\n\n**IMPORTANT: You can route to MULTIPLE workers for parallel execution when:**\n- The task requires information from multiple domains (e.g., code + documentation)\n- Multiple workers have complementary expertise\n- Parallel execution would provide a more comprehensive answer\n\n**Response Format:**\n\nFor SINGLE worker routing:\n{\n \"targetAgent\": \"worker_id\",\n \"reasoning\": \"explanation of why this worker is best suited\",\n \"confidence\": 0.0-1.0,\n \"strategy\": \"llm-based\"\n}\n\nFor PARALLEL multi-worker routing:\n{\n \"targetAgents\": [\"worker_id_1\", \"worker_id_2\", ...],\n \"reasoning\": \"explanation of why these workers should work in parallel\",\n \"confidence\": 0.0-1.0,\n \"strategy\": \"llm-based\"\n}\n\nChoose parallel routing when the task benefits from multiple perspectives or data sources.";
|
|
2610
2658
|
/**
|
|
2611
2659
|
* LLM-based routing strategy
|
|
2612
2660
|
* Uses an LLM to intelligently route tasks based on worker capabilities
|
package/dist/index.d.ts
CHANGED
|
@@ -1860,40 +1860,70 @@ declare const RoutingStrategySchema: z.ZodEnum<["llm-based", "rule-based", "roun
|
|
|
1860
1860
|
type RoutingStrategy = z.infer<typeof RoutingStrategySchema>;
|
|
1861
1861
|
/**
|
|
1862
1862
|
* Schema for routing decision
|
|
1863
|
+
*
|
|
1864
|
+
* Supports both single-agent and parallel multi-agent routing:
|
|
1865
|
+
* - Single: Use `targetAgent` field
|
|
1866
|
+
* - Parallel: Use `targetAgents` array field
|
|
1867
|
+
*
|
|
1868
|
+
* If both are provided, `targetAgents` takes precedence.
|
|
1869
|
+
*
|
|
1870
|
+
* Note: Uses .nullable() instead of .optional() for OpenAI structured output compatibility
|
|
1863
1871
|
*/
|
|
1864
|
-
declare const RoutingDecisionSchema: z.ZodObject<{
|
|
1872
|
+
declare const RoutingDecisionSchema: z.ZodEffects<z.ZodObject<{
|
|
1865
1873
|
/**
|
|
1866
|
-
* Target agent to route to
|
|
1874
|
+
* Target agent to route to (single agent routing)
|
|
1875
|
+
* @deprecated Use targetAgents for parallel routing support
|
|
1867
1876
|
*/
|
|
1868
|
-
targetAgent: z.ZodString
|
|
1877
|
+
targetAgent: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
1878
|
+
/**
|
|
1879
|
+
* Target agents to route to (parallel routing)
|
|
1880
|
+
* When multiple agents are specified, they execute in parallel
|
|
1881
|
+
*/
|
|
1882
|
+
targetAgents: z.ZodDefault<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
1869
1883
|
/**
|
|
1870
1884
|
* Reasoning for the routing decision
|
|
1871
1885
|
*/
|
|
1872
|
-
reasoning: z.
|
|
1886
|
+
reasoning: z.ZodDefault<z.ZodString>;
|
|
1873
1887
|
/**
|
|
1874
1888
|
* Confidence in the routing decision (0-1)
|
|
1875
1889
|
*/
|
|
1876
|
-
confidence: z.
|
|
1890
|
+
confidence: z.ZodDefault<z.ZodNumber>;
|
|
1877
1891
|
/**
|
|
1878
1892
|
* Strategy used for routing
|
|
1879
1893
|
*/
|
|
1880
|
-
strategy: z.ZodEnum<["llm-based", "rule-based", "round-robin", "skill-based", "load-balanced"]
|
|
1894
|
+
strategy: z.ZodDefault<z.ZodEnum<["llm-based", "rule-based", "round-robin", "skill-based", "load-balanced"]>>;
|
|
1881
1895
|
/**
|
|
1882
1896
|
* Timestamp of the routing decision
|
|
1883
1897
|
*/
|
|
1884
|
-
timestamp: z.
|
|
1898
|
+
timestamp: z.ZodDefault<z.ZodNumber>;
|
|
1885
1899
|
}, "strip", z.ZodTypeAny, {
|
|
1886
|
-
|
|
1900
|
+
timestamp: number;
|
|
1901
|
+
reasoning: string;
|
|
1902
|
+
confidence: number;
|
|
1903
|
+
targetAgent: string | null;
|
|
1904
|
+
targetAgents: string[] | null;
|
|
1887
1905
|
strategy: "llm-based" | "rule-based" | "round-robin" | "skill-based" | "load-balanced";
|
|
1906
|
+
}, {
|
|
1888
1907
|
timestamp?: number | undefined;
|
|
1889
1908
|
reasoning?: string | undefined;
|
|
1890
1909
|
confidence?: number | undefined;
|
|
1891
|
-
|
|
1892
|
-
|
|
1910
|
+
targetAgent?: string | null | undefined;
|
|
1911
|
+
targetAgents?: string[] | null | undefined;
|
|
1912
|
+
strategy?: "llm-based" | "rule-based" | "round-robin" | "skill-based" | "load-balanced" | undefined;
|
|
1913
|
+
}>, {
|
|
1914
|
+
timestamp: number;
|
|
1915
|
+
reasoning: string;
|
|
1916
|
+
confidence: number;
|
|
1917
|
+
targetAgent: string | null;
|
|
1918
|
+
targetAgents: string[] | null;
|
|
1893
1919
|
strategy: "llm-based" | "rule-based" | "round-robin" | "skill-based" | "load-balanced";
|
|
1920
|
+
}, {
|
|
1894
1921
|
timestamp?: number | undefined;
|
|
1895
1922
|
reasoning?: string | undefined;
|
|
1896
1923
|
confidence?: number | undefined;
|
|
1924
|
+
targetAgent?: string | null | undefined;
|
|
1925
|
+
targetAgents?: string[] | null | undefined;
|
|
1926
|
+
strategy?: "llm-based" | "rule-based" | "round-robin" | "skill-based" | "load-balanced" | undefined;
|
|
1897
1927
|
}>;
|
|
1898
1928
|
type RoutingDecision = z.infer<typeof RoutingDecisionSchema>;
|
|
1899
1929
|
/**
|
|
@@ -2166,31 +2196,49 @@ declare const MultiAgentStateConfig: {
|
|
|
2166
2196
|
* Accumulates all routing decisions
|
|
2167
2197
|
*/
|
|
2168
2198
|
routingHistory: {
|
|
2169
|
-
schema: z.ZodArray<z.ZodObject<{
|
|
2170
|
-
targetAgent: z.ZodString
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2199
|
+
schema: z.ZodArray<z.ZodEffects<z.ZodObject<{
|
|
2200
|
+
targetAgent: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
2201
|
+
targetAgents: z.ZodDefault<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
2202
|
+
reasoning: z.ZodDefault<z.ZodString>;
|
|
2203
|
+
confidence: z.ZodDefault<z.ZodNumber>;
|
|
2204
|
+
strategy: z.ZodDefault<z.ZodEnum<["llm-based", "rule-based", "round-robin", "skill-based", "load-balanced"]>>;
|
|
2205
|
+
timestamp: z.ZodDefault<z.ZodNumber>;
|
|
2175
2206
|
}, "strip", z.ZodTypeAny, {
|
|
2176
|
-
|
|
2207
|
+
timestamp: number;
|
|
2208
|
+
reasoning: string;
|
|
2209
|
+
confidence: number;
|
|
2210
|
+
targetAgent: string | null;
|
|
2211
|
+
targetAgents: string[] | null;
|
|
2177
2212
|
strategy: "llm-based" | "rule-based" | "round-robin" | "skill-based" | "load-balanced";
|
|
2213
|
+
}, {
|
|
2178
2214
|
timestamp?: number | undefined;
|
|
2179
2215
|
reasoning?: string | undefined;
|
|
2180
2216
|
confidence?: number | undefined;
|
|
2181
|
-
|
|
2182
|
-
|
|
2217
|
+
targetAgent?: string | null | undefined;
|
|
2218
|
+
targetAgents?: string[] | null | undefined;
|
|
2219
|
+
strategy?: "llm-based" | "rule-based" | "round-robin" | "skill-based" | "load-balanced" | undefined;
|
|
2220
|
+
}>, {
|
|
2221
|
+
timestamp: number;
|
|
2222
|
+
reasoning: string;
|
|
2223
|
+
confidence: number;
|
|
2224
|
+
targetAgent: string | null;
|
|
2225
|
+
targetAgents: string[] | null;
|
|
2183
2226
|
strategy: "llm-based" | "rule-based" | "round-robin" | "skill-based" | "load-balanced";
|
|
2227
|
+
}, {
|
|
2184
2228
|
timestamp?: number | undefined;
|
|
2185
2229
|
reasoning?: string | undefined;
|
|
2186
2230
|
confidence?: number | undefined;
|
|
2231
|
+
targetAgent?: string | null | undefined;
|
|
2232
|
+
targetAgents?: string[] | null | undefined;
|
|
2233
|
+
strategy?: "llm-based" | "rule-based" | "round-robin" | "skill-based" | "load-balanced" | undefined;
|
|
2187
2234
|
}>, "many">;
|
|
2188
2235
|
reducer: (left: RoutingDecision[], right: RoutingDecision[]) => {
|
|
2189
|
-
|
|
2236
|
+
timestamp: number;
|
|
2237
|
+
reasoning: string;
|
|
2238
|
+
confidence: number;
|
|
2239
|
+
targetAgent: string | null;
|
|
2240
|
+
targetAgents: string[] | null;
|
|
2190
2241
|
strategy: "llm-based" | "rule-based" | "round-robin" | "skill-based" | "load-balanced";
|
|
2191
|
-
timestamp?: number | undefined;
|
|
2192
|
-
reasoning?: string | undefined;
|
|
2193
|
-
confidence?: number | undefined;
|
|
2194
2242
|
}[];
|
|
2195
2243
|
default: () => never[];
|
|
2196
2244
|
description: string;
|
|
@@ -2606,7 +2654,7 @@ interface RoutingStrategyImpl {
|
|
|
2606
2654
|
/**
|
|
2607
2655
|
* Default system prompt for LLM-based routing
|
|
2608
2656
|
*/
|
|
2609
|
-
declare const DEFAULT_SUPERVISOR_SYSTEM_PROMPT = "You are a supervisor agent responsible for routing tasks to specialized worker agents.\n\nYour job is to:\n1. Analyze the current task and context\n2. Review available worker capabilities\n3. Select the most appropriate worker for the task\n4. Provide clear reasoning for your decision\n\
|
|
2657
|
+
declare const DEFAULT_SUPERVISOR_SYSTEM_PROMPT = "You are a supervisor agent responsible for routing tasks to specialized worker agents.\n\nYour job is to:\n1. Analyze the current task and context\n2. Review available worker capabilities\n3. Select the most appropriate worker(s) for the task\n4. Provide clear reasoning for your decision\n\n**IMPORTANT: You can route to MULTIPLE workers for parallel execution when:**\n- The task requires information from multiple domains (e.g., code + documentation)\n- Multiple workers have complementary expertise\n- Parallel execution would provide a more comprehensive answer\n\n**Response Format:**\n\nFor SINGLE worker routing:\n{\n \"targetAgent\": \"worker_id\",\n \"reasoning\": \"explanation of why this worker is best suited\",\n \"confidence\": 0.0-1.0,\n \"strategy\": \"llm-based\"\n}\n\nFor PARALLEL multi-worker routing:\n{\n \"targetAgents\": [\"worker_id_1\", \"worker_id_2\", ...],\n \"reasoning\": \"explanation of why these workers should work in parallel\",\n \"confidence\": 0.0-1.0,\n \"strategy\": \"llm-based\"\n}\n\nChoose parallel routing when the task benefits from multiple perspectives or data sources.";
|
|
2610
2658
|
/**
|
|
2611
2659
|
* LLM-based routing strategy
|
|
2612
2660
|
* Uses an LLM to intelligently route tasks based on worker capabilities
|
package/dist/index.js
CHANGED
|
@@ -1543,26 +1543,35 @@ var RoutingStrategySchema = z7.enum([
|
|
|
1543
1543
|
]);
|
|
1544
1544
|
var RoutingDecisionSchema = z7.object({
|
|
1545
1545
|
/**
|
|
1546
|
-
* Target agent to route to
|
|
1546
|
+
* Target agent to route to (single agent routing)
|
|
1547
|
+
* @deprecated Use targetAgents for parallel routing support
|
|
1547
1548
|
*/
|
|
1548
|
-
targetAgent: z7.string().describe("Agent to route the task to"),
|
|
1549
|
+
targetAgent: z7.string().nullable().default(null).describe("Agent to route the task to (single routing)"),
|
|
1550
|
+
/**
|
|
1551
|
+
* Target agents to route to (parallel routing)
|
|
1552
|
+
* When multiple agents are specified, they execute in parallel
|
|
1553
|
+
*/
|
|
1554
|
+
targetAgents: z7.array(z7.string()).nullable().default(null).describe("Agents to route the task to (parallel routing)"),
|
|
1549
1555
|
/**
|
|
1550
1556
|
* Reasoning for the routing decision
|
|
1551
1557
|
*/
|
|
1552
|
-
reasoning: z7.string().
|
|
1558
|
+
reasoning: z7.string().default("").describe("Explanation for routing decision"),
|
|
1553
1559
|
/**
|
|
1554
1560
|
* Confidence in the routing decision (0-1)
|
|
1555
1561
|
*/
|
|
1556
|
-
confidence: z7.number().min(0).max(1).
|
|
1562
|
+
confidence: z7.number().min(0).max(1).default(0.8).describe("Confidence score"),
|
|
1557
1563
|
/**
|
|
1558
1564
|
* Strategy used for routing
|
|
1559
1565
|
*/
|
|
1560
|
-
strategy: RoutingStrategySchema.describe("Strategy used for this decision"),
|
|
1566
|
+
strategy: RoutingStrategySchema.default("llm-based").describe("Strategy used for this decision"),
|
|
1561
1567
|
/**
|
|
1562
1568
|
* Timestamp of the routing decision
|
|
1563
1569
|
*/
|
|
1564
|
-
timestamp: z7.number().
|
|
1565
|
-
})
|
|
1570
|
+
timestamp: z7.number().default(() => Date.now()).describe("Timestamp of the decision")
|
|
1571
|
+
}).refine(
|
|
1572
|
+
(data) => data.targetAgent || data.targetAgents && data.targetAgents.length > 0,
|
|
1573
|
+
{ message: "Either targetAgent or targetAgents must be provided" }
|
|
1574
|
+
);
|
|
1566
1575
|
var WorkerCapabilitiesSchema = z7.object({
|
|
1567
1576
|
/**
|
|
1568
1577
|
* Skills/capabilities the agent has
|
|
@@ -1830,16 +1839,33 @@ var DEFAULT_SUPERVISOR_SYSTEM_PROMPT = `You are a supervisor agent responsible f
|
|
|
1830
1839
|
Your job is to:
|
|
1831
1840
|
1. Analyze the current task and context
|
|
1832
1841
|
2. Review available worker capabilities
|
|
1833
|
-
3. Select the most appropriate worker for the task
|
|
1842
|
+
3. Select the most appropriate worker(s) for the task
|
|
1834
1843
|
4. Provide clear reasoning for your decision
|
|
1835
1844
|
|
|
1836
|
-
|
|
1845
|
+
**IMPORTANT: You can route to MULTIPLE workers for parallel execution when:**
|
|
1846
|
+
- The task requires information from multiple domains (e.g., code + documentation)
|
|
1847
|
+
- Multiple workers have complementary expertise
|
|
1848
|
+
- Parallel execution would provide a more comprehensive answer
|
|
1849
|
+
|
|
1850
|
+
**Response Format:**
|
|
1851
|
+
|
|
1852
|
+
For SINGLE worker routing:
|
|
1837
1853
|
{
|
|
1838
1854
|
"targetAgent": "worker_id",
|
|
1839
1855
|
"reasoning": "explanation of why this worker is best suited",
|
|
1840
1856
|
"confidence": 0.0-1.0,
|
|
1841
1857
|
"strategy": "llm-based"
|
|
1842
|
-
}
|
|
1858
|
+
}
|
|
1859
|
+
|
|
1860
|
+
For PARALLEL multi-worker routing:
|
|
1861
|
+
{
|
|
1862
|
+
"targetAgents": ["worker_id_1", "worker_id_2", ...],
|
|
1863
|
+
"reasoning": "explanation of why these workers should work in parallel",
|
|
1864
|
+
"confidence": 0.0-1.0,
|
|
1865
|
+
"strategy": "llm-based"
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
Choose parallel routing when the task benefits from multiple perspectives or data sources.`;
|
|
1843
1869
|
var llmBasedRouting = {
|
|
1844
1870
|
name: "llm-based",
|
|
1845
1871
|
async route(state, config) {
|
|
@@ -1862,7 +1888,7 @@ var llmBasedRouting = {
|
|
|
1862
1888
|
Available workers:
|
|
1863
1889
|
${workerInfo}
|
|
1864
1890
|
|
|
1865
|
-
Select the best worker for this task and explain your reasoning.`;
|
|
1891
|
+
Select the best worker(s) for this task and explain your reasoning.`;
|
|
1866
1892
|
const conversationHistory = [];
|
|
1867
1893
|
let attempt = 0;
|
|
1868
1894
|
while (attempt < maxRetries) {
|
|
@@ -1884,19 +1910,33 @@ Select the best worker for this task and explain your reasoning.`;
|
|
|
1884
1910
|
attempt++;
|
|
1885
1911
|
continue;
|
|
1886
1912
|
}
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1913
|
+
let decision;
|
|
1914
|
+
if (response && typeof response === "object" && ("targetAgent" in response || "targetAgents" in response)) {
|
|
1915
|
+
decision = response;
|
|
1916
|
+
} else if (response.content) {
|
|
1917
|
+
if (typeof response.content === "string") {
|
|
1918
|
+
try {
|
|
1919
|
+
decision = JSON.parse(response.content);
|
|
1920
|
+
} catch (error) {
|
|
1921
|
+
throw new Error(`Failed to parse routing decision from LLM. Expected JSON but got: ${response.content}`);
|
|
1922
|
+
}
|
|
1923
|
+
} else if (typeof response.content === "object") {
|
|
1924
|
+
decision = response.content;
|
|
1925
|
+
} else {
|
|
1926
|
+
throw new Error(`Unexpected response content type: ${typeof response.content}`);
|
|
1927
|
+
}
|
|
1928
|
+
} else {
|
|
1929
|
+
throw new Error(`Unexpected response format: ${JSON.stringify(response)}`);
|
|
1899
1930
|
}
|
|
1931
|
+
const result = {
|
|
1932
|
+
targetAgent: decision.targetAgent,
|
|
1933
|
+
targetAgents: decision.targetAgents,
|
|
1934
|
+
reasoning: decision.reasoning,
|
|
1935
|
+
confidence: decision.confidence,
|
|
1936
|
+
strategy: "llm-based",
|
|
1937
|
+
timestamp: Date.now()
|
|
1938
|
+
};
|
|
1939
|
+
return result;
|
|
1900
1940
|
}
|
|
1901
1941
|
throw new Error(`Max tool retries (${maxRetries}) exceeded without routing decision`);
|
|
1902
1942
|
}
|
|
@@ -1912,6 +1952,7 @@ var roundRobinRouting = {
|
|
|
1912
1952
|
const targetAgent = availableWorkers[lastRoutingIndex];
|
|
1913
1953
|
return {
|
|
1914
1954
|
targetAgent,
|
|
1955
|
+
targetAgents: null,
|
|
1915
1956
|
reasoning: `Round-robin selection: worker ${lastRoutingIndex + 1} of ${availableWorkers.length}`,
|
|
1916
1957
|
confidence: 1,
|
|
1917
1958
|
strategy: "round-robin",
|
|
@@ -1941,6 +1982,7 @@ var skillBasedRouting = {
|
|
|
1941
1982
|
}
|
|
1942
1983
|
return {
|
|
1943
1984
|
targetAgent: firstAvailable[0],
|
|
1985
|
+
targetAgents: null,
|
|
1944
1986
|
reasoning: "No skill matches found, using first available worker",
|
|
1945
1987
|
confidence: 0.5,
|
|
1946
1988
|
strategy: "skill-based",
|
|
@@ -1951,6 +1993,7 @@ var skillBasedRouting = {
|
|
|
1951
1993
|
const confidence = Math.min(best.score / 5, 1);
|
|
1952
1994
|
return {
|
|
1953
1995
|
targetAgent: best.id,
|
|
1996
|
+
targetAgents: null,
|
|
1954
1997
|
reasoning: `Best skill match with score ${best.score} (skills: ${best.skills.join(", ")})`,
|
|
1955
1998
|
confidence,
|
|
1956
1999
|
strategy: "skill-based",
|
|
@@ -1970,6 +2013,7 @@ var loadBalancedRouting = {
|
|
|
1970
2013
|
const confidence = targetWorker.workload === 0 ? 1 : Math.max(0.5, 1 - targetWorker.workload / (avgWorkload * 2));
|
|
1971
2014
|
return {
|
|
1972
2015
|
targetAgent: targetWorker.id,
|
|
2016
|
+
targetAgents: null,
|
|
1973
2017
|
reasoning: `Lowest workload: ${targetWorker.workload} tasks (avg: ${avgWorkload.toFixed(1)})`,
|
|
1974
2018
|
confidence,
|
|
1975
2019
|
strategy: "load-balanced",
|
|
@@ -2025,10 +2069,7 @@ function wrapReActAgent(workerId, agent, verbose = false) {
|
|
|
2025
2069
|
);
|
|
2026
2070
|
if (!currentAssignment) {
|
|
2027
2071
|
logger.debug("No active assignment found", { workerId });
|
|
2028
|
-
return {
|
|
2029
|
-
currentAgent: "supervisor",
|
|
2030
|
-
status: "routing"
|
|
2031
|
-
};
|
|
2072
|
+
return {};
|
|
2032
2073
|
}
|
|
2033
2074
|
const result = await agent.invoke(
|
|
2034
2075
|
{
|
|
@@ -2060,9 +2101,7 @@ function wrapReActAgent(workerId, agent, verbose = false) {
|
|
|
2060
2101
|
}
|
|
2061
2102
|
};
|
|
2062
2103
|
return {
|
|
2063
|
-
completedTasks: [taskResult]
|
|
2064
|
-
currentAgent: "supervisor",
|
|
2065
|
-
status: "routing"
|
|
2104
|
+
completedTasks: [taskResult]
|
|
2066
2105
|
};
|
|
2067
2106
|
} catch (error) {
|
|
2068
2107
|
if (error && typeof error === "object" && "constructor" in error && error.constructor.name === "GraphInterrupt") {
|
|
@@ -2133,7 +2172,7 @@ function createSupervisorNode(config) {
|
|
|
2133
2172
|
};
|
|
2134
2173
|
}
|
|
2135
2174
|
const allCompleted = state.activeAssignments.every(
|
|
2136
|
-
(
|
|
2175
|
+
(assignment) => state.completedTasks.some((task2) => task2.assignmentId === assignment.id)
|
|
2137
2176
|
);
|
|
2138
2177
|
if (allCompleted && state.activeAssignments.length > 0) {
|
|
2139
2178
|
if (verbose) {
|
|
@@ -2146,20 +2185,29 @@ function createSupervisorNode(config) {
|
|
|
2146
2185
|
}
|
|
2147
2186
|
const routingImpl = getRoutingStrategy(strategy);
|
|
2148
2187
|
const decision = await routingImpl.route(state, config);
|
|
2188
|
+
const targetAgents = decision.targetAgents && decision.targetAgents.length > 0 ? decision.targetAgents : decision.targetAgent ? [decision.targetAgent] : [];
|
|
2189
|
+
if (targetAgents.length === 0) {
|
|
2190
|
+
throw new Error("Routing decision must specify at least one target agent");
|
|
2191
|
+
}
|
|
2149
2192
|
if (verbose) {
|
|
2150
|
-
|
|
2193
|
+
if (targetAgents.length === 1) {
|
|
2194
|
+
console.log(`[Supervisor] Routing to ${targetAgents[0]}: ${decision.reasoning}`);
|
|
2195
|
+
} else {
|
|
2196
|
+
console.log(`[Supervisor] Routing to ${targetAgents.length} agents in parallel [${targetAgents.join(", ")}]: ${decision.reasoning}`);
|
|
2197
|
+
}
|
|
2151
2198
|
}
|
|
2152
|
-
const
|
|
2199
|
+
const task = state.messages[state.messages.length - 1]?.content || state.input;
|
|
2200
|
+
const assignments = targetAgents.map((workerId) => ({
|
|
2153
2201
|
id: `task_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
|
2154
|
-
workerId
|
|
2155
|
-
task
|
|
2202
|
+
workerId,
|
|
2203
|
+
task,
|
|
2156
2204
|
priority: 5,
|
|
2157
2205
|
assignedAt: Date.now()
|
|
2158
|
-
};
|
|
2159
|
-
const
|
|
2206
|
+
}));
|
|
2207
|
+
const messages = assignments.map((assignment) => ({
|
|
2160
2208
|
id: `msg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
2161
2209
|
from: "supervisor",
|
|
2162
|
-
to: [
|
|
2210
|
+
to: [assignment.workerId],
|
|
2163
2211
|
type: "task_assignment",
|
|
2164
2212
|
content: assignment.task,
|
|
2165
2213
|
timestamp: Date.now(),
|
|
@@ -2167,13 +2215,15 @@ function createSupervisorNode(config) {
|
|
|
2167
2215
|
assignmentId: assignment.id,
|
|
2168
2216
|
priority: assignment.priority
|
|
2169
2217
|
}
|
|
2170
|
-
};
|
|
2218
|
+
}));
|
|
2171
2219
|
return {
|
|
2172
|
-
currentAgent:
|
|
2220
|
+
currentAgent: targetAgents.join(","),
|
|
2221
|
+
// Store all agents (for backward compat)
|
|
2173
2222
|
status: "executing",
|
|
2174
2223
|
routingHistory: [decision],
|
|
2175
|
-
activeAssignments:
|
|
2176
|
-
|
|
2224
|
+
activeAssignments: assignments,
|
|
2225
|
+
// Multiple assignments for parallel execution!
|
|
2226
|
+
messages,
|
|
2177
2227
|
iteration: state.iteration + 1
|
|
2178
2228
|
};
|
|
2179
2229
|
} catch (error) {
|
|
@@ -2208,10 +2258,7 @@ function createWorkerNode(config) {
|
|
|
2208
2258
|
if (verbose) {
|
|
2209
2259
|
console.log(`[Worker:${id}] No active assignment found`);
|
|
2210
2260
|
}
|
|
2211
|
-
return {
|
|
2212
|
-
currentAgent: "supervisor",
|
|
2213
|
-
status: "routing"
|
|
2214
|
-
};
|
|
2261
|
+
return {};
|
|
2215
2262
|
}
|
|
2216
2263
|
if (executeFn) {
|
|
2217
2264
|
if (verbose) {
|
|
@@ -2286,9 +2333,7 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
|
|
|
2286
2333
|
return {
|
|
2287
2334
|
completedTasks: [taskResult],
|
|
2288
2335
|
messages: [message],
|
|
2289
|
-
workers: updatedWorkers
|
|
2290
|
-
currentAgent: "supervisor",
|
|
2291
|
-
status: "routing"
|
|
2336
|
+
workers: updatedWorkers
|
|
2292
2337
|
};
|
|
2293
2338
|
} catch (error) {
|
|
2294
2339
|
if (error && typeof error === "object" && "constructor" in error && error.constructor.name === "GraphInterrupt") {
|
|
@@ -2401,10 +2446,16 @@ function createMultiAgentSystem(config) {
|
|
|
2401
2446
|
} = config;
|
|
2402
2447
|
const workflow = new StateGraph4(MultiAgentState);
|
|
2403
2448
|
let supervisorConfig = { ...supervisor, maxIterations, verbose };
|
|
2404
|
-
if (supervisor.model
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2449
|
+
if (supervisor.model) {
|
|
2450
|
+
let configuredModel = supervisor.model;
|
|
2451
|
+
if (supervisor.strategy === "llm-based") {
|
|
2452
|
+
configuredModel = configuredModel.withStructuredOutput(RoutingDecisionSchema);
|
|
2453
|
+
}
|
|
2454
|
+
if (supervisor.tools && supervisor.tools.length > 0) {
|
|
2455
|
+
const langchainTools = toLangChainTools3(supervisor.tools);
|
|
2456
|
+
configuredModel = configuredModel.bindTools(langchainTools);
|
|
2457
|
+
}
|
|
2458
|
+
supervisorConfig.model = configuredModel;
|
|
2408
2459
|
}
|
|
2409
2460
|
const supervisorNode = createSupervisorNode(supervisorConfig);
|
|
2410
2461
|
workflow.addNode("supervisor", supervisorNode);
|
|
@@ -2432,6 +2483,10 @@ function createMultiAgentSystem(config) {
|
|
|
2432
2483
|
return "aggregator";
|
|
2433
2484
|
}
|
|
2434
2485
|
if (state.currentAgent && state.currentAgent !== "supervisor") {
|
|
2486
|
+
if (state.currentAgent.includes(",")) {
|
|
2487
|
+
const agents = state.currentAgent.split(",").map((a) => a.trim());
|
|
2488
|
+
return agents;
|
|
2489
|
+
}
|
|
2435
2490
|
return state.currentAgent;
|
|
2436
2491
|
}
|
|
2437
2492
|
return "supervisor";
|