@illuma-ai/agents 1.1.15 → 1.1.16

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.
Files changed (64) hide show
  1. package/dist/cjs/common/enum.cjs +13 -13
  2. package/dist/cjs/common/enum.cjs.map +1 -1
  3. package/dist/cjs/graphs/MultiAgentGraph.cjs +146 -150
  4. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
  5. package/dist/cjs/main.cjs +2 -2
  6. package/dist/cjs/types/graph.cjs.map +1 -1
  7. package/dist/esm/common/enum.mjs +12 -12
  8. package/dist/esm/common/enum.mjs.map +1 -1
  9. package/dist/esm/graphs/MultiAgentGraph.mjs +147 -151
  10. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
  11. package/dist/esm/main.mjs +1 -1
  12. package/dist/esm/types/graph.mjs.map +1 -1
  13. package/dist/types/common/enum.d.ts +11 -11
  14. package/dist/types/graphs/MultiAgentGraph.d.ts +38 -36
  15. package/dist/types/types/graph.d.ts +13 -7
  16. package/package.json +1 -1
  17. package/src/common/__tests__/enum.test.ts +14 -6
  18. package/src/common/enum.ts +11 -11
  19. package/src/graphs/MultiAgentGraph.ts +148 -152
  20. package/src/graphs/__tests__/multi-agent-delegate.test.ts +44 -44
  21. package/src/graphs/__tests__/multi-agent-edges.test.ts +83 -85
  22. package/src/scripts/multi-agent-chain.js +1 -1
  23. package/src/scripts/multi-agent-chain.ts +1 -1
  24. package/src/scripts/multi-agent-document-review-chain.js +1 -1
  25. package/src/scripts/multi-agent-document-review-chain.ts +1 -1
  26. package/src/scripts/multi-agent-hybrid-flow.js +3 -3
  27. package/src/scripts/multi-agent-hybrid-flow.ts +3 -3
  28. package/src/scripts/multi-agent-parallel.js +2 -2
  29. package/src/scripts/multi-agent-parallel.ts +2 -2
  30. package/src/scripts/multi-agent-sequence.js +2 -2
  31. package/src/scripts/multi-agent-sequence.ts +2 -2
  32. package/src/scripts/multi-agent-supervisor.js +5 -5
  33. package/src/scripts/multi-agent-supervisor.ts +5 -5
  34. package/src/scripts/poc-multi-agent-comprehensive.ts +7 -7
  35. package/src/scripts/sequential-full-metadata-test.js +1 -1
  36. package/src/scripts/sequential-full-metadata-test.ts +1 -1
  37. package/src/scripts/test-custom-prompt-key.js +3 -3
  38. package/src/scripts/test-custom-prompt-key.ts +3 -3
  39. package/src/scripts/test-handoff-input.js +1 -1
  40. package/src/scripts/test-handoff-input.ts +1 -1
  41. package/src/scripts/test-handoff-preamble.js +1 -1
  42. package/src/scripts/test-handoff-preamble.ts +1 -1
  43. package/src/scripts/test-handoff-steering.js +3 -3
  44. package/src/scripts/test-handoff-steering.ts +3 -3
  45. package/src/scripts/test-multi-agent-list-handoff.js +1 -1
  46. package/src/scripts/test-multi-agent-list-handoff.ts +1 -1
  47. package/src/scripts/test-parallel-agent-labeling.js +2 -2
  48. package/src/scripts/test-parallel-agent-labeling.ts +2 -2
  49. package/src/scripts/test-parallel-handoffs.js +2 -2
  50. package/src/scripts/test-parallel-handoffs.ts +2 -2
  51. package/src/scripts/test-thinking-handoff-bedrock.js +1 -1
  52. package/src/scripts/test-thinking-handoff-bedrock.ts +1 -1
  53. package/src/scripts/test-thinking-handoff.js +1 -1
  54. package/src/scripts/test-thinking-handoff.ts +1 -1
  55. package/src/scripts/test-thinking-to-thinking-handoff-bedrock.js +1 -1
  56. package/src/scripts/test-thinking-to-thinking-handoff-bedrock.ts +1 -1
  57. package/src/scripts/test-tool-before-handoff-role-order.js +1 -1
  58. package/src/scripts/test-tool-before-handoff-role-order.ts +1 -1
  59. package/src/scripts/test-tools-before-handoff.js +1 -1
  60. package/src/scripts/test-tools-before-handoff.ts +1 -1
  61. package/src/specs/agent-handoffs-bedrock.integration.test.ts +6 -6
  62. package/src/specs/agent-handoffs.test.ts +35 -35
  63. package/src/specs/thinking-handoff.test.ts +9 -9
  64. package/src/types/graph.ts +13 -7
@@ -13,30 +13,30 @@ var summarize = require('../messages/summarize.cjs');
13
13
  var Graph = require('./Graph.cjs');
14
14
 
15
15
  /** Pattern to extract instructions from transfer ToolMessage content */
16
- const HANDOFF_INSTRUCTIONS_PATTERN = /(?:Instructions?|Context):\s*(.+)/is;
16
+ const TRANSFER_INSTRUCTIONS_PATTERN = /(?:Instructions?|Context):\s*(.+)/is;
17
17
  /**
18
18
  * MultiAgentGraph extends StandardGraph to support dynamic multi-agent workflows
19
19
  * with handoffs, fan-in/fan-out, and other composable patterns.
20
20
  *
21
21
  * Key behavior:
22
- * - Agents with ONLY handoff edges: Can dynamically route to any handoff destination
23
- * - Agents with ONLY direct edges: Always follow their direct edges
24
- * - Agents with BOTH: Use Command for exclusive routing (handoff OR direct, not both)
25
- * - If handoff occurs: Only the handoff destination executes
26
- * - If no handoff: Direct edges execute (potentially in parallel)
22
+ * - Agents with ONLY transfer edges: Can dynamically route to any transfer destination
23
+ * - Agents with ONLY sequence edges: Always follow their sequence edges
24
+ * - Agents with BOTH: Use Command for exclusive routing (transfer OR sequence, not both)
25
+ * - If transfer occurs: Only the transfer destination executes
26
+ * - If no transfer: Sequence edges execute (potentially in parallel)
27
27
  *
28
- * This enables the common pattern where an agent either delegates (handoff)
29
- * OR continues its workflow (direct edges), but not both simultaneously.
28
+ * This enables the common pattern where an agent either transfers (one-way)
29
+ * OR continues its workflow (sequence edges), but not both simultaneously.
30
30
  */
