@agentforge/patterns 0.5.4 → 0.6.0
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 +74 -24
- package/dist/index.d.cts +33 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +75 -25
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1891,6 +1891,33 @@ var MultiAgentState = (0, import_core6.createStateAnnotation)(MultiAgentStateCon
|
|
|
1891
1891
|
|
|
1892
1892
|
// src/multi-agent/routing.ts
|
|
1893
1893
|
var import_messages4 = require("@langchain/core/messages");
|
|
1894
|
+
async function executeTools(toolCalls, tools) {
|
|
1895
|
+
const results = [];
|
|
1896
|
+
for (const toolCall of toolCalls) {
|
|
1897
|
+
const tool = tools.find((t) => t.metadata.name === toolCall.name);
|
|
1898
|
+
if (!tool) {
|
|
1899
|
+
results.push(new import_messages4.ToolMessage({
|
|
1900
|
+
content: `Error: Tool '${toolCall.name}' not found`,
|
|
1901
|
+
tool_call_id: toolCall.id
|
|
1902
|
+
}));
|
|
1903
|
+
continue;
|
|
1904
|
+
}
|
|
1905
|
+
try {
|
|
1906
|
+
const result = await tool.execute(toolCall.args);
|
|
1907
|
+
const content = typeof result === "string" ? result : JSON.stringify(result);
|
|
1908
|
+
results.push(new import_messages4.ToolMessage({
|
|
1909
|
+
content,
|
|
1910
|
+
tool_call_id: toolCall.id
|
|
1911
|
+
}));
|
|
1912
|
+
} catch (error) {
|
|
1913
|
+
results.push(new import_messages4.ToolMessage({
|
|
1914
|
+
content: `Error executing tool: ${error.message}`,
|
|
1915
|
+
tool_call_id: toolCall.id
|
|
1916
|
+
}));
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1919
|
+
return results;
|
|
1920
|
+
}
|
|
1894
1921
|
var DEFAULT_SUPERVISOR_SYSTEM_PROMPT = `You are a supervisor agent responsible for routing tasks to specialized worker agents.
|
|
1895
1922
|
|
|
1896
1923
|
Your job is to:
|
|
@@ -1913,11 +1940,13 @@ var llmBasedRouting = {
|
|
|
1913
1940
|
throw new Error("LLM-based routing requires a model to be configured");
|
|
1914
1941
|
}
|
|
1915
1942
|
const systemPrompt = config.systemPrompt || DEFAULT_SUPERVISOR_SYSTEM_PROMPT;
|
|
1943
|
+
const maxRetries = config.maxToolRetries || 3;
|
|
1944
|
+
const tools = config.tools || [];
|
|
1916
1945
|
const workerInfo = Object.entries(state.workers).map(([id, caps]) => {
|
|
1917
1946
|
const skills = caps.skills.join(", ");
|
|
1918
|
-
const
|
|
1947
|
+
const tools2 = caps.tools.join(", ");
|
|
1919
1948
|
const available = caps.available ? "available" : "busy";
|
|
1920
|
-
return `- ${id}: Skills: [${skills}], Tools: [${
|
|
1949
|
+
return `- ${id}: Skills: [${skills}], Tools: [${tools2}], Status: ${available}, Workload: ${caps.currentWorkload}`;
|
|
1921
1950
|
}).join("\n");
|
|
1922
1951
|
const lastMessage = state.messages[state.messages.length - 1];
|
|
1923
1952
|
const taskContext = lastMessage?.content || state.input;
|
|
@@ -1927,24 +1956,42 @@ Available workers:
|
|
|
1927
1956
|
${workerInfo}
|
|
1928
1957
|
|
|
1929
1958
|
Select the best worker for this task and explain your reasoning.`;
|
|
1930
|
-
const
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1959
|
+
const conversationHistory = [];
|
|
1960
|
+
let attempt = 0;
|
|
1961
|
+
while (attempt < maxRetries) {
|
|
1962
|
+
const messages = [
|
|
1963
|
+
new import_messages4.SystemMessage(systemPrompt),
|
|
1964
|
+
new import_messages4.HumanMessage(userPrompt),
|
|
1965
|
+
...conversationHistory
|
|
1966
|
+
];
|
|
1967
|
+
const response = await config.model.invoke(messages);
|
|
1968
|
+
if (response.tool_calls && response.tool_calls.length > 0) {
|
|
1969
|
+
if (tools.length === 0) {
|
|
1970
|
+
throw new Error("LLM requested tool calls but no tools are configured");
|
|
1971
|
+
}
|
|
1972
|
+
const toolResults = await executeTools(response.tool_calls, tools);
|
|
1973
|
+
conversationHistory.push(
|
|
1974
|
+
new import_messages4.AIMessage({ content: response.content || "", tool_calls: response.tool_calls }),
|
|
1975
|
+
...toolResults
|
|
1976
|
+
);
|
|
1977
|
+
attempt++;
|
|
1978
|
+
continue;
|
|
1979
|
+
}
|
|
1980
|
+
const content = typeof response.content === "string" ? response.content : JSON.stringify(response.content);
|
|
1981
|
+
try {
|
|
1982
|
+
const decision = JSON.parse(content);
|
|
1983
|
+
return {
|
|
1984
|
+
targetAgent: decision.targetAgent,
|
|
1985
|
+
reasoning: decision.reasoning,
|
|
1986
|
+
confidence: decision.confidence,
|
|
1987
|
+
strategy: "llm-based",
|
|
1988
|
+
timestamp: Date.now()
|
|
1989
|
+
};
|
|
1990
|
+
} catch (error) {
|
|
1991
|
+
throw new Error(`Failed to parse routing decision from LLM: ${error}`);
|
|
1992
|
+
}
|
|
1947
1993
|
}
|
|
1994
|
+
throw new Error(`Max tool retries (${maxRetries}) exceeded without routing decision`);
|
|
1948
1995
|
}
|
|
1949
1996
|
};
|
|
1950
1997
|
var roundRobinRouting = {
|
|
@@ -2419,6 +2466,7 @@ Please synthesize these results into a comprehensive response that addresses the
|
|
|
2419
2466
|
|
|
2420
2467
|
// src/multi-agent/agent.ts
|
|
2421
2468
|
var import_langgraph4 = require("@langchain/langgraph");
|
|
2469
|
+
var import_core8 = require("@agentforge/core");
|
|
2422
2470
|
function createMultiAgentSystem(config) {
|
|
2423
2471
|
const {
|
|
2424
2472
|
supervisor,
|
|
@@ -2429,11 +2477,13 @@ function createMultiAgentSystem(config) {
|
|
|
2429
2477
|
checkpointer
|
|
2430
2478
|
} = config;
|
|
2431
2479
|
const workflow = new import_langgraph4.StateGraph(MultiAgentState);
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2480
|
+
let supervisorConfig = { ...supervisor, maxIterations, verbose };
|
|
2481
|
+
if (supervisor.model && supervisor.tools && supervisor.tools.length > 0) {
|
|
2482
|
+
const langchainTools = (0, import_core8.toLangChainTools)(supervisor.tools);
|
|
2483
|
+
const modelWithTools = supervisor.model.bindTools(langchainTools);
|
|
2484
|
+
supervisorConfig.model = modelWithTools;
|
|
2485
|
+
}
|
|
2486
|
+
const supervisorNode = createSupervisorNode(supervisorConfig);
|
|
2437
2487
|
workflow.addNode("supervisor", supervisorNode);
|
|
2438
2488
|
const workerIds = [];
|
|
2439
2489
|
const workerCapabilities = {};
|
package/dist/index.d.cts
CHANGED
|
@@ -2411,6 +2411,37 @@ interface SupervisorConfig {
|
|
|
2411
2411
|
* Maximum number of routing iterations
|
|
2412
2412
|
*/
|
|
2413
2413
|
maxIterations?: number;
|
|
2414
|
+
/**
|
|
2415
|
+
* Optional tools the supervisor can use during routing
|
|
2416
|
+
*
|
|
2417
|
+
* Enables the supervisor to gather additional information before making routing decisions.
|
|
2418
|
+
* Common use case: askHuman tool for clarifying ambiguous queries.
|
|
2419
|
+
*
|
|
2420
|
+
* Note: Only works with LLM-based routing strategy.
|
|
2421
|
+
*
|
|
2422
|
+
* @example
|
|
2423
|
+
* ```typescript
|
|
2424
|
+
* import { createAskHumanTool } from '@agentforge/tools';
|
|
2425
|
+
*
|
|
2426
|
+
* const system = createMultiAgentSystem({
|
|
2427
|
+
* supervisor: {
|
|
2428
|
+
* strategy: 'llm-based',
|
|
2429
|
+
* model: chatModel,
|
|
2430
|
+
* tools: [createAskHumanTool()],
|
|
2431
|
+
* },
|
|
2432
|
+
* // ...
|
|
2433
|
+
* });
|
|
2434
|
+
* ```
|
|
2435
|
+
*/
|
|
2436
|
+
tools?: Tool<any, any>[];
|
|
2437
|
+
/**
|
|
2438
|
+
* Maximum number of tool call retries before requiring routing decision
|
|
2439
|
+
*
|
|
2440
|
+
* Prevents infinite loops where the supervisor keeps calling tools without making a routing decision.
|
|
2441
|
+
*
|
|
2442
|
+
* @default 3
|
|
2443
|
+
*/
|
|
2444
|
+
maxToolRetries?: number;
|
|
2414
2445
|
}
|
|
2415
2446
|
/**
|
|
2416
2447
|
* Configuration for a worker agent node
|
|
@@ -2576,6 +2607,8 @@ declare const DEFAULT_SUPERVISOR_SYSTEM_PROMPT = "You are a supervisor agent res
|
|
|
2576
2607
|
/**
|
|
2577
2608
|
* LLM-based routing strategy
|
|
2578
2609
|
* Uses an LLM to intelligently route tasks based on worker capabilities
|
|
2610
|
+
*
|
|
2611
|
+
* Supports tool calls (e.g., askHuman) for gathering additional information before routing.
|
|
2579
2612
|
*/
|
|
2580
2613
|
declare const llmBasedRouting: RoutingStrategyImpl;
|
|
2581
2614
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -2411,6 +2411,37 @@ interface SupervisorConfig {
|
|
|
2411
2411
|
* Maximum number of routing iterations
|
|
2412
2412
|
*/
|
|
2413
2413
|
maxIterations?: number;
|
|
2414
|
+
/**
|
|
2415
|
+
* Optional tools the supervisor can use during routing
|
|
2416
|
+
*
|
|
2417
|
+
* Enables the supervisor to gather additional information before making routing decisions.
|
|
2418
|
+
* Common use case: askHuman tool for clarifying ambiguous queries.
|
|
2419
|
+
*
|
|
2420
|
+
* Note: Only works with LLM-based routing strategy.
|
|
2421
|
+
*
|
|
2422
|
+
* @example
|
|
2423
|
+
* ```typescript
|
|
2424
|
+
* import { createAskHumanTool } from '@agentforge/tools';
|
|
2425
|
+
*
|
|
2426
|
+
* const system = createMultiAgentSystem({
|
|
2427
|
+
* supervisor: {
|
|
2428
|
+
* strategy: 'llm-based',
|
|
2429
|
+
* model: chatModel,
|
|
2430
|
+
* tools: [createAskHumanTool()],
|
|
2431
|
+
* },
|
|
2432
|
+
* // ...
|
|
2433
|
+
* });
|
|
2434
|
+
* ```
|
|
2435
|
+
*/
|
|
2436
|
+
tools?: Tool<any, any>[];
|
|
2437
|
+
/**
|
|
2438
|
+
* Maximum number of tool call retries before requiring routing decision
|
|
2439
|
+
*
|
|
2440
|
+
* Prevents infinite loops where the supervisor keeps calling tools without making a routing decision.
|
|
2441
|
+
*
|
|
2442
|
+
* @default 3
|
|
2443
|
+
*/
|
|
2444
|
+
maxToolRetries?: number;
|
|
2414
2445
|
}
|
|
2415
2446
|
/**
|
|
2416
2447
|
* Configuration for a worker agent node
|
|
@@ -2576,6 +2607,8 @@ declare const DEFAULT_SUPERVISOR_SYSTEM_PROMPT = "You are a supervisor agent res
|
|
|
2576
2607
|
/**
|
|
2577
2608
|
* LLM-based routing strategy
|
|
2578
2609
|
* Uses an LLM to intelligently route tasks based on worker capabilities
|
|
2610
|
+
*
|
|
2611
|
+
* Supports tool calls (e.g., askHuman) for gathering additional information before routing.
|
|
2579
2612
|
*/
|
|
2580
2613
|
declare const llmBasedRouting: RoutingStrategyImpl;
|
|
2581
2614
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1791,7 +1791,34 @@ var MultiAgentStateConfig = {
|
|
|
1791
1791
|
var MultiAgentState = createStateAnnotation4(MultiAgentStateConfig);
|
|
1792
1792
|
|
|
1793
1793
|
// src/multi-agent/routing.ts
|
|
1794
|
-
import { HumanMessage as HumanMessage4, SystemMessage as SystemMessage4 } from "@langchain/core/messages";
|
|
1794
|
+
import { HumanMessage as HumanMessage4, SystemMessage as SystemMessage4, AIMessage as AIMessage2, ToolMessage as ToolMessage2 } from "@langchain/core/messages";
|
|
1795
|
+
async function executeTools(toolCalls, tools) {
|
|
1796
|
+
const results = [];
|
|
1797
|
+
for (const toolCall of toolCalls) {
|
|
1798
|
+
const tool = tools.find((t) => t.metadata.name === toolCall.name);
|
|
1799
|
+
if (!tool) {
|
|
1800
|
+
results.push(new ToolMessage2({
|
|
1801
|
+
content: `Error: Tool '${toolCall.name}' not found`,
|
|
1802
|
+
tool_call_id: toolCall.id
|
|
1803
|
+
}));
|
|
1804
|
+
continue;
|
|
1805
|
+
}
|
|
1806
|
+
try {
|
|
1807
|
+
const result = await tool.execute(toolCall.args);
|
|
1808
|
+
const content = typeof result === "string" ? result : JSON.stringify(result);
|
|
1809
|
+
results.push(new ToolMessage2({
|
|
1810
|
+
content,
|
|
1811
|
+
tool_call_id: toolCall.id
|
|
1812
|
+
}));
|
|
1813
|
+
} catch (error) {
|
|
1814
|
+
results.push(new ToolMessage2({
|
|
1815
|
+
content: `Error executing tool: ${error.message}`,
|
|
1816
|
+
tool_call_id: toolCall.id
|
|
1817
|
+
}));
|
|
1818
|
+
}
|
|
1819
|
+
}
|
|
1820
|
+
return results;
|
|
1821
|
+
}
|
|
1795
1822
|
var DEFAULT_SUPERVISOR_SYSTEM_PROMPT = `You are a supervisor agent responsible for routing tasks to specialized worker agents.
|
|
1796
1823
|
|
|
1797
1824
|
Your job is to:
|
|
@@ -1814,11 +1841,13 @@ var llmBasedRouting = {
|
|
|
1814
1841
|
throw new Error("LLM-based routing requires a model to be configured");
|
|
1815
1842
|
}
|
|
1816
1843
|
const systemPrompt = config.systemPrompt || DEFAULT_SUPERVISOR_SYSTEM_PROMPT;
|
|
1844
|
+
const maxRetries = config.maxToolRetries || 3;
|
|
1845
|
+
const tools = config.tools || [];
|
|
1817
1846
|
const workerInfo = Object.entries(state.workers).map(([id, caps]) => {
|
|
1818
1847
|
const skills = caps.skills.join(", ");
|
|
1819
|
-
const
|
|
1848
|
+
const tools2 = caps.tools.join(", ");
|
|
1820
1849
|
const available = caps.available ? "available" : "busy";
|
|
1821
|
-
return `- ${id}: Skills: [${skills}], Tools: [${
|
|
1850
|
+
return `- ${id}: Skills: [${skills}], Tools: [${tools2}], Status: ${available}, Workload: ${caps.currentWorkload}`;
|
|
1822
1851
|
}).join("\n");
|
|
1823
1852
|
const lastMessage = state.messages[state.messages.length - 1];
|
|
1824
1853
|
const taskContext = lastMessage?.content || state.input;
|
|
@@ -1828,24 +1857,42 @@ Available workers:
|
|
|
1828
1857
|
${workerInfo}
|
|
1829
1858
|
|
|
1830
1859
|
Select the best worker for this task and explain your reasoning.`;
|
|
1831
|
-
const
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1860
|
+
const conversationHistory = [];
|
|
1861
|
+
let attempt = 0;
|
|
1862
|
+
while (attempt < maxRetries) {
|
|
1863
|
+
const messages = [
|
|
1864
|
+
new SystemMessage4(systemPrompt),
|
|
1865
|
+
new HumanMessage4(userPrompt),
|
|
1866
|
+
...conversationHistory
|
|
1867
|
+
];
|
|
1868
|
+
const response = await config.model.invoke(messages);
|
|
1869
|
+
if (response.tool_calls && response.tool_calls.length > 0) {
|
|
1870
|
+
if (tools.length === 0) {
|
|
1871
|
+
throw new Error("LLM requested tool calls but no tools are configured");
|
|
1872
|
+
}
|
|
1873
|
+
const toolResults = await executeTools(response.tool_calls, tools);
|
|
1874
|
+
conversationHistory.push(
|
|
1875
|
+
new AIMessage2({ content: response.content || "", tool_calls: response.tool_calls }),
|
|
1876
|
+
...toolResults
|
|
1877
|
+
);
|
|
1878
|
+
attempt++;
|
|
1879
|
+
continue;
|
|
1880
|
+
}
|
|
1881
|
+
const content = typeof response.content === "string" ? response.content : JSON.stringify(response.content);
|
|
1882
|
+
try {
|
|
1883
|
+
const decision = JSON.parse(content);
|
|
1884
|
+
return {
|
|
1885
|
+
targetAgent: decision.targetAgent,
|
|
1886
|
+
reasoning: decision.reasoning,
|
|
1887
|
+
confidence: decision.confidence,
|
|
1888
|
+
strategy: "llm-based",
|
|
1889
|
+
timestamp: Date.now()
|
|
1890
|
+
};
|
|
1891
|
+
} catch (error) {
|
|
1892
|
+
throw new Error(`Failed to parse routing decision from LLM: ${error}`);
|
|
1893
|
+
}
|
|
1848
1894
|
}
|
|
1895
|
+
throw new Error(`Max tool retries (${maxRetries}) exceeded without routing decision`);
|
|
1849
1896
|
}
|
|
1850
1897
|
};
|
|
1851
1898
|
var roundRobinRouting = {
|
|
@@ -2320,6 +2367,7 @@ Please synthesize these results into a comprehensive response that addresses the
|
|
|
2320
2367
|
|
|
2321
2368
|
// src/multi-agent/agent.ts
|
|
2322
2369
|
import { StateGraph as StateGraph4, END as END4 } from "@langchain/langgraph";
|
|
2370
|
+
import { toLangChainTools as toLangChainTools3 } from "@agentforge/core";
|
|
2323
2371
|
function createMultiAgentSystem(config) {
|
|
2324
2372
|
const {
|
|
2325
2373
|
supervisor,
|
|
@@ -2330,11 +2378,13 @@ function createMultiAgentSystem(config) {
|
|
|
2330
2378
|
checkpointer
|
|
2331
2379
|
} = config;
|
|
2332
2380
|
const workflow = new StateGraph4(MultiAgentState);
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2381
|
+
let supervisorConfig = { ...supervisor, maxIterations, verbose };
|
|
2382
|
+
if (supervisor.model && supervisor.tools && supervisor.tools.length > 0) {
|
|
2383
|
+
const langchainTools = toLangChainTools3(supervisor.tools);
|
|
2384
|
+
const modelWithTools = supervisor.model.bindTools(langchainTools);
|
|
2385
|
+
supervisorConfig.model = modelWithTools;
|
|
2386
|
+
}
|
|
2387
|
+
const supervisorNode = createSupervisorNode(supervisorConfig);
|
|
2338
2388
|
workflow.addNode("supervisor", supervisorNode);
|
|
2339
2389
|
const workerIds = [];
|
|
2340
2390
|
const workerCapabilities = {};
|