@agentforge/patterns 0.7.0 → 0.8.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.js CHANGED
@@ -180,8 +180,8 @@ function generateToolCallCacheKey(toolName, args) {
180
180
  return `${toolName}:${sortedArgs}`;
181
181
  }
182
182
  function createPatternLogger(name, defaultLevel = "info") {
183
- const logLevel5 = process.env.LOG_LEVEL?.toLowerCase() || defaultLevel;
184
- return createLogger(name, { level: logLevel5 });
183
+ const logLevel4 = process.env.LOG_LEVEL?.toLowerCase() || defaultLevel;
184
+ return createLogger(name, { level: logLevel4 });
185
185
  }
186
186
  function calculateDeduplicationSavings(duplicatesSkipped, toolsExecuted) {
187
187
  if (duplicatesSkipped === 0) {
@@ -2060,67 +2060,7 @@ var MultiAgentStateConfig = {
2060
2060
  var MultiAgentState = createStateAnnotation4(MultiAgentStateConfig);
2061
2061
 
2062
2062
  // src/multi-agent/routing.ts
2063
- import { HumanMessage as HumanMessage4, SystemMessage as SystemMessage4, AIMessage as AIMessage2, ToolMessage as ToolMessage2 } from "@langchain/core/messages";
2064
- import { createLogger as createLogger2, LogLevel } from "@agentforge/core";
2065
- var logLevel = process.env.LOG_LEVEL?.toLowerCase() || LogLevel.INFO;
2066
- var logger = createLogger2("multi-agent:routing", { level: logLevel });
2067
- async function executeTools(toolCalls, tools) {
2068
- const results = [];
2069
- logger.debug("Executing tools", {
2070
- toolCallCount: toolCalls.length,
2071
- toolNames: toolCalls.map((tc) => tc.name)
2072
- });
2073
- for (const toolCall of toolCalls) {
2074
- const tool = tools.find((t) => t.metadata.name === toolCall.name);
2075
- if (!tool) {
2076
- logger.warn("Tool not found", {
2077
- toolName: toolCall.name,
2078
- availableTools: tools.map((t) => t.metadata.name)
2079
- });
2080
- results.push(new ToolMessage2({
2081
- content: `Error: Tool '${toolCall.name}' not found`,
2082
- tool_call_id: toolCall.id
2083
- }));
2084
- continue;
2085
- }
2086
- try {
2087
- logger.debug("Executing tool", {
2088
- toolName: toolCall.name,
2089
- args: toolCall.args
2090
- });
2091
- const result = await tool.execute(toolCall.args);
2092
- const content = typeof result === "string" ? result : JSON.stringify(result);
2093
- logger.debug("Tool execution successful", {
2094
- toolName: toolCall.name,
2095
- resultLength: content.length
2096
- });
2097
- results.push(new ToolMessage2({
2098
- content,
2099
- tool_call_id: toolCall.id
2100
- }));
2101
- } catch (error) {
2102
- logger.error("Tool execution failed", {
2103
- toolName: toolCall.name,
2104
- error: error.message
2105
- });
2106
- results.push(new ToolMessage2({
2107
- content: `Error executing tool: ${error.message}`,
2108
- tool_call_id: toolCall.id
2109
- }));
2110
- }
2111
- }
2112
- logger.debug("Tool execution complete", {
2113
- successCount: results.filter((r) => {
2114
- const content = typeof r.content === "string" ? r.content : JSON.stringify(r.content);
2115
- return !content.startsWith("Error");
2116
- }).length,
2117
- errorCount: results.filter((r) => {
2118
- const content = typeof r.content === "string" ? r.content : JSON.stringify(r.content);
2119
- return content.startsWith("Error");
2120
- }).length
2121
- });
2122
- return results;
2123
- }
2063
+ import { HumanMessage as HumanMessage4, SystemMessage as SystemMessage4 } from "@langchain/core/messages";
2124
2064
  var DEFAULT_SUPERVISOR_SYSTEM_PROMPT = `You are a supervisor agent responsible for routing tasks to specialized worker agents.
2125
2065
 
2126
2066
  Your job is to:
@@ -2156,151 +2096,48 @@ Choose parallel routing when the task benefits from multiple perspectives or dat
2156
2096
  var llmBasedRouting = {
2157
2097
  name: "llm-based",
2158
2098
  async route(state, config) {
2159
- logger.info("Starting LLM-based routing", {
2160
- iteration: state.iteration,
2161
- availableWorkers: Object.keys(state.workers).length
2162
- });
2163
2099
  if (!config.model) {
2164
2100
  throw new Error("LLM-based routing requires a model to be configured");
2165
2101
  }
2166
2102
  const systemPrompt = config.systemPrompt || DEFAULT_SUPERVISOR_SYSTEM_PROMPT;
2167
- const maxRetries = config.maxToolRetries || 3;
2168
- const tools = config.tools || [];
2169
2103
  const workerInfo = Object.entries(state.workers).map(([id, caps]) => {
2170
2104
  const skills = caps.skills.join(", ");
2171
- const tools2 = caps.tools.join(", ");
2105
+ const tools = caps.tools.join(", ");
2172
2106
  const available = caps.available ? "available" : "busy";
2173
- return `- ${id}: Skills: [${skills}], Tools: [${tools2}], Status: ${available}, Workload: ${caps.currentWorkload}`;
2107
+ return `- ${id}: Skills: [${skills}], Tools: [${tools}], Status: ${available}, Workload: ${caps.currentWorkload}`;
2174
2108
  }).join("\n");
2175
- logger.debug("Worker capabilities", {
2176
- workers: Object.entries(state.workers).map(([id, caps]) => ({
2177
- id,
2178
- skills: caps.skills,
2179
- available: caps.available,
2180
- workload: caps.currentWorkload
2181
- }))
2182
- });
2183
2109
  const lastMessage = state.messages[state.messages.length - 1];
2184
2110
  const taskContext = lastMessage?.content || state.input;
2185
- logger.debug("Task context", {
2186
- taskLength: taskContext.length,
2187
- taskPreview: taskContext.substring(0, 100)
2188
- });
2189
2111
  const userPrompt = `Current task: ${taskContext}
2190
2112
 
2191
2113
  Available workers:
2192
2114
  ${workerInfo}
2193
2115
 
2194
2116
  Select the best worker(s) for this task and explain your reasoning.`;
2195
- const conversationHistory = [];
2196
- let attempt = 0;
2197
- while (attempt < maxRetries) {
2198
- logger.debug("LLM routing attempt", {
2199
- attempt: attempt + 1,
2200
- maxRetries,
2201
- conversationHistoryLength: conversationHistory.length
2202
- });
2203
- const messages = [
2204
- new SystemMessage4(systemPrompt),
2205
- new HumanMessage4(userPrompt),
2206
- ...conversationHistory
2207
- ];
2208
- const response = await config.model.invoke(messages);
2209
- if (response.tool_calls && response.tool_calls.length > 0) {
2210
- logger.info("LLM requested tool calls", {
2211
- toolCount: response.tool_calls.length,
2212
- toolNames: response.tool_calls.map((tc) => tc.name)
2213
- });
2214
- if (tools.length === 0) {
2215
- throw new Error("LLM requested tool calls but no tools are configured");
2216
- }
2217
- const toolResults = await executeTools(response.tool_calls, tools);
2218
- conversationHistory.push(
2219
- new AIMessage2({ content: response.content || "", tool_calls: response.tool_calls }),
2220
- ...toolResults
2221
- );
2222
- attempt++;
2223
- logger.debug("Retrying routing with tool results", { attempt });
2224
- continue;
2225
- }
2226
- logger.debug("Parsing routing decision from LLM response");
2227
- let decision;
2228
- if (response && typeof response === "object" && ("targetAgent" in response || "targetAgents" in response)) {
2229
- logger.debug("Response is structured output", {
2230
- hasTargetAgent: "targetAgent" in response,
2231
- hasTargetAgents: "targetAgents" in response
2232
- });
2233
- decision = response;
2234
- } else if (response.content) {
2235
- if (typeof response.content === "string") {
2236
- try {
2237
- decision = JSON.parse(response.content);
2238
- logger.debug("Parsed JSON from string response");
2239
- } catch (error) {
2240
- logger.error("Failed to parse routing decision", {
2241
- content: response.content,
2242
- error: error instanceof Error ? error.message : String(error)
2243
- });
2244
- throw new Error(`Failed to parse routing decision from LLM. Expected JSON but got: ${response.content}`);
2245
- }
2246
- } else if (typeof response.content === "object") {
2247
- logger.debug("Response content is already an object");
2248
- decision = response.content;
2249
- } else {
2250
- logger.error("Unexpected response content type", {
2251
- type: typeof response.content
2252
- });
2253
- throw new Error(`Unexpected response content type: ${typeof response.content}`);
2254
- }
2255
- } else {
2256
- logger.error("Unexpected response format", {
2257
- response: JSON.stringify(response)
2258
- });
2259
- throw new Error(`Unexpected response format: ${JSON.stringify(response)}`);
2260
- }
2261
- const result = {
2262
- targetAgent: decision.targetAgent,
2263
- targetAgents: decision.targetAgents,
2264
- reasoning: decision.reasoning,
2265
- confidence: decision.confidence,
2266
- strategy: "llm-based",
2267
- timestamp: Date.now()
2268
- };
2269
- logger.info("LLM routing decision made", {
2270
- targetAgent: result.targetAgent,
2271
- targetAgents: result.targetAgents,
2272
- isParallel: result.targetAgents && result.targetAgents.length > 1,
2273
- confidence: result.confidence,
2274
- reasoning: result.reasoning
2275
- });
2276
- return result;
2277
- }
2278
- logger.error("Max tool retries exceeded", { maxRetries });
2279
- throw new Error(`Max tool retries (${maxRetries}) exceeded without routing decision`);
2117
+ const messages = [
2118
+ new SystemMessage4(systemPrompt),
2119
+ new HumanMessage4(userPrompt)
2120
+ ];
2121
+ const decision = await config.model.invoke(messages);
2122
+ return {
2123
+ targetAgent: decision.targetAgent,
2124
+ targetAgents: decision.targetAgents,
2125
+ reasoning: decision.reasoning,
2126
+ confidence: decision.confidence,
2127
+ strategy: "llm-based",
2128
+ timestamp: Date.now()
2129
+ };
2280
2130
  }
2281
2131
  };
2282
2132
  var roundRobinRouting = {
2283
2133
  name: "round-robin",
2284
2134
  async route(state, config) {
2285
- logger.info("Starting round-robin routing", {
2286
- iteration: state.iteration
2287
- });
2288
2135
  const availableWorkers = Object.entries(state.workers).filter(([_, caps]) => caps.available).map(([id]) => id);
2289
- logger.debug("Available workers for round-robin", {
2290
- count: availableWorkers.length,
2291
- workers: availableWorkers
2292
- });
2293
2136
  if (availableWorkers.length === 0) {
2294
- logger.error("No available workers for round-robin routing");
2295
2137
  throw new Error("No available workers for round-robin routing");
2296
2138
  }
2297
2139
  const lastRoutingIndex = state.routingHistory.length % availableWorkers.length;
2298
2140
  const targetAgent = availableWorkers[lastRoutingIndex];
2299
- logger.info("Round-robin routing decision", {
2300
- targetAgent,
2301
- index: lastRoutingIndex + 1,
2302
- totalWorkers: availableWorkers.length
2303
- });
2304
2141
  return {
2305
2142
  targetAgent,
2306
2143
  targetAgents: null,
@@ -2314,15 +2151,8 @@ var roundRobinRouting = {
2314
2151
  var skillBasedRouting = {
2315
2152
  name: "skill-based",
2316
2153
  async route(state, config) {
2317
- logger.info("Starting skill-based routing", {
2318
- iteration: state.iteration
2319
- });
2320
2154
  const lastMessage = state.messages[state.messages.length - 1];
2321
2155
  const taskContent = (lastMessage?.content || state.input).toLowerCase();
2322
- logger.debug("Task content for skill matching", {
2323
- taskLength: taskContent.length,
2324
- taskPreview: taskContent.substring(0, 100)
2325
- });
2326
2156
  const workerScores = Object.entries(state.workers).filter(([_, caps]) => caps.available).map(([id, caps]) => {
2327
2157
  const skillMatches = caps.skills.filter(
2328
2158
  (skill) => taskContent.includes(skill.toLowerCase())
@@ -2333,20 +2163,11 @@ var skillBasedRouting = {
2333
2163
  const score = skillMatches * 2 + toolMatches;
2334
2164
  return { id, score, skills: caps.skills, tools: caps.tools };
2335
2165
  }).filter((w) => w.score > 0).sort((a, b) => b.score - a.score);
2336
- logger.debug("Worker skill scores", {
2337
- scoredWorkers: workerScores.map((w) => ({ id: w.id, score: w.score }))
2338
- });
2339
2166
  if (workerScores.length === 0) {
2340
- logger.warn("No skill matches found, using fallback");
2341
2167
  const firstAvailable = Object.entries(state.workers).find(([_, caps]) => caps.available);
2342
2168
  if (!firstAvailable) {
2343
- logger.error("No available workers for skill-based routing");
2344
2169
  throw new Error("No available workers for skill-based routing");
2345
2170
  }
2346
- logger.info("Skill-based routing fallback decision", {
2347
- targetAgent: firstAvailable[0],
2348
- confidence: 0.5
2349
- });
2350
2171
  return {
2351
2172
  targetAgent: firstAvailable[0],
2352
2173
  targetAgents: null,
@@ -2358,12 +2179,6 @@ var skillBasedRouting = {
2358
2179
  }
2359
2180
  const best = workerScores[0];
2360
2181
  const confidence = Math.min(best.score / 5, 1);
2361
- logger.info("Skill-based routing decision", {
2362
- targetAgent: best.id,
2363
- score: best.score,
2364
- confidence,
2365
- matchedSkills: best.skills
2366
- });
2367
2182
  return {
2368
2183
  targetAgent: best.id,
2369
2184
  targetAgents: null,
@@ -2377,26 +2192,13 @@ var skillBasedRouting = {
2377
2192
  var loadBalancedRouting = {
2378
2193
  name: "load-balanced",
2379
2194
  async route(state, config) {
2380
- logger.info("Starting load-balanced routing", {
2381
- iteration: state.iteration
2382
- });
2383
2195
  const availableWorkers = Object.entries(state.workers).filter(([_, caps]) => caps.available).map(([id, caps]) => ({ id, workload: caps.currentWorkload })).sort((a, b) => a.workload - b.workload);
2384
- logger.debug("Worker workloads", {
2385
- workers: availableWorkers.map((w) => ({ id: w.id, workload: w.workload }))
2386
- });
2387
2196
  if (availableWorkers.length === 0) {
2388
- logger.error("No available workers for load-balanced routing");
2389
2197
  throw new Error("No available workers for load-balanced routing");
2390
2198
  }
2391
2199
  const targetWorker = availableWorkers[0];
2392
2200
  const avgWorkload = availableWorkers.reduce((sum, w) => sum + w.workload, 0) / availableWorkers.length;
2393
2201
  const confidence = targetWorker.workload === 0 ? 1 : Math.max(0.5, 1 - targetWorker.workload / (avgWorkload * 2));
2394
- logger.info("Load-balanced routing decision", {
2395
- targetAgent: targetWorker.id,
2396
- workload: targetWorker.workload,
2397
- avgWorkload: avgWorkload.toFixed(1),
2398
- confidence
2399
- });
2400
2202
  return {
2401
2203
  targetAgent: targetWorker.id,
2402
2204
  targetAgents: null,
@@ -2410,24 +2212,13 @@ var loadBalancedRouting = {
2410
2212
  var ruleBasedRouting = {
2411
2213
  name: "rule-based",
2412
2214
  async route(state, config) {
2413
- logger.info("Starting rule-based routing", {
2414
- iteration: state.iteration
2415
- });
2416
2215
  if (!config.routingFn) {
2417
- logger.error("Rule-based routing requires a custom routing function");
2418
2216
  throw new Error("Rule-based routing requires a custom routing function");
2419
2217
  }
2420
- const decision = await config.routingFn(state);
2421
- logger.info("Rule-based routing decision", {
2422
- targetAgent: decision.targetAgent,
2423
- targetAgents: decision.targetAgents,
2424
- confidence: decision.confidence
2425
- });
2426
- return decision;
2218
+ return await config.routingFn(state);
2427
2219
  }
2428
2220
  };
2429
2221
  function getRoutingStrategy(name) {
2430
- logger.debug("Getting routing strategy", { name });
2431
2222
  switch (name) {
2432
2223
  case "llm-based":
2433
2224
  return llmBasedRouting;
@@ -2440,15 +2231,14 @@ function getRoutingStrategy(name) {
2440
2231
  case "rule-based":
2441
2232
  return ruleBasedRouting;
2442
2233
  default:
2443
- logger.error("Unknown routing strategy", { name });
2444
2234
  throw new Error(`Unknown routing strategy: ${name}`);
2445
2235
  }
2446
2236
  }
2447
2237
 
2448
2238
  // src/multi-agent/utils.ts
2449
- import { createLogger as createLogger3, LogLevel as LogLevel2 } from "@agentforge/core";
2450
- var logLevel2 = process.env.LOG_LEVEL?.toLowerCase() || LogLevel2.INFO;
2451
- var logger2 = createLogger3("multi-agent", { level: logLevel2 });
2239
+ import { createLogger as createLogger2, LogLevel } from "@agentforge/core";
2240
+ var logLevel = process.env.LOG_LEVEL?.toLowerCase() || LogLevel.INFO;
2241
+ var logger = createLogger2("multi-agent", { level: logLevel });
2452
2242
  function isReActAgent(obj) {
2453
2243
  return obj && typeof obj === "object" && typeof obj.invoke === "function" && typeof obj.stream === "function" && // Additional check to ensure it's not just any object with invoke/stream
2454
2244
  (obj.constructor?.name === "CompiledGraph" || obj.constructor?.name === "CompiledStateGraph");
@@ -2456,9 +2246,9 @@ function isReActAgent(obj) {
2456
2246
  function wrapReActAgent(workerId, agent, verbose = false) {
2457
2247
  return async (state, config) => {
2458
2248
  try {
2459
- logger2.debug("Wrapping ReAct agent execution", { workerId });
2249
+ logger.debug("Wrapping ReAct agent execution", { workerId });
2460
2250
  const task = state.messages[state.messages.length - 1]?.content || state.input;
2461
- logger2.debug("Extracted task", {
2251
+ logger.debug("Extracted task", {
2462
2252
  workerId,
2463
2253
  taskPreview: task.substring(0, 100) + (task.length > 100 ? "..." : "")
2464
2254
  });
@@ -2466,7 +2256,7 @@ function wrapReActAgent(workerId, agent, verbose = false) {
2466
2256
  (assignment) => assignment.workerId === workerId && !state.completedTasks.some((task2) => task2.assignmentId === assignment.id)
2467
2257
  );
2468
2258
  if (!currentAssignment) {
2469
- logger2.debug("No active assignment found", { workerId });
2259
+ logger.debug("No active assignment found", { workerId });
2470
2260
  return {};
2471
2261
  }
2472
2262
  const result = await agent.invoke(
@@ -2477,14 +2267,14 @@ function wrapReActAgent(workerId, agent, verbose = false) {
2477
2267
  // Pass through the config for checkpointing and interrupt support
2478
2268
  );
2479
2269
  const response = result.messages?.[result.messages.length - 1]?.content || "No response";
2480
- logger2.debug("Received response from ReAct agent", {
2270
+ logger.debug("Received response from ReAct agent", {
2481
2271
  workerId,
2482
2272
  responsePreview: response.substring(0, 100) + (response.length > 100 ? "..." : "")
2483
2273
  });
2484
2274
  const toolsUsed = result.actions?.map((action) => action.name).filter(Boolean) || [];
2485
2275
  const uniqueTools = [...new Set(toolsUsed)];
2486
2276
  if (uniqueTools.length > 0) {
2487
- logger2.debug("Tools used by ReAct agent", { workerId, tools: uniqueTools });
2277
+ logger.debug("Tools used by ReAct agent", { workerId, tools: uniqueTools });
2488
2278
  }
2489
2279
  const taskResult = {
2490
2280
  assignmentId: currentAssignment.id,
@@ -2503,7 +2293,7 @@ function wrapReActAgent(workerId, agent, verbose = false) {
2503
2293
  };
2504
2294
  } catch (error) {
2505
2295
  const errorMessage = handleNodeError(error, `react-agent:${workerId}`, false);
2506
- logger2.error("Error in ReAct agent execution", {
2296
+ logger.error("Error in ReAct agent execution", {
2507
2297
  workerId,
2508
2298
  error: errorMessage
2509
2299
  });
@@ -2535,9 +2325,9 @@ function wrapReActAgent(workerId, agent, verbose = false) {
2535
2325
 
2536
2326
  // src/multi-agent/nodes.ts
2537
2327
  import { HumanMessage as HumanMessage5, SystemMessage as SystemMessage5 } from "@langchain/core/messages";
2538
- import { toLangChainTools as toLangChainTools2, createLogger as createLogger4, LogLevel as LogLevel3 } from "@agentforge/core";
2539
- var logLevel3 = process.env.LOG_LEVEL?.toLowerCase() || LogLevel3.INFO;
2540
- var logger3 = createLogger4("multi-agent:nodes", { level: logLevel3 });
2328
+ import { toLangChainTools as toLangChainTools2, createLogger as createLogger3, LogLevel as LogLevel2 } from "@agentforge/core";
2329
+ var logLevel2 = process.env.LOG_LEVEL?.toLowerCase() || LogLevel2.INFO;
2330
+ var logger2 = createLogger3("multi-agent:nodes", { level: logLevel2 });
2541
2331
  var DEFAULT_AGGREGATOR_SYSTEM_PROMPT = `You are an aggregator agent responsible for combining results from multiple worker agents.
2542
2332
 
2543
2333
  Your job is to:
@@ -2555,19 +2345,19 @@ function createSupervisorNode(config) {
2555
2345
  } = config;
2556
2346
  return async (state) => {
2557
2347
  try {
2558
- logger3.info("Supervisor node executing", {
2348
+ logger2.info("Supervisor node executing", {
2559
2349
  iteration: state.iteration,
2560
2350
  maxIterations,
2561
2351
  activeAssignments: state.activeAssignments.length,
2562
2352
  completedTasks: state.completedTasks.length
2563
2353
  });
2564
- logger3.debug(`Routing iteration ${state.iteration}/${maxIterations}`);
2354
+ logger2.debug(`Routing iteration ${state.iteration}/${maxIterations}`);
2565
2355
  if (state.iteration >= maxIterations) {
2566
- logger3.warn("Max iterations reached", {
2356
+ logger2.warn("Max iterations reached", {
2567
2357
  iteration: state.iteration,
2568
2358
  maxIterations
2569
2359
  });
2570
- logger3.debug("Max iterations reached, moving to aggregation");
2360
+ logger2.debug("Max iterations reached, moving to aggregation");
2571
2361
  return {
2572
2362
  status: "aggregating",
2573
2363
  currentAgent: "aggregator"
@@ -2576,26 +2366,26 @@ function createSupervisorNode(config) {
2576
2366
  const allCompleted = state.activeAssignments.every(
2577
2367
  (assignment) => state.completedTasks.some((task2) => task2.assignmentId === assignment.id)
2578
2368
  );
2579
- logger3.debug("Checking task completion", {
2369
+ logger2.debug("Checking task completion", {
2580
2370
  activeAssignments: state.activeAssignments.length,
2581
2371
  completedTasks: state.completedTasks.length,
2582
2372
  allCompleted
2583
2373
  });
2584
2374
  if (allCompleted && state.activeAssignments.length > 0) {
2585
- logger3.info("All tasks completed, moving to aggregation", {
2375
+ logger2.info("All tasks completed, moving to aggregation", {
2586
2376
  completedCount: state.completedTasks.length
2587
2377
  });
2588
- logger3.debug("All tasks completed, moving to aggregation");
2378
+ logger2.debug("All tasks completed, moving to aggregation");
2589
2379
  return {
2590
2380
  status: "aggregating",
2591
2381
  currentAgent: "aggregator"
2592
2382
  };
2593
2383
  }
2594
- logger3.debug("Getting routing strategy", { strategy });
2384
+ logger2.debug("Getting routing strategy", { strategy });
2595
2385
  const routingImpl = getRoutingStrategy(strategy);
2596
2386
  const decision = await routingImpl.route(state, config);
2597
2387
  const targetAgents = decision.targetAgents && decision.targetAgents.length > 0 ? decision.targetAgents : decision.targetAgent ? [decision.targetAgent] : [];
2598
- logger3.debug("Target agents determined", {
2388
+ logger2.debug("Target agents determined", {
2599
2389
  targetAgents,
2600
2390
  isParallel: targetAgents.length > 1,
2601
2391
  decision: {
@@ -2604,17 +2394,17 @@ function createSupervisorNode(config) {
2604
2394
  }
2605
2395
  });
2606
2396
  if (targetAgents.length === 0) {
2607
- logger3.error("No target agents specified in routing decision");
2397
+ logger2.error("No target agents specified in routing decision");
2608
2398
  throw new Error("Routing decision must specify at least one target agent");
2609
2399
  }
2610
2400
  if (targetAgents.length === 1) {
2611
- logger3.info("Routing to single agent", {
2401
+ logger2.info("Routing to single agent", {
2612
2402
  targetAgent: targetAgents[0],
2613
2403
  reasoning: decision.reasoning,
2614
2404
  confidence: decision.confidence
2615
2405
  });
2616
2406
  } else {
2617
- logger3.info("Routing to multiple agents in parallel", {
2407
+ logger2.info("Routing to multiple agents in parallel", {
2618
2408
  targetAgents,
2619
2409
  count: targetAgents.length,
2620
2410
  reasoning: decision.reasoning,
@@ -2622,9 +2412,9 @@ function createSupervisorNode(config) {
2622
2412
  });
2623
2413
  }
2624
2414
  if (targetAgents.length === 1) {
2625
- logger3.debug(`Routing to ${targetAgents[0]}: ${decision.reasoning}`);
2415
+ logger2.debug(`Routing to ${targetAgents[0]}: ${decision.reasoning}`);
2626
2416
  } else {
2627
- logger3.debug(`Routing to ${targetAgents.length} agents in parallel [${targetAgents.join(", ")}]: ${decision.reasoning}`);
2417
+ logger2.debug(`Routing to ${targetAgents.length} agents in parallel [${targetAgents.join(", ")}]: ${decision.reasoning}`);
2628
2418
  }
2629
2419
  const task = state.messages[state.messages.length - 1]?.content || state.input;
2630
2420
  const assignments = targetAgents.map((workerId) => ({
@@ -2634,7 +2424,7 @@ function createSupervisorNode(config) {
2634
2424
  priority: 5,
2635
2425
  assignedAt: Date.now()
2636
2426
  }));
2637
- logger3.debug("Created task assignments", {
2427
+ logger2.debug("Created task assignments", {
2638
2428
  assignmentCount: assignments.length,
2639
2429
  assignments: assignments.map((a) => ({
2640
2430
  id: a.id,
@@ -2654,7 +2444,7 @@ function createSupervisorNode(config) {
2654
2444
  priority: assignment.priority
2655
2445
  }
2656
2446
  }));
2657
- logger3.info("Supervisor routing complete", {
2447
+ logger2.info("Supervisor routing complete", {
2658
2448
  currentAgent: targetAgents.join(","),
2659
2449
  status: "executing",
2660
2450
  assignmentCount: assignments.length,
@@ -2671,7 +2461,7 @@ function createSupervisorNode(config) {
2671
2461
  iteration: state.iteration + 1
2672
2462
  };
2673
2463
  } catch (error) {
2674
- logger3.error("Supervisor node error", {
2464
+ logger2.error("Supervisor node error", {
2675
2465
  error: error instanceof Error ? error.message : String(error),
2676
2466
  stack: error instanceof Error ? error.stack : void 0,
2677
2467
  iteration: state.iteration
@@ -2696,7 +2486,7 @@ function createWorkerNode(config) {
2696
2486
  } = config;
2697
2487
  return async (state, runConfig) => {
2698
2488
  try {
2699
- logger3.info("Worker node executing", {
2489
+ logger2.info("Worker node executing", {
2700
2490
  workerId: id,
2701
2491
  iteration: state.iteration,
2702
2492
  activeAssignments: state.activeAssignments.length
@@ -2705,39 +2495,39 @@ function createWorkerNode(config) {
2705
2495
  (assignment) => assignment.workerId === id && !state.completedTasks.some((task) => task.assignmentId === assignment.id)
2706
2496
  );
2707
2497
  if (!currentAssignment) {
2708
- logger3.debug("No active assignment found for worker", {
2498
+ logger2.debug("No active assignment found for worker", {
2709
2499
  workerId: id,
2710
2500
  totalActiveAssignments: state.activeAssignments.length,
2711
2501
  completedTasks: state.completedTasks.length
2712
2502
  });
2713
2503
  return {};
2714
2504
  }
2715
- logger3.info("Worker processing assignment", {
2505
+ logger2.info("Worker processing assignment", {
2716
2506
  workerId: id,
2717
2507
  assignmentId: currentAssignment.id,
2718
2508
  taskLength: currentAssignment.task.length,
2719
2509
  taskPreview: currentAssignment.task.substring(0, 100)
2720
2510
  });
2721
2511
  if (executeFn) {
2722
- logger3.debug("Using custom execution function", { workerId: id });
2512
+ logger2.debug("Using custom execution function", { workerId: id });
2723
2513
  return await executeFn(state, runConfig);
2724
2514
  }
2725
2515
  if (agent) {
2726
2516
  if (isReActAgent(agent)) {
2727
- logger3.debug("Using ReAct agent", { workerId: id });
2517
+ logger2.debug("Using ReAct agent", { workerId: id });
2728
2518
  const wrappedFn = wrapReActAgent(id, agent, verbose);
2729
2519
  return await wrappedFn(state, runConfig);
2730
2520
  } else {
2731
- logger3.warn("Agent provided but not a ReAct agent, falling back", { workerId: id });
2521
+ logger2.warn("Agent provided but not a ReAct agent, falling back", { workerId: id });
2732
2522
  }
2733
2523
  }
2734
2524
  if (!model) {
2735
- logger3.error("Worker missing required configuration", { workerId: id });
2525
+ logger2.error("Worker missing required configuration", { workerId: id });
2736
2526
  throw new Error(
2737
2527
  `Worker ${id} requires either a model, an agent, or a custom execution function. Provide one of: config.model, config.agent, or config.executeFn`
2738
2528
  );
2739
2529
  }
2740
- logger3.debug("Using default LLM execution", {
2530
+ logger2.debug("Using default LLM execution", {
2741
2531
  workerId: id,
2742
2532
  hasTools: tools.length > 0,
2743
2533
  toolCount: tools.length
@@ -2753,7 +2543,7 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
2753
2543
  ];
2754
2544
  let modelToUse = model;
2755
2545
  if (tools.length > 0 && model.bindTools) {
2756
- logger3.debug("Binding tools to model", {
2546
+ logger2.debug("Binding tools to model", {
2757
2547
  workerId: id,
2758
2548
  toolCount: tools.length,
2759
2549
  toolNames: tools.map((t) => t.metadata.name)
@@ -2761,10 +2551,10 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
2761
2551
  const langchainTools = toLangChainTools2(tools);
2762
2552
  modelToUse = model.bindTools(langchainTools);
2763
2553
  }
2764
- logger3.debug("Invoking LLM", { workerId: id });
2554
+ logger2.debug("Invoking LLM", { workerId: id });
2765
2555
  const response = await modelToUse.invoke(messages);
2766
2556
  const result = typeof response.content === "string" ? response.content : JSON.stringify(response.content);
2767
- logger3.info("Worker task completed", {
2557
+ logger2.info("Worker task completed", {
2768
2558
  workerId: id,
2769
2559
  assignmentId: currentAssignment.id,
2770
2560
  resultLength: result.length,
@@ -2799,7 +2589,7 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
2799
2589
  currentWorkload: Math.max(0, capabilities.currentWorkload - 1)
2800
2590
  }
2801
2591
  };
2802
- logger3.debug("Worker state update", {
2592
+ logger2.debug("Worker state update", {
2803
2593
  workerId: id,
2804
2594
  newWorkload: updatedWorkers[id].currentWorkload
2805
2595
  });
@@ -2810,7 +2600,7 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
2810
2600
  };
2811
2601
  } catch (error) {
2812
2602
  const errorMessage = handleNodeError(error, `worker:${id}`, false);
2813
- logger3.error("Worker node error", {
2603
+ logger2.error("Worker node error", {
2814
2604
  workerId: id,
2815
2605
  error: errorMessage
2816
2606
  });
@@ -2818,7 +2608,7 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
2818
2608
  (assignment) => assignment.workerId === id
2819
2609
  );
2820
2610
  if (currentAssignment) {
2821
- logger3.warn("Creating error result for assignment", {
2611
+ logger2.warn("Creating error result for assignment", {
2822
2612
  workerId: id,
2823
2613
  assignmentId: currentAssignment.id
2824
2614
  });
@@ -2836,7 +2626,7 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
2836
2626
  status: "routing"
2837
2627
  };
2838
2628
  }
2839
- logger3.error("No assignment found for error handling", { workerId: id });
2629
+ logger2.error("No assignment found for error handling", { workerId: id });
2840
2630
  return {
2841
2631
  status: "failed",
2842
2632
  error: errorMessage
@@ -2853,16 +2643,16 @@ function createAggregatorNode(config = {}) {
2853
2643
  } = config;
2854
2644
  return async (state) => {
2855
2645
  try {
2856
- logger3.info("Aggregator node executing", {
2646
+ logger2.info("Aggregator node executing", {
2857
2647
  completedTasks: state.completedTasks.length,
2858
2648
  successfulTasks: state.completedTasks.filter((t) => t.success).length,
2859
2649
  failedTasks: state.completedTasks.filter((t) => !t.success).length
2860
2650
  });
2861
- logger3.debug("Combining results from workers");
2651
+ logger2.debug("Combining results from workers");
2862
2652
  if (aggregateFn) {
2863
- logger3.debug("Using custom aggregation function");
2653
+ logger2.debug("Using custom aggregation function");
2864
2654
  const response2 = await aggregateFn(state);
2865
- logger3.info("Custom aggregation complete", {
2655
+ logger2.info("Custom aggregation complete", {
2866
2656
  responseLength: response2.length
2867
2657
  });
2868
2658
  return {
@@ -2871,16 +2661,16 @@ function createAggregatorNode(config = {}) {
2871
2661
  };
2872
2662
  }
2873
2663
  if (state.completedTasks.length === 0) {
2874
- logger3.warn("No completed tasks to aggregate");
2664
+ logger2.warn("No completed tasks to aggregate");
2875
2665
  return {
2876
2666
  response: "No tasks were completed.",
2877
2667
  status: "completed"
2878
2668
  };
2879
2669
  }
2880
2670
  if (!model) {
2881
- logger3.debug("No model provided, concatenating results");
2671
+ logger2.debug("No model provided, concatenating results");
2882
2672
  const combinedResults = state.completedTasks.filter((task) => task.success).map((task) => task.result).join("\n\n");
2883
- logger3.info("Simple concatenation complete", {
2673
+ logger2.info("Simple concatenation complete", {
2884
2674
  resultLength: combinedResults.length
2885
2675
  });
2886
2676
  return {
@@ -2888,7 +2678,7 @@ function createAggregatorNode(config = {}) {
2888
2678
  status: "completed"
2889
2679
  };
2890
2680
  }
2891
- logger3.debug("Using LLM for intelligent aggregation", {
2681
+ logger2.debug("Using LLM for intelligent aggregation", {
2892
2682
  taskCount: state.completedTasks.length
2893
2683
  });
2894
2684
  const taskResults = state.completedTasks.map((task, idx) => {
@@ -2907,20 +2697,20 @@ Please synthesize these results into a comprehensive response that addresses the
2907
2697
  new SystemMessage5(systemPrompt),
2908
2698
  new HumanMessage5(userPrompt)
2909
2699
  ];
2910
- logger3.debug("Invoking aggregation LLM");
2700
+ logger2.debug("Invoking aggregation LLM");
2911
2701
  const response = await model.invoke(messages);
2912
2702
  const aggregatedResponse = typeof response.content === "string" ? response.content : JSON.stringify(response.content);
2913
- logger3.info("Aggregation complete", {
2703
+ logger2.info("Aggregation complete", {
2914
2704
  responseLength: aggregatedResponse.length,
2915
2705
  responsePreview: aggregatedResponse.substring(0, 100)
2916
2706
  });
2917
- logger3.debug("Aggregation complete");
2707
+ logger2.debug("Aggregation complete");
2918
2708
  return {
2919
2709
  response: aggregatedResponse,
2920
2710
  status: "completed"
2921
2711
  };
2922
2712
  } catch (error) {
2923
- logger3.error("Aggregator node error", {
2713
+ logger2.error("Aggregator node error", {
2924
2714
  error: error instanceof Error ? error.message : String(error),
2925
2715
  stack: error instanceof Error ? error.stack : void 0,
2926
2716
  completedTasks: state.completedTasks.length
@@ -2935,9 +2725,9 @@ Please synthesize these results into a comprehensive response that addresses the
2935
2725
 
2936
2726
  // src/multi-agent/agent.ts
2937
2727
  import { StateGraph as StateGraph4, END as END4 } from "@langchain/langgraph";
2938
- import { toLangChainTools as toLangChainTools3, createLogger as createLogger5, LogLevel as LogLevel4 } from "@agentforge/core";
2939
- var logLevel4 = process.env.LOG_LEVEL?.toLowerCase() || LogLevel4.INFO;
2940
- var logger4 = createLogger5("multi-agent:system", { level: logLevel4 });
2728
+ import { createLogger as createLogger4, LogLevel as LogLevel3 } from "@agentforge/core";
2729
+ var logLevel3 = process.env.LOG_LEVEL?.toLowerCase() || LogLevel3.INFO;
2730
+ var logger3 = createLogger4("multi-agent:system", { level: logLevel3 });
2941
2731
  function createMultiAgentSystem(config) {
2942
2732
  const {
2943
2733
  supervisor,
@@ -2954,10 +2744,6 @@ function createMultiAgentSystem(config) {
2954
2744
  if (supervisor.strategy === "llm-based") {
2955
2745
  configuredModel = configuredModel.withStructuredOutput(RoutingDecisionSchema);
2956
2746
  }
2957
- if (supervisor.tools && supervisor.tools.length > 0) {
2958
- const langchainTools = toLangChainTools3(supervisor.tools);
2959
- configuredModel = configuredModel.bindTools(langchainTools);
2960
- }
2961
2747
  supervisorConfig.model = configuredModel;
2962
2748
  }
2963
2749
  const supervisorNode = createSupervisorNode(supervisorConfig);
@@ -2979,46 +2765,46 @@ function createMultiAgentSystem(config) {
2979
2765
  });
2980
2766
  workflow.addNode("aggregator", aggregatorNode);
2981
2767
  const supervisorRouter = (state) => {
2982
- logger4.debug("Supervisor router executing", {
2768
+ logger3.debug("Supervisor router executing", {
2983
2769
  status: state.status,
2984
2770
  currentAgent: state.currentAgent,
2985
2771
  iteration: state.iteration
2986
2772
  });
2987
2773
  if (state.status === "completed" || state.status === "failed") {
2988
- logger4.info("Supervisor router: ending workflow", { status: state.status });
2774
+ logger3.info("Supervisor router: ending workflow", { status: state.status });
2989
2775
  return END4;
2990
2776
  }
2991
2777
  if (state.status === "aggregating") {
2992
- logger4.info("Supervisor router: routing to aggregator");
2778
+ logger3.info("Supervisor router: routing to aggregator");
2993
2779
  return "aggregator";
2994
2780
  }
2995
2781
  if (state.currentAgent && state.currentAgent !== "supervisor") {
2996
2782
  if (state.currentAgent.includes(",")) {
2997
2783
  const agents = state.currentAgent.split(",").map((a) => a.trim());
2998
- logger4.info("Supervisor router: parallel routing", {
2784
+ logger3.info("Supervisor router: parallel routing", {
2999
2785
  agents,
3000
2786
  count: agents.length
3001
2787
  });
3002
2788
  return agents;
3003
2789
  }
3004
- logger4.info("Supervisor router: single agent routing", {
2790
+ logger3.info("Supervisor router: single agent routing", {
3005
2791
  targetAgent: state.currentAgent
3006
2792
  });
3007
2793
  return state.currentAgent;
3008
2794
  }
3009
- logger4.debug("Supervisor router: staying at supervisor");
2795
+ logger3.debug("Supervisor router: staying at supervisor");
3010
2796
  return "supervisor";
3011
2797
  };
3012
2798
  const workerRouter = (state) => {
3013
- logger4.debug("Worker router executing", {
2799
+ logger3.debug("Worker router executing", {
3014
2800
  iteration: state.iteration,
3015
2801
  completedTasks: state.completedTasks.length
3016
2802
  });
3017
- logger4.debug("Worker router: returning to supervisor");
2803
+ logger3.debug("Worker router: returning to supervisor");
3018
2804
  return "supervisor";
3019
2805
  };
3020
2806
  const aggregatorRouter = (state) => {
3021
- logger4.info("Aggregator router: ending workflow", {
2807
+ logger3.info("Aggregator router: ending workflow", {
3022
2808
  completedTasks: state.completedTasks.length,
3023
2809
  status: state.status
3024
2810
  });