@agentforge/patterns 0.7.0 → 0.8.1

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 CHANGED
@@ -283,8 +283,8 @@ function generateToolCallCacheKey(toolName, args) {
283
283
  return `${toolName}:${sortedArgs}`;
284
284
  }
285
285
  function createPatternLogger(name, defaultLevel = "info") {
286
- const logLevel5 = process.env.LOG_LEVEL?.toLowerCase() || defaultLevel;
287
- return (0, import_core2.createLogger)(name, { level: logLevel5 });
286
+ const logLevel4 = process.env.LOG_LEVEL?.toLowerCase() || defaultLevel;
287
+ return (0, import_core2.createLogger)(name, { level: logLevel4 });
288
288
  }
289
289
  function calculateDeduplicationSavings(duplicatesSkipped, toolsExecuted) {
290
290
  if (duplicatesSkipped === 0) {
@@ -604,7 +604,8 @@ function createReActAgent(config, options) {
604
604
  return ACTION_NODE;
605
605
  };
606
606
  const workflow = new import_langgraph.StateGraph(ReActState).addNode(REASONING_NODE, reasoningNode).addNode(ACTION_NODE, actionNode).addNode(OBSERVATION_NODE, observationNode).addEdge("__start__", REASONING_NODE).addConditionalEdges(REASONING_NODE, shouldContinue).addEdge(ACTION_NODE, OBSERVATION_NODE).addEdge(OBSERVATION_NODE, REASONING_NODE);
607
- return workflow.compile(checkpointer ? { checkpointer } : void 0);
607
+ const checkpointerConfig = checkpointer === true ? { checkpointer: true } : checkpointer ? { checkpointer } : void 0;
608
+ return workflow.compile(checkpointerConfig);
608
609
  }
609
610
 
610
611
  // src/react/builder.ts
@@ -689,6 +690,43 @@ var ReActAgentBuilder = class {
689
690
  this.options.nodeNames = nodeNames;
690
691
  return this;
691
692
  }
693
+ /**
694
+ * Set the checkpointer for state persistence (optional)
695
+ *
696
+ * Can be:
697
+ * - A BaseCheckpointSaver instance (e.g., MemorySaver) for standalone agents
698
+ * - `true` to use the parent graph's checkpointer with a separate namespace (for nested graphs)
699
+ *
700
+ * Required for human-in-the-loop workflows (askHuman tool) and conversation continuity.
701
+ *
702
+ * @param checkpointer - Checkpointer instance or `true` for nested graphs
703
+ *
704
+ * @example
705
+ * Standalone agent with its own checkpointer:
706
+ * ```typescript
707
+ * import { MemorySaver } from '@langchain/langgraph';
708
+ *
709
+ * const agent = new ReActAgentBuilder()
710
+ * .withModel(model)
711
+ * .withTools(tools)
712
+ * .withCheckpointer(new MemorySaver())
713
+ * .build();
714
+ * ```
715
+ *
716
+ * @example
717
+ * Nested agent using parent's checkpointer (for multi-agent systems):
718
+ * ```typescript
719
+ * const agent = new ReActAgentBuilder()
720
+ * .withModel(model)
721
+ * .withTools(tools)
722
+ * .withCheckpointer(true) // Use parent's checkpointer with separate namespace
723
+ * .build();
724
+ * ```
725
+ */
726
+ withCheckpointer(checkpointer) {
727
+ this.config.checkpointer = checkpointer;
728
+ return this;
729
+ }
692
730
  /**
693
731
  * Build the ReAct agent
694
732
  *
@@ -708,7 +746,8 @@ var ReActAgentBuilder = class {
708
746
  systemPrompt: this.config.systemPrompt || DEFAULT_REACT_SYSTEM_PROMPT,
709
747
  maxIterations: this.config.maxIterations ?? 10,
710
748
  returnIntermediateSteps: this.config.returnIntermediateSteps ?? false,
711
- stopCondition: this.config.stopCondition
749
+ stopCondition: this.config.stopCondition,
750
+ checkpointer: this.config.checkpointer
712
751
  };
713
752
  return createReActAgent(finalConfig, this.options);
714
753
  }
@@ -2164,66 +2203,6 @@ var MultiAgentState = (0, import_core7.createStateAnnotation)(MultiAgentStateCon
2164
2203
 
2165
2204
  // src/multi-agent/routing.ts
2166
2205
  var import_messages4 = require("@langchain/core/messages");
2167
- var import_core8 = require("@agentforge/core");
2168
- var logLevel = process.env.LOG_LEVEL?.toLowerCase() || import_core8.LogLevel.INFO;
2169
- var logger = (0, import_core8.createLogger)("multi-agent:routing", { level: logLevel });
2170
- async function executeTools(toolCalls, tools) {
2171
- const results = [];
2172
- logger.debug("Executing tools", {
2173
- toolCallCount: toolCalls.length,
2174
- toolNames: toolCalls.map((tc) => tc.name)
2175
- });
2176
- for (const toolCall of toolCalls) {
2177
- const tool = tools.find((t) => t.metadata.name === toolCall.name);
2178
- if (!tool) {
2179
- logger.warn("Tool not found", {
2180
- toolName: toolCall.name,
2181
- availableTools: tools.map((t) => t.metadata.name)
2182
- });
2183
- results.push(new import_messages4.ToolMessage({
2184
- content: `Error: Tool '${toolCall.name}' not found`,
2185
- tool_call_id: toolCall.id
2186
- }));
2187
- continue;
2188
- }
2189
- try {
2190
- logger.debug("Executing tool", {
2191
- toolName: toolCall.name,
2192
- args: toolCall.args
2193
- });
2194
- const result = await tool.execute(toolCall.args);
2195
- const content = typeof result === "string" ? result : JSON.stringify(result);
2196
- logger.debug("Tool execution successful", {
2197
- toolName: toolCall.name,
2198
- resultLength: content.length
2199
- });
2200
- results.push(new import_messages4.ToolMessage({
2201
- content,
2202
- tool_call_id: toolCall.id
2203
- }));
2204
- } catch (error) {
2205
- logger.error("Tool execution failed", {
2206
- toolName: toolCall.name,
2207
- error: error.message
2208
- });
2209
- results.push(new import_messages4.ToolMessage({
2210
- content: `Error executing tool: ${error.message}`,
2211
- tool_call_id: toolCall.id
2212
- }));
2213
- }
2214
- }
2215
- logger.debug("Tool execution complete", {
2216
- successCount: results.filter((r) => {
2217
- const content = typeof r.content === "string" ? r.content : JSON.stringify(r.content);
2218
- return !content.startsWith("Error");
2219
- }).length,
2220
- errorCount: results.filter((r) => {
2221
- const content = typeof r.content === "string" ? r.content : JSON.stringify(r.content);
2222
- return content.startsWith("Error");
2223
- }).length
2224
- });
2225
- return results;
2226
- }
2227
2206
  var DEFAULT_SUPERVISOR_SYSTEM_PROMPT = `You are a supervisor agent responsible for routing tasks to specialized worker agents.
2228
2207
 
2229
2208
  Your job is to:
@@ -2259,151 +2238,48 @@ Choose parallel routing when the task benefits from multiple perspectives or dat
2259
2238
  var llmBasedRouting = {
2260
2239
  name: "llm-based",
2261
2240
  async route(state, config) {
2262
- logger.info("Starting LLM-based routing", {
2263
- iteration: state.iteration,
2264
- availableWorkers: Object.keys(state.workers).length
2265
- });
2266
2241
  if (!config.model) {
2267
2242
  throw new Error("LLM-based routing requires a model to be configured");
2268
2243
  }
2269
2244
  const systemPrompt = config.systemPrompt || DEFAULT_SUPERVISOR_SYSTEM_PROMPT;
2270
- const maxRetries = config.maxToolRetries || 3;
2271
- const tools = config.tools || [];
2272
2245
  const workerInfo = Object.entries(state.workers).map(([id, caps]) => {
2273
2246
  const skills = caps.skills.join(", ");
2274
- const tools2 = caps.tools.join(", ");
2247
+ const tools = caps.tools.join(", ");
2275
2248
  const available = caps.available ? "available" : "busy";
2276
- return `- ${id}: Skills: [${skills}], Tools: [${tools2}], Status: ${available}, Workload: ${caps.currentWorkload}`;
2249
+ return `- ${id}: Skills: [${skills}], Tools: [${tools}], Status: ${available}, Workload: ${caps.currentWorkload}`;
2277
2250
  }).join("\n");
2278
- logger.debug("Worker capabilities", {
2279
- workers: Object.entries(state.workers).map(([id, caps]) => ({
2280
- id,
2281
- skills: caps.skills,
2282
- available: caps.available,
2283
- workload: caps.currentWorkload
2284
- }))
2285
- });
2286
2251
  const lastMessage = state.messages[state.messages.length - 1];
2287
2252
  const taskContext = lastMessage?.content || state.input;
2288
- logger.debug("Task context", {
2289
- taskLength: taskContext.length,
2290
- taskPreview: taskContext.substring(0, 100)
2291
- });
2292
2253
  const userPrompt = `Current task: ${taskContext}
2293
2254
 
2294
2255
  Available workers:
2295
2256
  ${workerInfo}
2296
2257
 
2297
2258
  Select the best worker(s) for this task and explain your reasoning.`;
2298
- const conversationHistory = [];
2299
- let attempt = 0;
2300
- while (attempt < maxRetries) {
2301
- logger.debug("LLM routing attempt", {
2302
- attempt: attempt + 1,
2303
- maxRetries,
2304
- conversationHistoryLength: conversationHistory.length
2305
- });
2306
- const messages = [
2307
- new import_messages4.SystemMessage(systemPrompt),
2308
- new import_messages4.HumanMessage(userPrompt),
2309
- ...conversationHistory
2310
- ];
2311
- const response = await config.model.invoke(messages);
2312
- if (response.tool_calls && response.tool_calls.length > 0) {
2313
- logger.info("LLM requested tool calls", {
2314
- toolCount: response.tool_calls.length,
2315
- toolNames: response.tool_calls.map((tc) => tc.name)
2316
- });
2317
- if (tools.length === 0) {
2318
- throw new Error("LLM requested tool calls but no tools are configured");
2319
- }
2320
- const toolResults = await executeTools(response.tool_calls, tools);
2321
- conversationHistory.push(
2322
- new import_messages4.AIMessage({ content: response.content || "", tool_calls: response.tool_calls }),
2323
- ...toolResults
2324
- );
2325
- attempt++;
2326
- logger.debug("Retrying routing with tool results", { attempt });
2327
- continue;
2328
- }
2329
- logger.debug("Parsing routing decision from LLM response");
2330
- let decision;
2331
- if (response && typeof response === "object" && ("targetAgent" in response || "targetAgents" in response)) {
2332
- logger.debug("Response is structured output", {
2333
- hasTargetAgent: "targetAgent" in response,
2334
- hasTargetAgents: "targetAgents" in response
2335
- });
2336
- decision = response;
2337
- } else if (response.content) {
2338
- if (typeof response.content === "string") {
2339
- try {
2340
- decision = JSON.parse(response.content);
2341
- logger.debug("Parsed JSON from string response");
2342
- } catch (error) {
2343
- logger.error("Failed to parse routing decision", {
2344
- content: response.content,
2345
- error: error instanceof Error ? error.message : String(error)
2346
- });
2347
- throw new Error(`Failed to parse routing decision from LLM. Expected JSON but got: ${response.content}`);
2348
- }
2349
- } else if (typeof response.content === "object") {
2350
- logger.debug("Response content is already an object");
2351
- decision = response.content;
2352
- } else {
2353
- logger.error("Unexpected response content type", {
2354
- type: typeof response.content
2355
- });
2356
- throw new Error(`Unexpected response content type: ${typeof response.content}`);
2357
- }
2358
- } else {
2359
- logger.error("Unexpected response format", {
2360
- response: JSON.stringify(response)
2361
- });
2362
- throw new Error(`Unexpected response format: ${JSON.stringify(response)}`);
2363
- }
2364
- const result = {
2365
- targetAgent: decision.targetAgent,
2366
- targetAgents: decision.targetAgents,
2367
- reasoning: decision.reasoning,
2368
- confidence: decision.confidence,
2369
- strategy: "llm-based",
2370
- timestamp: Date.now()
2371
- };
2372
- logger.info("LLM routing decision made", {
2373
- targetAgent: result.targetAgent,
2374
- targetAgents: result.targetAgents,
2375
- isParallel: result.targetAgents && result.targetAgents.length > 1,
2376
- confidence: result.confidence,
2377
- reasoning: result.reasoning
2378
- });
2379
- return result;
2380
- }
2381
- logger.error("Max tool retries exceeded", { maxRetries });
2382
- throw new Error(`Max tool retries (${maxRetries}) exceeded without routing decision`);
2259
+ const messages = [
2260
+ new import_messages4.SystemMessage(systemPrompt),
2261
+ new import_messages4.HumanMessage(userPrompt)
2262
+ ];
2263
+ const decision = await config.model.invoke(messages);
2264
+ return {
2265
+ targetAgent: decision.targetAgent,
2266
+ targetAgents: decision.targetAgents,
2267
+ reasoning: decision.reasoning,
2268
+ confidence: decision.confidence,
2269
+ strategy: "llm-based",
2270
+ timestamp: Date.now()
2271
+ };
2383
2272
  }
2384
2273
  };
2385
2274
  var roundRobinRouting = {
2386
2275
  name: "round-robin",
2387
2276
  async route(state, config) {
2388
- logger.info("Starting round-robin routing", {
2389
- iteration: state.iteration
2390
- });
2391
2277
  const availableWorkers = Object.entries(state.workers).filter(([_, caps]) => caps.available).map(([id]) => id);
2392
- logger.debug("Available workers for round-robin", {
2393
- count: availableWorkers.length,
2394
- workers: availableWorkers
2395
- });
2396
2278
  if (availableWorkers.length === 0) {
2397
- logger.error("No available workers for round-robin routing");
2398
2279
  throw new Error("No available workers for round-robin routing");
2399
2280
  }
2400
2281
  const lastRoutingIndex = state.routingHistory.length % availableWorkers.length;
2401
2282
  const targetAgent = availableWorkers[lastRoutingIndex];
2402
- logger.info("Round-robin routing decision", {
2403
- targetAgent,
2404
- index: lastRoutingIndex + 1,
2405
- totalWorkers: availableWorkers.length
2406
- });
2407
2283
  return {
2408
2284
  targetAgent,
2409
2285
  targetAgents: null,
@@ -2417,15 +2293,8 @@ var roundRobinRouting = {
2417
2293
  var skillBasedRouting = {
2418
2294
  name: "skill-based",
2419
2295
  async route(state, config) {
2420
- logger.info("Starting skill-based routing", {
2421
- iteration: state.iteration
2422
- });
2423
2296
  const lastMessage = state.messages[state.messages.length - 1];
2424
2297
  const taskContent = (lastMessage?.content || state.input).toLowerCase();
2425
- logger.debug("Task content for skill matching", {
2426
- taskLength: taskContent.length,
2427
- taskPreview: taskContent.substring(0, 100)
2428
- });
2429
2298
  const workerScores = Object.entries(state.workers).filter(([_, caps]) => caps.available).map(([id, caps]) => {
2430
2299
  const skillMatches = caps.skills.filter(
2431
2300
  (skill) => taskContent.includes(skill.toLowerCase())
@@ -2436,20 +2305,11 @@ var skillBasedRouting = {
2436
2305
  const score = skillMatches * 2 + toolMatches;
2437
2306
  return { id, score, skills: caps.skills, tools: caps.tools };
2438
2307
  }).filter((w) => w.score > 0).sort((a, b) => b.score - a.score);
2439
- logger.debug("Worker skill scores", {
2440
- scoredWorkers: workerScores.map((w) => ({ id: w.id, score: w.score }))
2441
- });
2442
2308
  if (workerScores.length === 0) {
2443
- logger.warn("No skill matches found, using fallback");
2444
2309
  const firstAvailable = Object.entries(state.workers).find(([_, caps]) => caps.available);
2445
2310
  if (!firstAvailable) {
2446
- logger.error("No available workers for skill-based routing");
2447
2311
  throw new Error("No available workers for skill-based routing");
2448
2312
  }
2449
- logger.info("Skill-based routing fallback decision", {
2450
- targetAgent: firstAvailable[0],
2451
- confidence: 0.5
2452
- });
2453
2313
  return {
2454
2314
  targetAgent: firstAvailable[0],
2455
2315
  targetAgents: null,
@@ -2461,12 +2321,6 @@ var skillBasedRouting = {
2461
2321
  }
2462
2322
  const best = workerScores[0];
2463
2323
  const confidence = Math.min(best.score / 5, 1);
2464
- logger.info("Skill-based routing decision", {
2465
- targetAgent: best.id,
2466
- score: best.score,
2467
- confidence,
2468
- matchedSkills: best.skills
2469
- });
2470
2324
  return {
2471
2325
  targetAgent: best.id,
2472
2326
  targetAgents: null,
@@ -2480,26 +2334,13 @@ var skillBasedRouting = {
2480
2334
  var loadBalancedRouting = {
2481
2335
  name: "load-balanced",
2482
2336
  async route(state, config) {
2483
- logger.info("Starting load-balanced routing", {
2484
- iteration: state.iteration
2485
- });
2486
2337
  const availableWorkers = Object.entries(state.workers).filter(([_, caps]) => caps.available).map(([id, caps]) => ({ id, workload: caps.currentWorkload })).sort((a, b) => a.workload - b.workload);
2487
- logger.debug("Worker workloads", {
2488
- workers: availableWorkers.map((w) => ({ id: w.id, workload: w.workload }))
2489
- });
2490
2338
  if (availableWorkers.length === 0) {
2491
- logger.error("No available workers for load-balanced routing");
2492
2339
  throw new Error("No available workers for load-balanced routing");
2493
2340
  }
2494
2341
  const targetWorker = availableWorkers[0];
2495
2342
  const avgWorkload = availableWorkers.reduce((sum, w) => sum + w.workload, 0) / availableWorkers.length;
2496
2343
  const confidence = targetWorker.workload === 0 ? 1 : Math.max(0.5, 1 - targetWorker.workload / (avgWorkload * 2));
2497
- logger.info("Load-balanced routing decision", {
2498
- targetAgent: targetWorker.id,
2499
- workload: targetWorker.workload,
2500
- avgWorkload: avgWorkload.toFixed(1),
2501
- confidence
2502
- });
2503
2344
  return {
2504
2345
  targetAgent: targetWorker.id,
2505
2346
  targetAgents: null,
@@ -2513,24 +2354,13 @@ var loadBalancedRouting = {
2513
2354
  var ruleBasedRouting = {
2514
2355
  name: "rule-based",
2515
2356
  async route(state, config) {
2516
- logger.info("Starting rule-based routing", {
2517
- iteration: state.iteration
2518
- });
2519
2357
  if (!config.routingFn) {
2520
- logger.error("Rule-based routing requires a custom routing function");
2521
2358
  throw new Error("Rule-based routing requires a custom routing function");
2522
2359
  }
2523
- const decision = await config.routingFn(state);
2524
- logger.info("Rule-based routing decision", {
2525
- targetAgent: decision.targetAgent,
2526
- targetAgents: decision.targetAgents,
2527
- confidence: decision.confidence
2528
- });
2529
- return decision;
2360
+ return await config.routingFn(state);
2530
2361
  }
2531
2362
  };
2532
2363
  function getRoutingStrategy(name) {
2533
- logger.debug("Getting routing strategy", { name });
2534
2364
  switch (name) {
2535
2365
  case "llm-based":
2536
2366
  return llmBasedRouting;
@@ -2543,15 +2373,14 @@ function getRoutingStrategy(name) {
2543
2373
  case "rule-based":
2544
2374
  return ruleBasedRouting;
2545
2375
  default:
2546
- logger.error("Unknown routing strategy", { name });
2547
2376
  throw new Error(`Unknown routing strategy: ${name}`);
2548
2377
  }
2549
2378
  }
2550
2379
 
2551
2380
  // src/multi-agent/utils.ts
2552
- var import_core9 = require("@agentforge/core");
2553
- var logLevel2 = process.env.LOG_LEVEL?.toLowerCase() || import_core9.LogLevel.INFO;
2554
- var logger2 = (0, import_core9.createLogger)("multi-agent", { level: logLevel2 });
2381
+ var import_core8 = require("@agentforge/core");
2382
+ var logLevel = process.env.LOG_LEVEL?.toLowerCase() || import_core8.LogLevel.INFO;
2383
+ var logger = (0, import_core8.createLogger)("multi-agent", { level: logLevel });
2555
2384
  function isReActAgent(obj) {
2556
2385
  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
2557
2386
  (obj.constructor?.name === "CompiledGraph" || obj.constructor?.name === "CompiledStateGraph");
@@ -2559,9 +2388,9 @@ function isReActAgent(obj) {
2559
2388
  function wrapReActAgent(workerId, agent, verbose = false) {
2560
2389
  return async (state, config) => {
2561
2390
  try {
2562
- logger2.debug("Wrapping ReAct agent execution", { workerId });
2391
+ logger.debug("Wrapping ReAct agent execution", { workerId });
2563
2392
  const task = state.messages[state.messages.length - 1]?.content || state.input;
2564
- logger2.debug("Extracted task", {
2393
+ logger.debug("Extracted task", {
2565
2394
  workerId,
2566
2395
  taskPreview: task.substring(0, 100) + (task.length > 100 ? "..." : "")
2567
2396
  });
@@ -2569,25 +2398,39 @@ function wrapReActAgent(workerId, agent, verbose = false) {
2569
2398
  (assignment) => assignment.workerId === workerId && !state.completedTasks.some((task2) => task2.assignmentId === assignment.id)
2570
2399
  );
2571
2400
  if (!currentAssignment) {
2572
- logger2.debug("No active assignment found", { workerId });
2401
+ logger.debug("No active assignment found", { workerId });
2573
2402
  return {};
2574
2403
  }
2404
+ const workerThreadId = config?.configurable?.thread_id ? `${config.configurable.thread_id}:worker:${workerId}` : void 0;
2405
+ const workerConfig = workerThreadId ? {
2406
+ ...config,
2407
+ configurable: {
2408
+ ...config.configurable,
2409
+ thread_id: workerThreadId
2410
+ }
2411
+ } : config;
2412
+ logger.debug("Invoking ReAct agent with worker-specific config", {
2413
+ workerId,
2414
+ parentThreadId: config?.configurable?.thread_id,
2415
+ workerThreadId,
2416
+ hasConfig: !!workerConfig
2417
+ });
2575
2418
  const result = await agent.invoke(
2576
2419
  {
2577
2420
  messages: [{ role: "user", content: task }]
2578
2421
  },
2579
- config
2580
- // Pass through the config for checkpointing and interrupt support
2422
+ workerConfig
2423
+ // Worker-specific config with unique thread_id
2581
2424
  );
2582
2425
  const response = result.messages?.[result.messages.length - 1]?.content || "No response";
2583
- logger2.debug("Received response from ReAct agent", {
2426
+ logger.debug("Received response from ReAct agent", {
2584
2427
  workerId,
2585
2428
  responsePreview: response.substring(0, 100) + (response.length > 100 ? "..." : "")
2586
2429
  });
2587
2430
  const toolsUsed = result.actions?.map((action) => action.name).filter(Boolean) || [];
2588
2431
  const uniqueTools = [...new Set(toolsUsed)];
2589
2432
  if (uniqueTools.length > 0) {
2590
- logger2.debug("Tools used by ReAct agent", { workerId, tools: uniqueTools });
2433
+ logger.debug("Tools used by ReAct agent", { workerId, tools: uniqueTools });
2591
2434
  }
2592
2435
  const taskResult = {
2593
2436
  assignmentId: currentAssignment.id,
@@ -2606,7 +2449,7 @@ function wrapReActAgent(workerId, agent, verbose = false) {
2606
2449
  };
2607
2450
  } catch (error) {
2608
2451
  const errorMessage = handleNodeError(error, `react-agent:${workerId}`, false);
2609
- logger2.error("Error in ReAct agent execution", {
2452
+ logger.error("Error in ReAct agent execution", {
2610
2453
  workerId,
2611
2454
  error: errorMessage
2612
2455
  });
@@ -2638,9 +2481,9 @@ function wrapReActAgent(workerId, agent, verbose = false) {
2638
2481
 
2639
2482
  // src/multi-agent/nodes.ts
2640
2483
  var import_messages5 = require("@langchain/core/messages");
2641
- var import_core10 = require("@agentforge/core");
2642
- var logLevel3 = process.env.LOG_LEVEL?.toLowerCase() || import_core10.LogLevel.INFO;
2643
- var logger3 = (0, import_core10.createLogger)("multi-agent:nodes", { level: logLevel3 });
2484
+ var import_core9 = require("@agentforge/core");
2485
+ var logLevel2 = process.env.LOG_LEVEL?.toLowerCase() || import_core9.LogLevel.INFO;
2486
+ var logger2 = (0, import_core9.createLogger)("multi-agent:nodes", { level: logLevel2 });
2644
2487
  var DEFAULT_AGGREGATOR_SYSTEM_PROMPT = `You are an aggregator agent responsible for combining results from multiple worker agents.
2645
2488
 
2646
2489
  Your job is to:
@@ -2658,19 +2501,19 @@ function createSupervisorNode(config) {
2658
2501
  } = config;
2659
2502
  return async (state) => {
2660
2503
  try {
2661
- logger3.info("Supervisor node executing", {
2504
+ logger2.info("Supervisor node executing", {
2662
2505
  iteration: state.iteration,
2663
2506
  maxIterations,
2664
2507
  activeAssignments: state.activeAssignments.length,
2665
2508
  completedTasks: state.completedTasks.length
2666
2509
  });
2667
- logger3.debug(`Routing iteration ${state.iteration}/${maxIterations}`);
2510
+ logger2.debug(`Routing iteration ${state.iteration}/${maxIterations}`);
2668
2511
  if (state.iteration >= maxIterations) {
2669
- logger3.warn("Max iterations reached", {
2512
+ logger2.warn("Max iterations reached", {
2670
2513
  iteration: state.iteration,
2671
2514
  maxIterations
2672
2515
  });
2673
- logger3.debug("Max iterations reached, moving to aggregation");
2516
+ logger2.debug("Max iterations reached, moving to aggregation");
2674
2517
  return {
2675
2518
  status: "aggregating",
2676
2519
  currentAgent: "aggregator"
@@ -2679,26 +2522,26 @@ function createSupervisorNode(config) {
2679
2522
  const allCompleted = state.activeAssignments.every(
2680
2523
  (assignment) => state.completedTasks.some((task2) => task2.assignmentId === assignment.id)
2681
2524
  );
2682
- logger3.debug("Checking task completion", {
2525
+ logger2.debug("Checking task completion", {
2683
2526
  activeAssignments: state.activeAssignments.length,
2684
2527
  completedTasks: state.completedTasks.length,
2685
2528
  allCompleted
2686
2529
  });
2687
2530
  if (allCompleted && state.activeAssignments.length > 0) {
2688
- logger3.info("All tasks completed, moving to aggregation", {
2531
+ logger2.info("All tasks completed, moving to aggregation", {
2689
2532
  completedCount: state.completedTasks.length
2690
2533
  });
2691
- logger3.debug("All tasks completed, moving to aggregation");
2534
+ logger2.debug("All tasks completed, moving to aggregation");
2692
2535
  return {
2693
2536
  status: "aggregating",
2694
2537
  currentAgent: "aggregator"
2695
2538
  };
2696
2539
  }
2697
- logger3.debug("Getting routing strategy", { strategy });
2540
+ logger2.debug("Getting routing strategy", { strategy });
2698
2541
  const routingImpl = getRoutingStrategy(strategy);
2699
2542
  const decision = await routingImpl.route(state, config);
2700
2543
  const targetAgents = decision.targetAgents && decision.targetAgents.length > 0 ? decision.targetAgents : decision.targetAgent ? [decision.targetAgent] : [];
2701
- logger3.debug("Target agents determined", {
2544
+ logger2.debug("Target agents determined", {
2702
2545
  targetAgents,
2703
2546
  isParallel: targetAgents.length > 1,
2704
2547
  decision: {
@@ -2707,17 +2550,17 @@ function createSupervisorNode(config) {
2707
2550
  }
2708
2551
  });
2709
2552
  if (targetAgents.length === 0) {
2710
- logger3.error("No target agents specified in routing decision");
2553
+ logger2.error("No target agents specified in routing decision");
2711
2554
  throw new Error("Routing decision must specify at least one target agent");
2712
2555
  }
2713
2556
  if (targetAgents.length === 1) {
2714
- logger3.info("Routing to single agent", {
2557
+ logger2.info("Routing to single agent", {
2715
2558
  targetAgent: targetAgents[0],
2716
2559
  reasoning: decision.reasoning,
2717
2560
  confidence: decision.confidence
2718
2561
  });
2719
2562
  } else {
2720
- logger3.info("Routing to multiple agents in parallel", {
2563
+ logger2.info("Routing to multiple agents in parallel", {
2721
2564
  targetAgents,
2722
2565
  count: targetAgents.length,
2723
2566
  reasoning: decision.reasoning,
@@ -2725,9 +2568,9 @@ function createSupervisorNode(config) {
2725
2568
  });
2726
2569
  }
2727
2570
  if (targetAgents.length === 1) {
2728
- logger3.debug(`Routing to ${targetAgents[0]}: ${decision.reasoning}`);
2571
+ logger2.debug(`Routing to ${targetAgents[0]}: ${decision.reasoning}`);
2729
2572
  } else {
2730
- logger3.debug(`Routing to ${targetAgents.length} agents in parallel [${targetAgents.join(", ")}]: ${decision.reasoning}`);
2573
+ logger2.debug(`Routing to ${targetAgents.length} agents in parallel [${targetAgents.join(", ")}]: ${decision.reasoning}`);
2731
2574
  }
2732
2575
  const task = state.messages[state.messages.length - 1]?.content || state.input;
2733
2576
  const assignments = targetAgents.map((workerId) => ({
@@ -2737,7 +2580,7 @@ function createSupervisorNode(config) {
2737
2580
  priority: 5,
2738
2581
  assignedAt: Date.now()
2739
2582
  }));
2740
- logger3.debug("Created task assignments", {
2583
+ logger2.debug("Created task assignments", {
2741
2584
  assignmentCount: assignments.length,
2742
2585
  assignments: assignments.map((a) => ({
2743
2586
  id: a.id,
@@ -2757,7 +2600,7 @@ function createSupervisorNode(config) {
2757
2600
  priority: assignment.priority
2758
2601
  }
2759
2602
  }));
2760
- logger3.info("Supervisor routing complete", {
2603
+ logger2.info("Supervisor routing complete", {
2761
2604
  currentAgent: targetAgents.join(","),
2762
2605
  status: "executing",
2763
2606
  assignmentCount: assignments.length,
@@ -2774,7 +2617,7 @@ function createSupervisorNode(config) {
2774
2617
  iteration: state.iteration + 1
2775
2618
  };
2776
2619
  } catch (error) {
2777
- logger3.error("Supervisor node error", {
2620
+ logger2.error("Supervisor node error", {
2778
2621
  error: error instanceof Error ? error.message : String(error),
2779
2622
  stack: error instanceof Error ? error.stack : void 0,
2780
2623
  iteration: state.iteration
@@ -2799,7 +2642,7 @@ function createWorkerNode(config) {
2799
2642
  } = config;
2800
2643
  return async (state, runConfig) => {
2801
2644
  try {
2802
- logger3.info("Worker node executing", {
2645
+ logger2.info("Worker node executing", {
2803
2646
  workerId: id,
2804
2647
  iteration: state.iteration,
2805
2648
  activeAssignments: state.activeAssignments.length
@@ -2808,39 +2651,39 @@ function createWorkerNode(config) {
2808
2651
  (assignment) => assignment.workerId === id && !state.completedTasks.some((task) => task.assignmentId === assignment.id)
2809
2652
  );
2810
2653
  if (!currentAssignment) {
2811
- logger3.debug("No active assignment found for worker", {
2654
+ logger2.debug("No active assignment found for worker", {
2812
2655
  workerId: id,
2813
2656
  totalActiveAssignments: state.activeAssignments.length,
2814
2657
  completedTasks: state.completedTasks.length
2815
2658
  });
2816
2659
  return {};
2817
2660
  }
2818
- logger3.info("Worker processing assignment", {
2661
+ logger2.info("Worker processing assignment", {
2819
2662
  workerId: id,
2820
2663
  assignmentId: currentAssignment.id,
2821
2664
  taskLength: currentAssignment.task.length,
2822
2665
  taskPreview: currentAssignment.task.substring(0, 100)
2823
2666
  });
2824
2667
  if (executeFn) {
2825
- logger3.debug("Using custom execution function", { workerId: id });
2668
+ logger2.debug("Using custom execution function", { workerId: id });
2826
2669
  return await executeFn(state, runConfig);
2827
2670
  }
2828
2671
  if (agent) {
2829
2672
  if (isReActAgent(agent)) {
2830
- logger3.debug("Using ReAct agent", { workerId: id });
2673
+ logger2.debug("Using ReAct agent", { workerId: id });
2831
2674
  const wrappedFn = wrapReActAgent(id, agent, verbose);
2832
2675
  return await wrappedFn(state, runConfig);
2833
2676
  } else {
2834
- logger3.warn("Agent provided but not a ReAct agent, falling back", { workerId: id });
2677
+ logger2.warn("Agent provided but not a ReAct agent, falling back", { workerId: id });
2835
2678
  }
2836
2679
  }
2837
2680
  if (!model) {
2838
- logger3.error("Worker missing required configuration", { workerId: id });
2681
+ logger2.error("Worker missing required configuration", { workerId: id });
2839
2682
  throw new Error(
2840
2683
  `Worker ${id} requires either a model, an agent, or a custom execution function. Provide one of: config.model, config.agent, or config.executeFn`
2841
2684
  );
2842
2685
  }
2843
- logger3.debug("Using default LLM execution", {
2686
+ logger2.debug("Using default LLM execution", {
2844
2687
  workerId: id,
2845
2688
  hasTools: tools.length > 0,
2846
2689
  toolCount: tools.length
@@ -2856,18 +2699,18 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
2856
2699
  ];
2857
2700
  let modelToUse = model;
2858
2701
  if (tools.length > 0 && model.bindTools) {
2859
- logger3.debug("Binding tools to model", {
2702
+ logger2.debug("Binding tools to model", {
2860
2703
  workerId: id,
2861
2704
  toolCount: tools.length,
2862
2705
  toolNames: tools.map((t) => t.metadata.name)
2863
2706
  });
2864
- const langchainTools = (0, import_core10.toLangChainTools)(tools);
2707
+ const langchainTools = (0, import_core9.toLangChainTools)(tools);
2865
2708
  modelToUse = model.bindTools(langchainTools);
2866
2709
  }
2867
- logger3.debug("Invoking LLM", { workerId: id });
2710
+ logger2.debug("Invoking LLM", { workerId: id });
2868
2711
  const response = await modelToUse.invoke(messages);
2869
2712
  const result = typeof response.content === "string" ? response.content : JSON.stringify(response.content);
2870
- logger3.info("Worker task completed", {
2713
+ logger2.info("Worker task completed", {
2871
2714
  workerId: id,
2872
2715
  assignmentId: currentAssignment.id,
2873
2716
  resultLength: result.length,
@@ -2902,7 +2745,7 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
2902
2745
  currentWorkload: Math.max(0, capabilities.currentWorkload - 1)
2903
2746
  }
2904
2747
  };
2905
- logger3.debug("Worker state update", {
2748
+ logger2.debug("Worker state update", {
2906
2749
  workerId: id,
2907
2750
  newWorkload: updatedWorkers[id].currentWorkload
2908
2751
  });
@@ -2913,7 +2756,7 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
2913
2756
  };
2914
2757
  } catch (error) {
2915
2758
  const errorMessage = handleNodeError(error, `worker:${id}`, false);
2916
- logger3.error("Worker node error", {
2759
+ logger2.error("Worker node error", {
2917
2760
  workerId: id,
2918
2761
  error: errorMessage
2919
2762
  });
@@ -2921,7 +2764,7 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
2921
2764
  (assignment) => assignment.workerId === id
2922
2765
  );
2923
2766
  if (currentAssignment) {
2924
- logger3.warn("Creating error result for assignment", {
2767
+ logger2.warn("Creating error result for assignment", {
2925
2768
  workerId: id,
2926
2769
  assignmentId: currentAssignment.id
2927
2770
  });
@@ -2939,7 +2782,7 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
2939
2782
  status: "routing"
2940
2783
  };
2941
2784
  }
2942
- logger3.error("No assignment found for error handling", { workerId: id });
2785
+ logger2.error("No assignment found for error handling", { workerId: id });
2943
2786
  return {
2944
2787
  status: "failed",
2945
2788
  error: errorMessage
@@ -2956,16 +2799,16 @@ function createAggregatorNode(config = {}) {
2956
2799
  } = config;
2957
2800
  return async (state) => {
2958
2801
  try {
2959
- logger3.info("Aggregator node executing", {
2802
+ logger2.info("Aggregator node executing", {
2960
2803
  completedTasks: state.completedTasks.length,
2961
2804
  successfulTasks: state.completedTasks.filter((t) => t.success).length,
2962
2805
  failedTasks: state.completedTasks.filter((t) => !t.success).length
2963
2806
  });
2964
- logger3.debug("Combining results from workers");
2807
+ logger2.debug("Combining results from workers");
2965
2808
  if (aggregateFn) {
2966
- logger3.debug("Using custom aggregation function");
2809
+ logger2.debug("Using custom aggregation function");
2967
2810
  const response2 = await aggregateFn(state);
2968
- logger3.info("Custom aggregation complete", {
2811
+ logger2.info("Custom aggregation complete", {
2969
2812
  responseLength: response2.length
2970
2813
  });
2971
2814
  return {
@@ -2974,16 +2817,16 @@ function createAggregatorNode(config = {}) {
2974
2817
  };
2975
2818
  }
2976
2819
  if (state.completedTasks.length === 0) {
2977
- logger3.warn("No completed tasks to aggregate");
2820
+ logger2.warn("No completed tasks to aggregate");
2978
2821
  return {
2979
2822
  response: "No tasks were completed.",
2980
2823
  status: "completed"
2981
2824
  };
2982
2825
  }
2983
2826
  if (!model) {
2984
- logger3.debug("No model provided, concatenating results");
2827
+ logger2.debug("No model provided, concatenating results");
2985
2828
  const combinedResults = state.completedTasks.filter((task) => task.success).map((task) => task.result).join("\n\n");
2986
- logger3.info("Simple concatenation complete", {
2829
+ logger2.info("Simple concatenation complete", {
2987
2830
  resultLength: combinedResults.length
2988
2831
  });
2989
2832
  return {
@@ -2991,7 +2834,7 @@ function createAggregatorNode(config = {}) {
2991
2834
  status: "completed"
2992
2835
  };
2993
2836
  }
2994
- logger3.debug("Using LLM for intelligent aggregation", {
2837
+ logger2.debug("Using LLM for intelligent aggregation", {
2995
2838
  taskCount: state.completedTasks.length
2996
2839
  });
2997
2840
  const taskResults = state.completedTasks.map((task, idx) => {
@@ -3010,20 +2853,20 @@ Please synthesize these results into a comprehensive response that addresses the
3010
2853
  new import_messages5.SystemMessage(systemPrompt),
3011
2854
  new import_messages5.HumanMessage(userPrompt)
3012
2855
  ];
3013
- logger3.debug("Invoking aggregation LLM");
2856
+ logger2.debug("Invoking aggregation LLM");
3014
2857
  const response = await model.invoke(messages);
3015
2858
  const aggregatedResponse = typeof response.content === "string" ? response.content : JSON.stringify(response.content);
3016
- logger3.info("Aggregation complete", {
2859
+ logger2.info("Aggregation complete", {
3017
2860
  responseLength: aggregatedResponse.length,
3018
2861
  responsePreview: aggregatedResponse.substring(0, 100)
3019
2862
  });
3020
- logger3.debug("Aggregation complete");
2863
+ logger2.debug("Aggregation complete");
3021
2864
  return {
3022
2865
  response: aggregatedResponse,
3023
2866
  status: "completed"
3024
2867
  };
3025
2868
  } catch (error) {
3026
- logger3.error("Aggregator node error", {
2869
+ logger2.error("Aggregator node error", {
3027
2870
  error: error instanceof Error ? error.message : String(error),
3028
2871
  stack: error instanceof Error ? error.stack : void 0,
3029
2872
  completedTasks: state.completedTasks.length
@@ -3038,9 +2881,9 @@ Please synthesize these results into a comprehensive response that addresses the
3038
2881
 
3039
2882
  // src/multi-agent/agent.ts
3040
2883
  var import_langgraph4 = require("@langchain/langgraph");
3041
- var import_core11 = require("@agentforge/core");
3042
- var logLevel4 = process.env.LOG_LEVEL?.toLowerCase() || import_core11.LogLevel.INFO;
3043
- var logger4 = (0, import_core11.createLogger)("multi-agent:system", { level: logLevel4 });
2884
+ var import_core10 = require("@agentforge/core");
2885
+ var logLevel3 = process.env.LOG_LEVEL?.toLowerCase() || import_core10.LogLevel.INFO;
2886
+ var logger3 = (0, import_core10.createLogger)("multi-agent:system", { level: logLevel3 });
3044
2887
  function createMultiAgentSystem(config) {
3045
2888
  const {
3046
2889
  supervisor,
@@ -3057,10 +2900,6 @@ function createMultiAgentSystem(config) {
3057
2900
  if (supervisor.strategy === "llm-based") {
3058
2901
  configuredModel = configuredModel.withStructuredOutput(RoutingDecisionSchema);
3059
2902
  }
3060
- if (supervisor.tools && supervisor.tools.length > 0) {
3061
- const langchainTools = (0, import_core11.toLangChainTools)(supervisor.tools);
3062
- configuredModel = configuredModel.bindTools(langchainTools);
3063
- }
3064
2903
  supervisorConfig.model = configuredModel;
3065
2904
  }
3066
2905
  const supervisorNode = createSupervisorNode(supervisorConfig);
@@ -3082,46 +2921,46 @@ function createMultiAgentSystem(config) {
3082
2921
  });
3083
2922
  workflow.addNode("aggregator", aggregatorNode);
3084
2923
  const supervisorRouter = (state) => {
3085
- logger4.debug("Supervisor router executing", {
2924
+ logger3.debug("Supervisor router executing", {
3086
2925
  status: state.status,
3087
2926
  currentAgent: state.currentAgent,
3088
2927
  iteration: state.iteration
3089
2928
  });
3090
2929
  if (state.status === "completed" || state.status === "failed") {
3091
- logger4.info("Supervisor router: ending workflow", { status: state.status });
2930
+ logger3.info("Supervisor router: ending workflow", { status: state.status });
3092
2931
  return import_langgraph4.END;
3093
2932
  }
3094
2933
  if (state.status === "aggregating") {
3095
- logger4.info("Supervisor router: routing to aggregator");
2934
+ logger3.info("Supervisor router: routing to aggregator");
3096
2935
  return "aggregator";
3097
2936
  }
3098
2937
  if (state.currentAgent && state.currentAgent !== "supervisor") {
3099
2938
  if (state.currentAgent.includes(",")) {
3100
2939
  const agents = state.currentAgent.split(",").map((a) => a.trim());
3101
- logger4.info("Supervisor router: parallel routing", {
2940
+ logger3.info("Supervisor router: parallel routing", {
3102
2941
  agents,
3103
2942
  count: agents.length
3104
2943
  });
3105
2944
  return agents;
3106
2945
  }
3107
- logger4.info("Supervisor router: single agent routing", {
2946
+ logger3.info("Supervisor router: single agent routing", {
3108
2947
  targetAgent: state.currentAgent
3109
2948
  });
3110
2949
  return state.currentAgent;
3111
2950
  }
3112
- logger4.debug("Supervisor router: staying at supervisor");
2951
+ logger3.debug("Supervisor router: staying at supervisor");
3113
2952
  return "supervisor";
3114
2953
  };
3115
2954
  const workerRouter = (state) => {
3116
- logger4.debug("Worker router executing", {
2955
+ logger3.debug("Worker router executing", {
3117
2956
  iteration: state.iteration,
3118
2957
  completedTasks: state.completedTasks.length
3119
2958
  });
3120
- logger4.debug("Worker router: returning to supervisor");
2959
+ logger3.debug("Worker router: returning to supervisor");
3121
2960
  return "supervisor";
3122
2961
  };
3123
2962
  const aggregatorRouter = (state) => {
3124
- logger4.info("Aggregator router: ending workflow", {
2963
+ logger3.info("Aggregator router: ending workflow", {
3125
2964
  completedTasks: state.completedTasks.length,
3126
2965
  status: state.status
3127
2966
  });