31
31
  class MultiAgentGraph extends Graph.StandardGraph {
32
32
  edges;
33
33
  startingNodes = new Set();
34
- directEdges = [];
34
+ sequenceEdges = [];
35
+ transferEdges = [];
35
36
  handoffEdges = [];
36
- delegateEdges = [];
37
37
  /**
38
38
  * Lazily populated registry of compiled subgraphs, keyed by agentId.
39
- * Delegate tools are created in the constructor but reference subgraphs
39
+ * Handoff tools are created in the constructor but reference subgraphs
40
40
  * that are only created in createWorkflow(). This Map bridges that gap —
41
41
  * tools capture the Map reference in their closure, and createWorkflow()
42
42
  * populates it before any tool invocation occurs.
@@ -63,41 +63,39 @@ class MultiAgentGraph extends Graph.StandardGraph {
63
63
  this.edges = input.edges;
64
64
  this.categorizeEdges();
65
65
  this.analyzeGraph();
66
+ this.createTransferTools();
66
67
  this.createHandoffTools();
67
- this.createDelegateTools();
68
68
  console.debug(`[MultiAgentGraph] Constructor complete: ${this.agentContexts.size} agents, ${this.edges.length} edges`);
69
69
  }
70
70
  /**
71
- * Categorize edges into handoff and direct types
71
+ * Categorize edges into handoff, transfer, and sequence types
72
72
  */
73
73
  categorizeEdges() {
74
74
  for (const edge of this.edges) {
75
- // Default behavior: edges with conditions or explicit 'handoff' type are handoff edges
76
- // Edges with explicit 'direct' type or multi-destination without conditions are direct edges
77
- if (edge.edgeType === _enum.EdgeType.DELEGATE) {
78
- this.delegateEdges.push(edge);
75
+ if (edge.edgeType === _enum.EdgeType.HANDOFF) {
76
+ this.handoffEdges.push(edge);
79
77
  }
80
- else if (edge.edgeType === _enum.EdgeType.DIRECT) {
81
- this.directEdges.push(edge);
78
+ else if (edge.edgeType === _enum.EdgeType.SEQUENCE) {
79
+ this.sequenceEdges.push(edge);
82
80
  }
83
- else if (edge.edgeType === _enum.EdgeType.HANDOFF || edge.condition != null) {
84
- this.handoffEdges.push(edge);
81
+ else if (edge.edgeType === _enum.EdgeType.TRANSFER || edge.condition != null) {
82
+ this.transferEdges.push(edge);
85
83
  }
86
84
  else {
87
- // Default: single-to-single edges are handoff, single-to-multiple are direct
85
+ // Default: single-to-single edges are transfer, single-to-multiple are sequence
88
86
  const destinations = Array.isArray(edge.to) ? edge.to : [edge.to];
89
87
  const sources = Array.isArray(edge.from) ? edge.from : [edge.from];
90
88
  if (sources.length === 1 && destinations.length > 1) {
91
- // Fan-out pattern defaults to direct
92
- this.directEdges.push(edge);
89
+ // Fan-out pattern defaults to sequence
90
+ this.sequenceEdges.push(edge);
93
91
  }
94
92
  else {
95
- // Everything else defaults to handoff
96
- this.handoffEdges.push(edge);
93
+ // Everything else defaults to transfer
94
+ this.transferEdges.push(edge);
97
95
  }
98
96
  }
99
97
  }
100
- console.debug(`[MultiAgentGraph] Edge categorization: ${this.handoffEdges.length} handoff, ${this.directEdges.length} direct, ${this.delegateEdges.length} delegate (of ${this.edges.length} total)`);
98
+ console.debug(`[MultiAgentGraph] Edge categorization: ${this.handoffEdges.length} handoff, ${this.transferEdges.length} transfer, ${this.sequenceEdges.length} sequence (of ${this.edges.length} total)`);
101
99
  }
102
100
  /**
103
101
  * Analyze graph structure to determine starting nodes and connections
@@ -155,8 +153,8 @@ class MultiAgentGraph extends Graph.StandardGraph {
155
153
  if (visited.has(current))
156
154
  continue;
157
155
  visited.add(current);
158
- // Find direct edges from this node
159
- for (const edge of this.directEdges) {
156
+ // Find sequence edges from this node
157
+ for (const edge of this.sequenceEdges) {
160
158
  const sources = Array.isArray(edge.from) ? edge.from : [edge.from];
161
159
  if (!sources.includes(current))
162
160
  continue;
@@ -183,8 +181,8 @@ class MultiAgentGraph extends Graph.StandardGraph {
183
181
  }
184
182
  }
185
183
  }
186
- // Also follow handoff and delegate edges for traversal (they don't create parallel groups)
187
- for (const edge of [...this.handoffEdges, ...this.delegateEdges]) {
184
+ // Also follow transfer and handoff edges for traversal (they don't create parallel groups)
185
+ for (const edge of [...this.transferEdges, ...this.handoffEdges]) {
188
186
  const sources = Array.isArray(edge.from) ? edge.from : [edge.from];
189
187
  if (!sources.includes(current))
190
188
  continue;
@@ -227,46 +225,44 @@ class MultiAgentGraph extends Graph.StandardGraph {
227
225
  return this.agentParallelGroups.get(agentId);
228
226
  }
229
227
  /**
230
- * Create handoff tools for agents based on handoff edges only
228
+ * Create transfer tools for agents based on transfer edges only.
229
+ * Transfer tools return Command for one-way routing — parent exits, child takes over.
231
230
  */
232
- createHandoffTools() {
233
- // Group handoff edges by source agent(s)
234
- const handoffsByAgent = new Map();
235
- // Only process handoff edges for tool creation
236
- for (const edge of this.handoffEdges) {
231
+ createTransferTools() {
232
+ const transfersByAgent = new Map();
233
+ for (const edge of this.transferEdges) {
237
234
  const sources = Array.isArray(edge.from) ? edge.from : [edge.from];
238
235
  sources.forEach((source) => {
239
- if (!handoffsByAgent.has(source)) {
240
- handoffsByAgent.set(source, []);
236
+ if (!transfersByAgent.has(source)) {
237
+ transfersByAgent.set(source, []);
241
238
  }
242
- handoffsByAgent.get(source).push(edge);
239
+ transfersByAgent.get(source).push(edge);
243
240
  });
244
241
  }
245
- // Create handoff tools for each agent
246
- for (const [agentId, edges] of handoffsByAgent) {
242
+ for (const [agentId, edges] of transfersByAgent) {
247
243
  const agentContext = this.agentContexts.get(agentId);
248
244
  if (!agentContext)
249
245
  continue;
250
- // Create handoff tools for this agent's outgoing edges
251
- const handoffTools = [];
246
+ const transferTools = [];
252
247
  const sourceAgentName = agentContext.name ?? agentId;
253
248
  for (const edge of edges) {
254
- handoffTools.push(...this.createHandoffToolsForEdge(edge, agentId, sourceAgentName));
249
+ transferTools.push(...this.createTransferToolsForEdge(edge, agentId, sourceAgentName));
255
250
  }
256
251
  if (!agentContext.graphTools) {
257
252
  agentContext.graphTools = [];
258
253
  }
259
- agentContext.graphTools.push(...handoffTools);
260
- console.debug(`[MultiAgentGraph] Handoff tools for "${agentId}": [${handoffTools.map((t) => t.name).join(', ')}]`);
254
+ agentContext.graphTools.push(...transferTools);
255
+ console.debug(`[MultiAgentGraph] Transfer tools for "${agentId}": [${transferTools.map((t) => t.name).join(', ')}]`);
261
256
  }
262
257
  }
263
258
  /**
264
- * Create handoff tools for an edge (handles multiple destinations)
265
- * @param edge - The graph edge defining the handoff
266
- * @param sourceAgentId - The ID of the agent that will perform the handoff
259
+ * Create transfer tools for an edge (handles multiple destinations).
260
+ * Transfer tools return Command for one-way routing parent exits, child takes over.
261
+ * @param edge - The graph edge defining the transfer
262
+ * @param sourceAgentId - The ID of the agent that will perform the transfer
267
263
  * @param sourceAgentName - The human-readable name of the source agent
268
264
  */
269
- createHandoffToolsForEdge(edge, sourceAgentId, sourceAgentName) {
265
+ createTransferToolsForEdge(edge, sourceAgentId, sourceAgentName) {
270
266
  const tools$1 = [];
271
267
  const destinations = Array.isArray(edge.to) ? edge.to : [edge.to];
272
268
  /** If there's a condition, create a single conditional handoff tool */
@@ -274,8 +270,8 @@ class MultiAgentGraph extends Graph.StandardGraph {
274
270
  const toolName = 'conditional_transfer';
275
271
  const toolDescription = edge.description ?? 'Conditionally transfer control based on state';
276
272
  /** Check if we have a prompt for handoff input */
277
- const hasHandoffInput = edge.prompt != null && typeof edge.prompt === 'string';
278
- const handoffInputDescription = hasHandoffInput ? edge.prompt : undefined;
273
+ const hasTransferInput = edge.prompt != null && typeof edge.prompt === 'string';
274
+ const transferInputDescription = hasTransferInput ? edge.prompt : undefined;
279
275
  const promptKey = edge.promptKey ?? 'instructions';
280
276
  tools$1.push(tools.tool(async (rawInput, config) => {
281
277
  const input = rawInput;
@@ -299,7 +295,7 @@ class MultiAgentGraph extends Graph.StandardGraph {
299
295
  destination = Array.isArray(result) ? result[0] : destinations[0];
300
296
  }
301
297
  let content = `Conditionally transferred to ${destination}`;
302
- if (hasHandoffInput &&
298
+ if (hasTransferInput &&
303
299
  promptKey in input &&
304
300
  input[promptKey] != null) {
305
301
  content += `\n\n${promptKey.charAt(0).toUpperCase() + promptKey.slice(1)}: ${input[promptKey]}`;
@@ -322,13 +318,13 @@ class MultiAgentGraph extends Graph.StandardGraph {
322
318
  });
323
319
  }, {
324
320
  name: toolName,
325
- schema: hasHandoffInput
321
+ schema: hasTransferInput
326
322
  ? {
327
323
  type: 'object',
328
324
  properties: {
329
325
  [promptKey]: {
330
326
  type: 'string',
331
- description: handoffInputDescription,
327
+ description: transferInputDescription,
332
328
  },
333
329
  },
334
330
  required: [],
@@ -343,10 +339,10 @@ class MultiAgentGraph extends Graph.StandardGraph {
343
339
  const toolName = `${_enum.Constants.LC_TRANSFER_TO_}${destination}`;
344
340
  const destContext = this.agentContexts.get(destination);
345
341
  const toolDescription = edge.description ??
346
- this.buildDefaultHandoffDescription(destContext, destination);
342
+ this.buildDefaultTransferDescription(destContext, destination);
347
343
  /** Check if we have a prompt for handoff input */
348
- const hasHandoffInput = edge.prompt != null && typeof edge.prompt === 'string';
349
- const handoffInputDescription = hasHandoffInput
344
+ const hasTransferInput = edge.prompt != null && typeof edge.prompt === 'string';
345
+ const transferInputDescription = hasTransferInput
350
346
  ? edge.prompt
351
347
  : undefined;
352
348
  const promptKey = edge.promptKey ?? 'instructions';
@@ -355,7 +351,7 @@ class MultiAgentGraph extends Graph.StandardGraph {
355
351
  const toolCallId = config?.toolCall?.id ??
356
352
  'unknown';
357
353
  let content = `Successfully transferred to ${destination}`;
358
- if (hasHandoffInput &&
354
+ if (hasTransferInput &&
359
355
  promptKey in input &&
360
356
  input[promptKey] != null) {
361
357
  content += `\n\n${promptKey.charAt(0).toUpperCase() + promptKey.slice(1)}: ${input[promptKey]}`;
@@ -432,13 +428,13 @@ class MultiAgentGraph extends Graph.StandardGraph {
432
428
  });
433
429
  }, {
434
430
  name: toolName,
435
- schema: hasHandoffInput
431
+ schema: hasTransferInput
436
432
  ? {
437
433
  type: 'object',
438
434
  properties: {
439
435
  [promptKey]: {
440
436
  type: 'string',
441
- description: handoffInputDescription,
437
+ description: transferInputDescription,
442
438
  },
443
439
  },
444
440
  required: [],
@@ -451,13 +447,13 @@ class MultiAgentGraph extends Graph.StandardGraph {
451
447
  return tools$1;
452
448
  }
453
449
  /**
454
- * Builds a meaningful default description for a handoff tool when no explicit
450
+ * Builds a meaningful default description for a transfer tool when no explicit
455
451
  * edge.description is provided. Uses the destination agent's name and description
456
452
  * so the LLM can make informed routing decisions.
457
453
  * @param destContext - AgentContext of the destination agent (may be undefined)
458
454
  * @param destinationId - Raw agent ID (fallback when context unavailable)
459
455
  */
460
- buildDefaultHandoffDescription(destContext, destinationId) {
456
+ buildDefaultTransferDescription(destContext, destinationId) {
461
457
  const displayName = destContext?.name ?? destinationId;
462
458
  const agentDescription = destContext?.description;
463
459
  if (agentDescription != null && agentDescription !== '') {
@@ -466,58 +462,58 @@ class MultiAgentGraph extends Graph.StandardGraph {
466
462
  return `Transfer control to "${displayName}"`;
467
463
  }
468
464
  /**
469
- * Create delegate tools for agents based on delegate edges.
470
- * Delegate tools invoke child agent subgraphs inline and return the result
471
- * as a string to the parent agent's context. Unlike handoff tools (which
472
- * return Command for fire-and-forget routing), delegate tools execute the
473
- * child, extract the final text, and return it within the parent's agent loop.
465
+ * Create handoff tools for agents based on handoff edges.
466
+ * Handoff tools invoke child agent subgraphs inline and return the result
467
+ * as a string to the parent agent's context. Unlike transfer tools (which
468
+ * return Command for one-way routing), handoff tools execute the child,
469
+ * extract the final text, and return it within the parent's agent loop.
474
470
  *
475
471
  * This enables the supervisor pattern: parent calls child → gets result → thinks → calls another.
476
472
  */
477
- createDelegateTools() {
478
- const delegatesByAgent = new Map();
479
- for (const edge of this.delegateEdges) {
473
+ createHandoffTools() {
474
+ const handoffsByAgent = new Map();
475
+ for (const edge of this.handoffEdges) {
480
476
  const sources = Array.isArray(edge.from) ? edge.from : [edge.from];
481
477
  sources.forEach((source) => {
482
- if (!delegatesByAgent.has(source)) {
483
- delegatesByAgent.set(source, []);
478
+ if (!handoffsByAgent.has(source)) {
479
+ handoffsByAgent.set(source, []);
484
480
  }
485
- delegatesByAgent.get(source).push(edge);
481
+ handoffsByAgent.get(source).push(edge);
486
482
  });
487
483
  }
488
- for (const [agentId, edges] of delegatesByAgent) {
484
+ for (const [agentId, edges] of handoffsByAgent) {
489
485
  const agentContext = this.agentContexts.get(agentId);
490
486
  if (!agentContext)
491
487
  continue;
492
- const delegateTools = [];
488
+ const handoffTools = [];
493
489
  for (const edge of edges) {
494
- delegateTools.push(...this.createDelegateToolsForEdge(edge, agentId));
490
+ handoffTools.push(...this.createHandoffToolsForEdge(edge, agentId));
495
491
  }
496
492
  if (!agentContext.graphTools) {
497
493
  agentContext.graphTools = [];
498
494
  }
499
- agentContext.graphTools.push(...delegateTools);
500
- console.debug(`[MultiAgentGraph] Delegate tools for "${agentId}": [${delegateTools.map((t) => t.name).join(', ')}]`);
495
+ agentContext.graphTools.push(...handoffTools);
496
+ console.debug(`[MultiAgentGraph] Handoff tools for "${agentId}": [${handoffTools.map((t) => t.name).join(', ')}]`);
501
497
  }
502
498
  }
503
499
  /**
504
- * Create delegate tools for an edge (handles multiple destinations).
505
- * Each delegate tool invokes the child agent's compiled subgraph inline,
500
+ * Create handoff tools for an edge (handles multiple destinations).
501
+ * Each handoff tool invokes the child agent's compiled subgraph inline,
506
502
  * extracts the final AI message text, truncates it, and returns it as
507
503
  * a string (which becomes a ToolMessage in the parent's context).
508
504
  *
509
- * @param edge - The graph edge defining the delegation
505
+ * @param edge - The graph edge defining the handoff
510
506
  * @param sourceAgentId - The ID of the parent/supervisor agent
511
507
  */
512
- createDelegateToolsForEdge(edge, sourceAgentId) {
508
+ createHandoffToolsForEdge(edge, sourceAgentId) {
513
509
  const tools$1 = [];
514
510
  const destinations = Array.isArray(edge.to) ? edge.to : [edge.to];
515
- const maxResultChars = edge.maxResultChars ?? _enum.DEFAULT_DELEGATE_MAX_RESULT_CHARS;
511
+ const maxResultChars = edge.maxResultChars ?? _enum.DEFAULT_HANDOFF_MAX_RESULT_CHARS;
516
512
  for (const destination of destinations) {
517
- const toolName = `${_enum.Constants.LC_DELEGATE_TO_}${destination}`;
513
+ const toolName = `${_enum.Constants.LC_HANDOFF_TO_}${destination}`;
518
514
  const destContext = this.agentContexts.get(destination);
519
515
  const toolDescription = edge.description ??
520
- this.buildDefaultDelegateDescription(destContext, destination);
516
+ this.buildDefaultHandoffDescription(destContext, destination);
521
517
  const hasPromptInput = edge.prompt != null && typeof edge.prompt === 'string';
522
518
  const promptInputDescription = hasPromptInput ? edge.prompt : undefined;
523
519
  const promptKey = edge.promptKey ?? 'instructions';
@@ -527,7 +523,7 @@ class MultiAgentGraph extends Graph.StandardGraph {
527
523
  const input = rawInput;
528
524
  const subgraph = registry.get(destination);
529
525
  if (!subgraph) {
530
- throw new Error(`Delegate target "${destination}" subgraph not found in registry. ` +
526
+ throw new Error(`Handoff target "${destination}" subgraph not found in registry. ` +
531
527
  'This is a bug: createWorkflow() should have populated the subgraph registry.');
532
528
  }
533
529
  const state = langgraph.getCurrentTaskInput();
@@ -544,7 +540,7 @@ class MultiAgentGraph extends Graph.StandardGraph {
544
540
  const childState = {
545
541
  messages: childMessages,
546
542
  };
547
- console.debug(`[MultiAgentGraph] Delegate "${sourceAgentId}" -> "${destination}" START ` +
543
+ console.debug(`[MultiAgentGraph] Handoff "${sourceAgentId}" -> "${destination}" START ` +
548
544
  `(messages: ${childMessages.length})`);
549
545
  try {
550
546
  /**
@@ -553,17 +549,17 @@ class MultiAgentGraph extends Graph.StandardGraph {
553
549
  * and configurable data (thread_id, user_id) to the child.
554
550
  */
555
551
  const result = await subgraph.invoke(childState, config);
556
- const resultText = MultiAgentGraph.extractDelegateResult(result.messages, destination);
557
- const truncatedResult = MultiAgentGraph.truncateDelegateResult(resultText, maxResultChars);
558
- console.debug(`[MultiAgentGraph] Delegate "${sourceAgentId}" -> "${destination}" DONE ` +
552
+ const resultText = MultiAgentGraph.extractHandoffResult(result.messages, destination);
553
+ const truncatedResult = MultiAgentGraph.truncateHandoffResult(resultText, maxResultChars);
554
+ console.debug(`[MultiAgentGraph] Handoff "${sourceAgentId}" -> "${destination}" DONE ` +
559
555
  `(result: ${resultText.length} chars` +
560
556
  `${truncatedResult.length < resultText.length ? `, truncated to ${truncatedResult.length}` : ''})`);
561
557
  return truncatedResult;
562
558
  }
563
559
  catch (err) {
564
560
  const errorMessage = err instanceof Error ? err.message : String(err);
565
- console.error(`[MultiAgentGraph] Delegate "${sourceAgentId}" -> "${destination}" ERROR:`, errorMessage);
566
- return `[Delegate to "${destination}" failed: ${errorMessage}]`;
561
+ console.error(`[MultiAgentGraph] Handoff "${sourceAgentId}" -> "${destination}" ERROR:`, errorMessage);
562
+ return `[Handoff to "${destination}" failed: ${errorMessage}]`;
567
563
  }
568
564
  }, {
569
565
  name: toolName,
@@ -591,7 +587,7 @@ class MultiAgentGraph extends Graph.StandardGraph {
591
587
  * @param messages - The child agent's output messages
592
588
  * @param agentId - The child agent ID (for fallback message)
593
589
  */
594
- static extractDelegateResult(messages, agentId) {
590
+ static extractHandoffResult(messages, agentId) {
595
591
  for (let i = messages.length - 1; i >= 0; i--) {
596
592
  const msg = messages[i];
597
593
  if (msg.getType() !== 'ai')
@@ -618,17 +614,17 @@ class MultiAgentGraph extends Graph.StandardGraph {
618
614
  return `[Agent "${agentId}" completed but produced no text output]`;
619
615
  }
620
616
  /**
621
- * Truncate delegate result using head/tail strategy (60/40 split).
617
+ * Truncate handoff result using head/tail strategy (60/40 split).
622
618
  * Preserves the beginning (key findings) and end (conclusions).
623
619
  * Matches the TaskTool.truncateResult pattern from Ranger.
624
620
  * @param result - The full result text
625
621
  * @param maxChars - Maximum allowed characters
626
622
  */
627
- static truncateDelegateResult(result, maxChars) {
623
+ static truncateHandoffResult(result, maxChars) {
628
624
  if (!result || result.length <= maxChars) {
629
625
  return result;
630
626
  }
631
- const truncationNotice = '\n\n[... delegate output truncated — middle section omitted to fit parent context ...]\n\n';
627
+ const truncationNotice = '\n\n[... handoff output truncated — middle section omitted to fit parent context ...]\n\n';
632
628
  const available = maxChars - truncationNotice.length;
633
629
  if (available <= 0) {
634
630
  return result.substring(0, maxChars);
@@ -640,17 +636,17 @@ class MultiAgentGraph extends Graph.StandardGraph {
640
636
  result.substring(result.length - tailSize));
641
637
  }
642
638
  /**
643
- * Build a meaningful default description for a delegate tool.
639
+ * Build a meaningful default description for a handoff tool.
644
640
  * @param destContext - AgentContext of the destination agent
645
641
  * @param destinationId - Raw agent ID (fallback)
646
642
  */
647
- buildDefaultDelegateDescription(destContext, destinationId) {
643
+ buildDefaultHandoffDescription(destContext, destinationId) {
648
644
  const displayName = destContext?.name ?? destinationId;
649
645
  const agentDescription = destContext?.description;
650
646
  if (agentDescription != null && agentDescription !== '') {
651
- return `Delegate task to "${displayName}": ${agentDescription}. The agent will execute and return its result.`;
647
+ return `Hand off task to "${displayName}": ${agentDescription}. The agent will execute and return its result.`;
652
648
  }
653
- return `Delegate task to "${displayName}" and receive its result.`;
649
+ return `Hand off task to "${displayName}" and receive its result.`;
654
650
  }
655
651
  /**
656
652
  * Create a complete agent subgraph (similar to createReactAgent)
@@ -671,7 +667,7 @@ class MultiAgentGraph extends Graph.StandardGraph {
671
667
  * @param agentId - The agent ID to check for handoff reception
672
668
  * @returns Object with filtered messages, extracted instructions, source agent, and parallel siblings
673
669
  */
674
- processHandoffReception(messages$1, agentId) {
670
+ processTransferReception(messages$1, agentId) {
675
671
  if (messages$1.length === 0)
676
672
  return null;
677
673
  /**
@@ -700,8 +696,8 @@ class MultiAgentGraph extends Graph.StandardGraph {
700
696
  destinationAgent = toolName.replace(_enum.Constants.LC_TRANSFER_TO_, '');
701
697
  }
702
698
  else if (isConditionalTransfer) {
703
- const handoffDest = candidateMsg.additional_kwargs.handoff_destination;
704
- destinationAgent = typeof handoffDest === 'string' ? handoffDest : null;
699
+ const transferDest = candidateMsg.additional_kwargs.handoff_destination;
700
+ destinationAgent = typeof transferDest === 'string' ? transferDest : null;
705
701
  }
706
702
  /** Check if this transfer targets our agent */
707
703
  if (destinationAgent === agentId) {
@@ -717,7 +713,7 @@ class MultiAgentGraph extends Graph.StandardGraph {
717
713
  const contentStr = typeof toolMessage.content === 'string'
718
714
  ? toolMessage.content
719
715
  : JSON.stringify(toolMessage.content);
720
- const instructionsMatch = contentStr.match(HANDOFF_INSTRUCTIONS_PATTERN);
716
+ const instructionsMatch = contentStr.match(TRANSFER_INSTRUCTIONS_PATTERN);
721
717
  const instructions = instructionsMatch?.[1]?.trim() ?? null;
722
718
  /** Extract source agent name from additional_kwargs */
723
719
  const handoffSourceName = toolMessage.additional_kwargs.handoff_source_name;
@@ -895,7 +891,7 @@ class MultiAgentGraph extends Graph.StandardGraph {
895
891
  };
896
892
  }
897
893
  /**
898
- * Create the multi-agent workflow with dynamic handoffs
894
+ * Create the multi-agent workflow with handoffs, transfers, and sequences
899
895
  */
900
896
  createWorkflow() {
901
897
  const StateAnnotation = langgraph.Annotation.Root({
@@ -921,54 +917,54 @@ class MultiAgentGraph extends Graph.StandardGraph {
921
917
  // Add all agents as complete subgraphs
922
918
  for (const [agentId] of this.agentContexts) {
923
919
  // Get all possible destinations for this agent
924
- const handoffDestinations = new Set();
925
- const directDestinations = new Set();
926
- // Check handoff edges for destinations
927
- for (const edge of this.handoffEdges) {
920
+ const transferDestinations = new Set();
921
+ const sequenceDestinations = new Set();
922
+ // Check transfer edges for destinations
923
+ for (const edge of this.transferEdges) {
928
924
  const sources = Array.isArray(edge.from) ? edge.from : [edge.from];
929
925
  if (sources.includes(agentId) === true) {
930
926
  const dests = Array.isArray(edge.to) ? edge.to : [edge.to];
931
- dests.forEach((dest) => handoffDestinations.add(dest));
927
+ dests.forEach((dest) => transferDestinations.add(dest));
932
928
  }
933
929
  }
934
- // Check direct edges for destinations
935
- for (const edge of this.directEdges) {
930
+ // Check sequence edges for destinations
931
+ for (const edge of this.sequenceEdges) {
936
932
  const sources = Array.isArray(edge.from) ? edge.from : [edge.from];
937
933
  if (sources.includes(agentId) === true) {
938
934
  const dests = Array.isArray(edge.to) ? edge.to : [edge.to];
939
- dests.forEach((dest) => directDestinations.add(dest));
935
+ dests.forEach((dest) => sequenceDestinations.add(dest));
940
936
  }
941
937
  }
942
- /** Check if this agent has BOTH handoff and direct edges */
943
- const hasHandoffEdges = handoffDestinations.size > 0;
944
- const hasDirectEdges = directDestinations.size > 0;
945
- const needsCommandRouting = hasHandoffEdges && hasDirectEdges;
938
+ /** Check if this agent has BOTH transfer and sequence edges */
939
+ const hasTransferEdges = transferDestinations.size > 0;
940
+ const hasSequenceEdges = sequenceDestinations.size > 0;
941
+ const needsCommandRouting = hasTransferEdges && hasSequenceEdges;
946
942
  /** Collect all possible destinations for this agent */
947
943
  const allDestinations = new Set([
948
- ...handoffDestinations,
949
- ...directDestinations,
944
+ ...transferDestinations,
945
+ ...sequenceDestinations,
950
946
  ]);
951
- if (handoffDestinations.size > 0 || directDestinations.size === 0) {
947
+ if (transferDestinations.size > 0 || sequenceDestinations.size === 0) {
952
948
  allDestinations.add(langgraph.END);
953
949
  }
954
950
  /** Agent subgraph (includes agent + tools) */
955
951
  const agentSubgraph = this.createAgentSubgraph(agentId);
956
- /** Register subgraph for delegate tools (lazy reference resolution) */
952
+ /** Register subgraph for handoff tools (lazy reference resolution) */
957
953
  this.subgraphRegistry.set(agentId, agentSubgraph);
958
954
  /** Wrapper function that handles agentMessages channel, handoff reception, and conditional routing */
959
955
  const agentWrapper = async (state, config) => {
960
956
  console.debug(`[MultiAgentGraph] Agent "${agentId}" wrapper ENTRY (messages: ${state.messages.length}, needsCommandRouting: ${needsCommandRouting})`);
961
957
  let result;
962
958
  /**
963
- * Check if this agent is receiving a handoff.
959
+ * Check if this agent is receiving a transfer.
964
960
  * If so, filter out the transfer messages and inject instructions as preamble.
965
961
  * This prevents the receiving agent from seeing the transfer as "completed work"
966
962
  * and prematurely producing an end token.
967
963
  */
968
- const handoffContext = this.processHandoffReception(state.messages, agentId);
969
- if (handoffContext !== null) {
970
- const { filteredMessages, instructions, sourceAgentName, parallelSiblings, } = handoffContext;
971
- console.debug(`[MultiAgentGraph] Agent "${agentId}" receiving handoff from "${sourceAgentName}" (instructions: ${instructions != null}, parallelSiblings: ${parallelSiblings.length})`);
964
+ const transferContext = this.processTransferReception(state.messages, agentId);
965
+ if (transferContext !== null) {
966
+ const { filteredMessages, instructions, sourceAgentName, parallelSiblings, } = transferContext;
967
+ console.debug(`[MultiAgentGraph] Agent "${agentId}" receiving transfer from "${sourceAgentName}" (instructions: ${instructions != null}, parallelSiblings: ${parallelSiblings.length})`);
972
968
  /**
973
969
  * Set handoff context on the receiving agent.
974
970
  * Uses pre-computed graph position for depth and parallel info.
@@ -1085,24 +1081,24 @@ class MultiAgentGraph extends Graph.StandardGraph {
1085
1081
  /** Track the last agent that produced output for continuation support */
1086
1082
  this.lastActiveAgentId = agentId;
1087
1083
  console.debug(`[MultiAgentGraph] Agent "${agentId}" wrapper EXIT (result messages: ${result.messages.length})`);
1088
- /** If agent has both handoff and direct edges, use Command for exclusive routing */
1084
+ /** If agent has both transfer and sequence edges, use Command for exclusive routing */
1089
1085
  if (needsCommandRouting) {
1090
- /** Check if a handoff occurred */
1086
+ /** Check if a transfer occurred */
1091
1087
  const lastMessage = result.messages[result.messages.length - 1];
1092
1088
  if (lastMessage != null &&
1093
1089
  lastMessage.getType() === 'tool' &&
1094
1090
  typeof lastMessage.name === 'string' &&
1095
1091
  lastMessage.name.startsWith(_enum.Constants.LC_TRANSFER_TO_)) {
1096
- /** Handoff occurred - extract destination and navigate there exclusively */
1097
- const handoffDest = lastMessage.name.replace(_enum.Constants.LC_TRANSFER_TO_, '');
1098
- console.debug(`[MultiAgentGraph] Command routing: "${agentId}" -> handoff to "${handoffDest}" (direct edges skipped: [${Array.from(directDestinations).join(', ')}])`);
1092
+ /** Transfer occurred - extract destination and navigate there exclusively */
1093
+ const transferDest = lastMessage.name.replace(_enum.Constants.LC_TRANSFER_TO_, '');
1094
+ console.debug(`[MultiAgentGraph] Command routing: "${agentId}" -> transfer to "${transferDest}" (sequence edges skipped: [${Array.from(sequenceDestinations).join(', ')}])`);
1099
1095
  /** Validate destination agent exists */
1100
- if (!this.agentContexts.has(handoffDest)) {
1096
+ if (!this.agentContexts.has(transferDest)) {
1101
1097
  const availableAgents = Array.from(this.agentContexts.keys()).join(', ');
1102
- console.error(`[MultiAgentGraph] Handoff to non-existent agent "${handoffDest}". Available: ${availableAgents}`);
1098
+ console.error(`[MultiAgentGraph] Transfer to non-existent agent "${transferDest}". Available: ${availableAgents}`);
1103
1099
  /** Return error to model so it can self-correct */
1104
1100
  const errorMsg = new messages.ToolMessage({
1105
- content: `Transfer failed: agent "${handoffDest}" does not exist. Available agents: ${availableAgents}. Please choose a valid agent to transfer to.`,
1101
+ content: `Transfer failed: agent "${transferDest}" does not exist. Available agents: ${availableAgents}. Please choose a valid agent to transfer to.`,
1106
1102
  tool_call_id: lastMessage.tool_call_id,
1107
1103
  name: lastMessage.name,
1108
1104
  });
@@ -1112,7 +1108,7 @@ class MultiAgentGraph extends Graph.StandardGraph {
1112
1108
  };
1113
1109
  }
1114
1110
  /** Pre-handoff context compaction: if receiving agent has smaller budget */
1115
- const receiverContext = this.agentContexts.get(handoffDest);
1111
+ const receiverContext = this.agentContexts.get(transferDest);
1116
1112
  const senderContext = this.agentContexts.get(agentId);
1117
1113
  if (receiverContext?.maxContextTokens != null &&
1118
1114
  senderContext?.tokenCounter != null &&
@@ -1124,7 +1120,7 @@ class MultiAgentGraph extends Graph.StandardGraph {
1124
1120
  const receiverBudget = receiverContext.maxContextTokens;
1125
1121
  if (currentSize > receiverBudget * 0.7) {
1126
1122
  console.warn(`[MultiAgentGraph] Pre-handoff compaction: context (${currentSize} tokens) exceeds ` +
1127
- `70% of receiver "${handoffDest}" budget (${receiverBudget} tokens)`);
1123
+ `70% of receiver "${transferDest}" budget (${receiverBudget} tokens)`);
1128
1124
  /** Generate handoff briefing */
1129
1125
  const senderName = senderContext.name ?? agentId;
1130
1126
  if (senderContext.summarizeCallback) {
@@ -1136,8 +1132,8 @@ class MultiAgentGraph extends Graph.StandardGraph {
1136
1132
  summaryBudget: Math.floor(receiverBudget * 0.2),
1137
1133
  isMultiAgent: true,
1138
1134
  agentWorkflowState: {
1139
- currentAgentId: handoffDest,
1140
- agentChain: [agentId, handoffDest],
1135
+ currentAgentId: transferDest,
1136
+ agentChain: [agentId, transferDest],
1141
1137
  pendingAgents: [],
1142
1138
  },
1143
1139
  });
@@ -1175,13 +1171,13 @@ class MultiAgentGraph extends Graph.StandardGraph {
1175
1171
  }
1176
1172
  return new langgraph.Command({
1177
1173
  update: result,
1178
- goto: handoffDest,
1174
+ goto: transferDest,
1179
1175
  });
1180
1176
  }
1181
1177
  else {
1182
- /** No handoff - proceed with direct edges */
1183
- console.debug(`[MultiAgentGraph] Command routing: "${agentId}" -> no handoff, following direct edges: [${Array.from(directDestinations).join(', ')}]`);
1184
- const directDests = Array.from(directDestinations);
1178
+ /** No transfer - proceed with sequence edges */
1179
+ console.debug(`[MultiAgentGraph] Command routing: "${agentId}" -> no transfer, following sequence edges: [${Array.from(sequenceDestinations).join(', ')}]`);
1180
+ const directDests = Array.from(sequenceDestinations);
1185
1181
  if (directDests.length === 1) {
1186
1182
  return new langgraph.Command({
1187
1183
  update: result,
@@ -1212,11 +1208,11 @@ class MultiAgentGraph extends Graph.StandardGraph {
1212
1208
  builder.addEdge(langgraph.START, startNode);
1213
1209
  }
1214
1210
  /**
1215
- * Add direct edges for automatic transitions
1211
+ * Add sequence edges for automatic transitions
1216
1212
  * Group edges by destination to handle fan-in scenarios
1217
1213
  */
1218
1214
  const edgesByDestination = new Map();
1219
- for (const edge of this.directEdges) {
1215
+ for (const edge of this.sequenceEdges) {
1220
1216
  const destinations = Array.isArray(edge.to) ? edge.to : [edge.to];
1221
1217
  for (const destination of destinations) {
1222
1218
  if (!edgesByDestination.has(destination)) {
@@ -1305,17 +1301,17 @@ class MultiAgentGraph extends Graph.StandardGraph {
1305
1301
  for (const edge of edges) {
1306
1302
  const sources = Array.isArray(edge.from) ? edge.from : [edge.from];
1307
1303
  for (const source of sources) {
1308
- /** Check if this source node has both handoff and direct edges */
1309
- const sourceHandoffEdges = this.handoffEdges.filter((e) => {
1304
+ /** Check if this source node has both transfer and sequence edges */
1305
+ const sourceTransferEdges = this.transferEdges.filter((e) => {
1310
1306
  const eSources = Array.isArray(e.from) ? e.from : [e.from];
1311
1307
  return eSources.includes(source);
1312
1308
  });
1313
- const sourceDirectEdges = this.directEdges.filter((e) => {
1309
+ const sourceSequenceEdges = this.sequenceEdges.filter((e) => {
1314
1310
  const eSources = Array.isArray(e.from) ? e.from : [e.from];
1315
1311
  return eSources.includes(source);
1316
1312
  });
1317
1313
  /** Skip adding edge if source uses Command routing (has both types) */
1318
- if (sourceHandoffEdges.length > 0 && sourceDirectEdges.length > 0) {
1314
+ if (sourceTransferEdges.length > 0 && sourceSequenceEdges.length > 0) {
1319
1315
  continue;
1320
1316
  }
1321
1317
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment