illuma-agents 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. package/LICENSE +25 -21
  2. package/dist/cjs/agents/AgentContext.cjs +222 -0
  3. package/dist/cjs/agents/AgentContext.cjs.map +1 -0
  4. package/dist/cjs/common/enum.cjs +7 -6
  5. package/dist/cjs/common/enum.cjs.map +1 -1
  6. package/dist/cjs/events.cjs +7 -5
  7. package/dist/cjs/events.cjs.map +1 -1
  8. package/dist/cjs/graphs/Graph.cjs +328 -207
  9. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  10. package/dist/cjs/graphs/MultiAgentGraph.cjs +507 -0
  11. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -0
  12. package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
  13. package/dist/cjs/llm/google/index.cjs.map +1 -1
  14. package/dist/cjs/llm/ollama/index.cjs.map +1 -1
  15. package/dist/cjs/llm/openai/index.cjs +35 -0
  16. package/dist/cjs/llm/openai/index.cjs.map +1 -1
  17. package/dist/cjs/llm/openai/utils/index.cjs +3 -1
  18. package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
  19. package/dist/cjs/llm/openrouter/index.cjs.map +1 -1
  20. package/dist/cjs/llm/providers.cjs +0 -2
  21. package/dist/cjs/llm/providers.cjs.map +1 -1
  22. package/dist/cjs/llm/vertexai/index.cjs.map +1 -1
  23. package/dist/cjs/main.cjs +12 -1
  24. package/dist/cjs/main.cjs.map +1 -1
  25. package/dist/cjs/messages/cache.cjs +123 -0
  26. package/dist/cjs/messages/cache.cjs.map +1 -0
  27. package/dist/cjs/messages/content.cjs +53 -0
  28. package/dist/cjs/messages/content.cjs.map +1 -0
  29. package/dist/cjs/messages/format.cjs +17 -29
  30. package/dist/cjs/messages/format.cjs.map +1 -1
  31. package/dist/cjs/run.cjs +119 -74
  32. package/dist/cjs/run.cjs.map +1 -1
  33. package/dist/cjs/stream.cjs +77 -73
  34. package/dist/cjs/stream.cjs.map +1 -1
  35. package/dist/cjs/tools/Calculator.cjs +45 -0
  36. package/dist/cjs/tools/Calculator.cjs.map +1 -0
  37. package/dist/cjs/tools/CodeExecutor.cjs +22 -22
  38. package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
  39. package/dist/cjs/tools/ToolNode.cjs +5 -3
  40. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  41. package/dist/cjs/tools/handlers.cjs +20 -20
  42. package/dist/cjs/tools/handlers.cjs.map +1 -1
  43. package/dist/cjs/utils/events.cjs +31 -0
  44. package/dist/cjs/utils/events.cjs.map +1 -0
  45. package/dist/cjs/utils/handlers.cjs +70 -0
  46. package/dist/cjs/utils/handlers.cjs.map +1 -0
  47. package/dist/cjs/utils/tokens.cjs +54 -7
  48. package/dist/cjs/utils/tokens.cjs.map +1 -1
  49. package/dist/esm/agents/AgentContext.mjs +220 -0
  50. package/dist/esm/agents/AgentContext.mjs.map +1 -0
  51. package/dist/esm/common/enum.mjs +7 -6
  52. package/dist/esm/common/enum.mjs.map +1 -1
  53. package/dist/esm/events.mjs +7 -5
  54. package/dist/esm/events.mjs.map +1 -1
  55. package/dist/esm/graphs/Graph.mjs +330 -209
  56. package/dist/esm/graphs/Graph.mjs.map +1 -1
  57. package/dist/esm/graphs/MultiAgentGraph.mjs +505 -0
  58. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -0
  59. package/dist/esm/llm/anthropic/index.mjs.map +1 -1
  60. package/dist/esm/llm/google/index.mjs.map +1 -1
  61. package/dist/esm/llm/ollama/index.mjs.map +1 -1
  62. package/dist/esm/llm/openai/index.mjs +35 -0
  63. package/dist/esm/llm/openai/index.mjs.map +1 -1
  64. package/dist/esm/llm/openai/utils/index.mjs +3 -1
  65. package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
  66. package/dist/esm/llm/openrouter/index.mjs.map +1 -1
  67. package/dist/esm/llm/providers.mjs +0 -2
  68. package/dist/esm/llm/providers.mjs.map +1 -1
  69. package/dist/esm/llm/vertexai/index.mjs.map +1 -1
  70. package/dist/esm/main.mjs +7 -2
  71. package/dist/esm/main.mjs.map +1 -1
  72. package/dist/esm/messages/cache.mjs +120 -0
  73. package/dist/esm/messages/cache.mjs.map +1 -0
  74. package/dist/esm/messages/content.mjs +51 -0
  75. package/dist/esm/messages/content.mjs.map +1 -0
  76. package/dist/esm/messages/format.mjs +18 -29
  77. package/dist/esm/messages/format.mjs.map +1 -1
  78. package/dist/esm/run.mjs +119 -74
  79. package/dist/esm/run.mjs.map +1 -1
  80. package/dist/esm/stream.mjs +77 -73
  81. package/dist/esm/stream.mjs.map +1 -1
  82. package/dist/esm/tools/Calculator.mjs +24 -0
  83. package/dist/esm/tools/Calculator.mjs.map +1 -0
  84. package/dist/esm/tools/CodeExecutor.mjs +22 -22
  85. package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
  86. package/dist/esm/tools/ToolNode.mjs +5 -3
  87. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  88. package/dist/esm/tools/handlers.mjs +20 -20
  89. package/dist/esm/tools/handlers.mjs.map +1 -1
  90. package/dist/esm/utils/events.mjs +29 -0
  91. package/dist/esm/utils/events.mjs.map +1 -0
  92. package/dist/esm/utils/handlers.mjs +68 -0
  93. package/dist/esm/utils/handlers.mjs.map +1 -0
  94. package/dist/esm/utils/tokens.mjs +54 -8
  95. package/dist/esm/utils/tokens.mjs.map +1 -1
  96. package/dist/types/agents/AgentContext.d.ts +94 -0
  97. package/dist/types/common/enum.d.ts +9 -7
  98. package/dist/types/events.d.ts +3 -3
  99. package/dist/types/graphs/Graph.d.ts +60 -66
  100. package/dist/types/graphs/MultiAgentGraph.d.ts +47 -0
  101. package/dist/types/graphs/index.d.ts +1 -0
  102. package/dist/types/index.d.ts +1 -0
  103. package/dist/types/llm/openai/index.d.ts +10 -0
  104. package/dist/types/messages/cache.d.ts +20 -0
  105. package/dist/types/messages/content.d.ts +7 -0
  106. package/dist/types/messages/format.d.ts +1 -7
  107. package/dist/types/messages/index.d.ts +2 -0
  108. package/dist/types/messages/reducer.d.ts +9 -0
  109. package/dist/types/run.d.ts +16 -10
  110. package/dist/types/stream.d.ts +4 -3
  111. package/dist/types/tools/Calculator.d.ts +8 -0
  112. package/dist/types/tools/ToolNode.d.ts +1 -1
  113. package/dist/types/tools/handlers.d.ts +9 -7
  114. package/dist/types/tools/search/tool.d.ts +4 -4
  115. package/dist/types/types/graph.d.ts +124 -11
  116. package/dist/types/types/llm.d.ts +13 -9
  117. package/dist/types/types/messages.d.ts +4 -0
  118. package/dist/types/types/run.d.ts +46 -8
  119. package/dist/types/types/stream.d.ts +3 -2
  120. package/dist/types/utils/events.d.ts +6 -0
  121. package/dist/types/utils/handlers.d.ts +34 -0
  122. package/dist/types/utils/index.d.ts +1 -0
  123. package/dist/types/utils/tokens.d.ts +24 -0
  124. package/package.json +162 -145
  125. package/src/agents/AgentContext.ts +323 -0
  126. package/src/common/enum.ts +177 -176
  127. package/src/events.ts +197 -191
  128. package/src/graphs/Graph.ts +1058 -846
  129. package/src/graphs/MultiAgentGraph.ts +598 -0
  130. package/src/graphs/index.ts +2 -1
  131. package/src/index.ts +25 -24
  132. package/src/llm/anthropic/index.ts +413 -413
  133. package/src/llm/google/index.ts +222 -222
  134. package/src/llm/google/utils/zod_to_genai_parameters.ts +86 -88
  135. package/src/llm/ollama/index.ts +92 -92
  136. package/src/llm/openai/index.ts +894 -853
  137. package/src/llm/openai/utils/index.ts +920 -918
  138. package/src/llm/openrouter/index.ts +60 -60
  139. package/src/llm/providers.ts +55 -57
  140. package/src/llm/vertexai/index.ts +360 -360
  141. package/src/messages/cache.test.ts +461 -0
  142. package/src/messages/cache.ts +151 -0
  143. package/src/messages/content.test.ts +362 -0
  144. package/src/messages/content.ts +63 -0
  145. package/src/messages/format.ts +611 -625
  146. package/src/messages/formatAgentMessages.test.ts +1144 -917
  147. package/src/messages/index.ts +6 -4
  148. package/src/messages/reducer.ts +80 -0
  149. package/src/run.ts +447 -381
  150. package/src/scripts/abort.ts +157 -138
  151. package/src/scripts/ant_web_search.ts +158 -158
  152. package/src/scripts/cli.ts +172 -167
  153. package/src/scripts/cli2.ts +133 -125
  154. package/src/scripts/cli3.ts +184 -178
  155. package/src/scripts/cli4.ts +191 -184
  156. package/src/scripts/cli5.ts +191 -184
  157. package/src/scripts/code_exec.ts +213 -214
  158. package/src/scripts/code_exec_simple.ts +147 -129
  159. package/src/scripts/content.ts +138 -120
  160. package/src/scripts/handoff-test.ts +135 -0
  161. package/src/scripts/multi-agent-chain.ts +278 -0
  162. package/src/scripts/multi-agent-conditional.ts +220 -0
  163. package/src/scripts/multi-agent-document-review-chain.ts +197 -0
  164. package/src/scripts/multi-agent-hybrid-flow.ts +310 -0
  165. package/src/scripts/multi-agent-parallel.ts +343 -0
  166. package/src/scripts/multi-agent-sequence.ts +212 -0
  167. package/src/scripts/multi-agent-supervisor.ts +364 -0
  168. package/src/scripts/multi-agent-test.ts +186 -0
  169. package/src/scripts/search.ts +146 -150
  170. package/src/scripts/simple.ts +225 -225
  171. package/src/scripts/stream.ts +140 -122
  172. package/src/scripts/test-custom-prompt-key.ts +145 -0
  173. package/src/scripts/test-handoff-input.ts +170 -0
  174. package/src/scripts/test-multi-agent-list-handoff.ts +261 -0
  175. package/src/scripts/test-tools-before-handoff.ts +222 -0
  176. package/src/scripts/tools.ts +153 -155
  177. package/src/specs/agent-handoffs.test.ts +889 -0
  178. package/src/specs/anthropic.simple.test.ts +320 -317
  179. package/src/specs/azure.simple.test.ts +325 -316
  180. package/src/specs/openai.simple.test.ts +311 -316
  181. package/src/specs/openrouter.simple.test.ts +107 -0
  182. package/src/specs/prune.test.ts +758 -763
  183. package/src/specs/reasoning.test.ts +201 -165
  184. package/src/specs/thinking-prune.test.ts +769 -703
  185. package/src/specs/token-memoization.test.ts +39 -0
  186. package/src/stream.ts +664 -651
  187. package/src/tools/Calculator.test.ts +278 -0
  188. package/src/tools/Calculator.ts +25 -0
  189. package/src/tools/CodeExecutor.ts +220 -220
  190. package/src/tools/ToolNode.ts +170 -170
  191. package/src/tools/handlers.ts +341 -336
  192. package/src/types/graph.ts +372 -185
  193. package/src/types/llm.ts +141 -140
  194. package/src/types/messages.ts +4 -0
  195. package/src/types/run.ts +128 -89
  196. package/src/types/stream.ts +401 -400
  197. package/src/utils/events.ts +32 -0
  198. package/src/utils/handlers.ts +107 -0
  199. package/src/utils/index.ts +6 -5
  200. package/src/utils/llmConfig.ts +183 -183
  201. package/src/utils/tokens.ts +129 -70
  202. package/dist/types/scripts/abort.d.ts +0 -1
  203. package/dist/types/scripts/ant_web_search.d.ts +0 -1
  204. package/dist/types/scripts/args.d.ts +0 -7
  205. package/dist/types/scripts/caching.d.ts +0 -1
  206. package/dist/types/scripts/cli.d.ts +0 -1
  207. package/dist/types/scripts/cli2.d.ts +0 -1
  208. package/dist/types/scripts/cli3.d.ts +0 -1
  209. package/dist/types/scripts/cli4.d.ts +0 -1
  210. package/dist/types/scripts/cli5.d.ts +0 -1
  211. package/dist/types/scripts/code_exec.d.ts +0 -1
  212. package/dist/types/scripts/code_exec_files.d.ts +0 -1
  213. package/dist/types/scripts/code_exec_simple.d.ts +0 -1
  214. package/dist/types/scripts/content.d.ts +0 -1
  215. package/dist/types/scripts/empty_input.d.ts +0 -1
  216. package/dist/types/scripts/image.d.ts +0 -1
  217. package/dist/types/scripts/memory.d.ts +0 -1
  218. package/dist/types/scripts/search.d.ts +0 -1
  219. package/dist/types/scripts/simple.d.ts +0 -1
  220. package/dist/types/scripts/stream.d.ts +0 -1
  221. package/dist/types/scripts/thinking.d.ts +0 -1
  222. package/dist/types/scripts/tools.d.ts +0 -1
  223. package/dist/types/specs/spec.utils.d.ts +0 -1
  224. package/dist/types/tools/example.d.ts +0 -78
  225. package/src/tools/example.ts +0 -129
@@ -0,0 +1,364 @@
1
+ import { config } from 'dotenv';
2
+ config();
3
+
4
+ import { HumanMessage, BaseMessage } from '@langchain/core/messages';
5
+ import type * as t from '@/types';
6
+ import { ChatModelStreamHandler, createContentAggregator } from '@/stream';
7
+ import { ToolEndHandler, ModelEndHandler } from '@/events';
8
+ import { Providers, GraphEvents } from '@/common';
9
+ import { sleep } from '@/utils/run';
10
+ import { Run } from '@/run';
11
+
12
+ const conversationHistory: BaseMessage[] = [];
13
+
14
+ /**
15
+ * Example of supervisor-based multi-agent system
16
+ *
17
+ * The supervisor has handoff tools for 5 different specialists.
18
+ * To demonstrate the concept while respecting LangGraph constraints,
19
+ * we show two approaches:
20
+ *
21
+ * 1. All 5 specialists exist but share the same adaptive configuration
22
+ * 2. Only 2 agents total by using a single adaptive specialist (requires workaround)
23
+ */
24
+ async function testSupervisorMultiAgent() {
25
+ console.log('Testing Supervisor-Based Multi-Agent System...\n');
26
+
27
+ // NOTE: To truly have only 2 agents with 5 handoff tools, you would need:
28
+ // 1. Custom tool implementation (see multi-agent-supervisor-mock.ts)
29
+ // 2. Or modify MultiAgentGraph to support "virtual" agents
30
+ // 3. Or use a single conditional edge with role parameter
31
+ //
32
+ // This example shows the concept using 6 agents that share configuration
33
+
34
+ // Set up content aggregator
35
+ const { contentParts, aggregateContent } = createContentAggregator();
36
+
37
+ // Define configurations for all possible specialists
38
+ const specialistConfigs = {
39
+ data_analyst: {
40
+ provider: Providers.OPENAI,
41
+ clientOptions: {
42
+ modelName: 'gpt-4.1',
43
+ apiKey: process.env.OPENAI_API_KEY,
44
+ },
45
+ instructions: `You are a Data Analyst specialist. Your expertise includes:
46
+ - Statistical analysis and data visualization
47
+ - SQL queries and database optimization
48
+ - Python/R for data science
49
+ - Machine learning model evaluation
50
+ - A/B testing and experiment design
51
+
52
+ Follow the supervisor's specific instructions carefully.`,
53
+ maxContextTokens: 8000,
54
+ },
55
+ security_expert: {
56
+ provider: Providers.OPENAI,
57
+ clientOptions: {
58
+ modelName: 'gpt-4.1',
59
+ apiKey: process.env.OPENAI_API_KEY,
60
+ },
61
+ instructions: `You are a Security Expert. Your expertise includes:
62
+ - Cybersecurity best practices
63
+ - Vulnerability assessment and penetration testing
64
+ - Security architecture and threat modeling
65
+ - Compliance (GDPR, HIPAA, SOC2, etc.)
66
+ - Incident response and forensics
67
+
68
+ Follow the supervisor's specific instructions carefully.`,
69
+ maxContextTokens: 8000,
70
+ },
71
+ product_designer: {
72
+ provider: Providers.OPENAI,
73
+ clientOptions: {
74
+ modelName: 'gpt-4.1',
75
+ apiKey: process.env.OPENAI_API_KEY,
76
+ },
77
+ instructions: `You are a Product Designer. Your expertise includes:
78
+ - User experience (UX) design principles
79
+ - User interface (UI) design and prototyping
80
+ - Design systems and component libraries
81
+ - User research and usability testing
82
+ - Accessibility and inclusive design
83
+
84
+ Follow the supervisor's specific instructions carefully.`,
85
+ maxContextTokens: 8000,
86
+ },
87
+ devops_engineer: {
88
+ provider: Providers.OPENAI,
89
+ clientOptions: {
90
+ modelName: 'gpt-4.1',
91
+ apiKey: process.env.OPENAI_API_KEY,
92
+ },
93
+ instructions: `You are a DevOps Engineer. Your expertise includes:
94
+ - CI/CD pipeline design and optimization
95
+ - Infrastructure as Code (Terraform, CloudFormation)
96
+ - Container orchestration (Kubernetes, Docker)
97
+ - Cloud platforms (AWS, GCP, Azure)
98
+ - Monitoring, logging, and observability
99
+
100
+ Follow the supervisor's specific instructions carefully.`,
101
+ maxContextTokens: 8000,
102
+ },
103
+ legal_advisor: {
104
+ provider: Providers.OPENAI,
105
+ clientOptions: {
106
+ modelName: 'gpt-4.1',
107
+ apiKey: process.env.OPENAI_API_KEY,
108
+ },
109
+ instructions: `You are a Legal Advisor specializing in technology. Your expertise includes:
110
+ - Software licensing and open source compliance
111
+ - Data privacy and protection laws
112
+ - Intellectual property and patents
113
+ - Contract review and negotiation
114
+ - Regulatory compliance for tech companies
115
+
116
+ Follow the supervisor's specific instructions carefully.`,
117
+ maxContextTokens: 8000,
118
+ },
119
+ };
120
+
121
+ // Track which specialist role was selected
122
+ let selectedRole = '';
123
+ let roleInstructions = '';
124
+
125
+ // Create custom handlers
126
+ const customHandlers = {
127
+ [GraphEvents.TOOL_END]: new ToolEndHandler(),
128
+ [GraphEvents.CHAT_MODEL_END]: new ModelEndHandler(),
129
+ [GraphEvents.CHAT_MODEL_STREAM]: new ChatModelStreamHandler(),
130
+ [GraphEvents.ON_RUN_STEP]: {
131
+ handle: (
132
+ event: GraphEvents.ON_RUN_STEP,
133
+ data: t.StreamEventData
134
+ ): void => {
135
+ const runStepData = data as any;
136
+ if (runStepData?.name) {
137
+ console.log(`\n[${runStepData.name}] Processing...`);
138
+ }
139
+ aggregateContent({ event, data: data as t.RunStep });
140
+ },
141
+ },
142
+ [GraphEvents.ON_RUN_STEP_COMPLETED]: {
143
+ handle: (
144
+ event: GraphEvents.ON_RUN_STEP_COMPLETED,
145
+ data: t.StreamEventData
146
+ ): void => {
147
+ aggregateContent({
148
+ event,
149
+ data: data as unknown as { result: t.ToolEndEvent },
150
+ });
151
+ },
152
+ },
153
+ [GraphEvents.ON_MESSAGE_DELTA]: {
154
+ handle: (
155
+ event: GraphEvents.ON_MESSAGE_DELTA,
156
+ data: t.StreamEventData
157
+ ): void => {
158
+ console.dir(data, { depth: null });
159
+ aggregateContent({ event, data: data as t.MessageDeltaEvent });
160
+ },
161
+ },
162
+ [GraphEvents.TOOL_START]: {
163
+ handle: (
164
+ _event: string,
165
+ data: t.StreamEventData,
166
+ metadata?: Record<string, unknown>
167
+ ): void => {
168
+ const toolData = data as any;
169
+ if (toolData?.name?.includes('transfer_to_')) {
170
+ const specialist = toolData.name.replace('transfer_to_', '');
171
+ console.log(`\n🔀 Transferring to ${specialist}...`);
172
+ selectedRole = specialist;
173
+ }
174
+ },
175
+ },
176
+ };
177
+
178
+ // Function to create the graph with supervisor having multiple handoff options
179
+ function createSupervisorGraph(): t.RunConfig {
180
+ console.log(`\nCreating graph with supervisor and 5 specialist agents.`);
181
+ console.log('All specialists share the same adaptive configuration.\n');
182
+
183
+ // Define the adaptive specialist configuration that will be reused
184
+ const specialistConfig = {
185
+ provider: Providers.OPENAI,
186
+ clientOptions: {
187
+ modelName: 'gpt-4.1',
188
+ apiKey: process.env.OPENAI_API_KEY,
189
+ },
190
+ instructions: `You are an Adaptive Specialist. Your agent ID indicates your role:
191
+
192
+ - data_analyst: Focus on statistical analysis, metrics, ML evaluation, A/B testing
193
+ - security_expert: Focus on cybersecurity, vulnerability assessment, compliance
194
+ - product_designer: Focus on UX/UI design, user research, accessibility
195
+ - devops_engineer: Focus on CI/CD, infrastructure, cloud platforms, monitoring
196
+ - legal_advisor: Focus on licensing, privacy laws, contracts, regulatory compliance
197
+
198
+ The supervisor will provide specific instructions. Follow them while maintaining your expert perspective.`,
199
+ maxContextTokens: 8000,
200
+ };
201
+
202
+ // Create the graph with supervisor and all 5 specialists
203
+ // All specialists share the same adaptive configuration
204
+ const agents: t.AgentInputs[] = [
205
+ {
206
+ agentId: 'supervisor',
207
+ provider: Providers.OPENAI,
208
+ clientOptions: {
209
+ modelName: 'gpt-4.1-mini',
210
+ apiKey: process.env.OPENAI_API_KEY,
211
+ },
212
+ instructions: `You are a Task Supervisor with access to 5 specialist agents:
213
+ 1. transfer_to_data_analyst - For statistical analysis and metrics
214
+ 2. transfer_to_security_expert - For cybersecurity and vulnerability assessment
215
+ 3. transfer_to_product_designer - For UX/UI design
216
+ 4. transfer_to_devops_engineer - For infrastructure and deployment
217
+ 5. transfer_to_legal_advisor - For compliance and licensing
218
+
219
+ Your role is to:
220
+ 1. Analyze the incoming request
221
+ 2. Decide which specialist is best suited
222
+ 3. Use the appropriate transfer tool (e.g., transfer_to_data_analyst)
223
+ 4. Provide specific instructions to guide their work
224
+
225
+ Be specific about what you need from the specialist.`,
226
+ maxContextTokens: 8000,
227
+ },
228
+ // Include all 5 specialists with the same adaptive configuration
229
+ {
230
+ agentId: 'data_analyst',
231
+ ...specialistConfig,
232
+ },
233
+ {
234
+ agentId: 'security_expert',
235
+ ...specialistConfig,
236
+ },
237
+ {
238
+ agentId: 'product_designer',
239
+ ...specialistConfig,
240
+ },
241
+ {
242
+ agentId: 'devops_engineer',
243
+ ...specialistConfig,
244
+ },
245
+ {
246
+ agentId: 'legal_advisor',
247
+ ...specialistConfig,
248
+ },
249
+ ];
250
+
251
+ // Create edges from supervisor to all 5 specialists
252
+ const edges: t.GraphEdge[] = [
253
+ {
254
+ from: 'supervisor',
255
+ to: 'data_analyst',
256
+ description:
257
+ 'Transfer to data analyst for statistical analysis and metrics',
258
+ edgeType: 'handoff',
259
+ },
260
+ {
261
+ from: 'supervisor',
262
+ to: 'security_expert',
263
+ description: 'Transfer to security expert for cybersecurity assessment',
264
+ edgeType: 'handoff',
265
+ },
266
+ {
267
+ from: 'supervisor',
268
+ to: 'product_designer',
269
+ description: 'Transfer to product designer for UX/UI design',
270
+ edgeType: 'handoff',
271
+ },
272
+ {
273
+ from: 'supervisor',
274
+ to: 'devops_engineer',
275
+ description:
276
+ 'Transfer to DevOps engineer for infrastructure and deployment',
277
+ edgeType: 'handoff',
278
+ },
279
+ {
280
+ from: 'supervisor',
281
+ to: 'legal_advisor',
282
+ description: 'Transfer to legal advisor for compliance and licensing',
283
+ edgeType: 'handoff',
284
+ },
285
+ ];
286
+
287
+ return {
288
+ runId: `supervisor-multi-agent-${Date.now()}`,
289
+ graphConfig: {
290
+ type: 'multi-agent',
291
+ agents,
292
+ edges,
293
+ },
294
+ customHandlers,
295
+ returnContent: true,
296
+ };
297
+ }
298
+
299
+ try {
300
+ // Test with different queries
301
+ const testQueries = [
302
+ 'How can we analyze user engagement metrics to improve our product?',
303
+ // 'What security measures should we implement for our new API?',
304
+ // 'Can you help design a better onboarding flow for our mobile app?',
305
+ // 'We need to set up a CI/CD pipeline for our microservices.',
306
+ // 'What are the legal implications of using GPL-licensed code in our product?',
307
+ ];
308
+
309
+ const config = {
310
+ configurable: {
311
+ thread_id: 'supervisor-conversation-1',
312
+ },
313
+ streamMode: 'values',
314
+ version: 'v2' as const,
315
+ };
316
+
317
+ for (const query of testQueries) {
318
+ console.log(`\n${'='.repeat(60)}`);
319
+ console.log(`USER QUERY: "${query}"`);
320
+ console.log('='.repeat(60));
321
+
322
+ // Reset conversation
323
+ conversationHistory.length = 0;
324
+ conversationHistory.push(new HumanMessage(query));
325
+
326
+ // Create graph with supervisor having 5 handoff tools to 1 adaptive specialist
327
+ const runConfig = createSupervisorGraph();
328
+ const run = await Run.create(runConfig);
329
+
330
+ console.log('Processing request...');
331
+
332
+ // Process with streaming
333
+ const inputs = {
334
+ messages: conversationHistory,
335
+ };
336
+
337
+ const finalContentParts = await run.processStream(inputs, config);
338
+ const finalMessages = run.getRunMessages();
339
+
340
+ if (finalMessages) {
341
+ conversationHistory.push(...finalMessages);
342
+ }
343
+
344
+ // Show summary
345
+ console.log(`\n${'─'.repeat(60)}`);
346
+ console.log(`Agents in graph: 6 total (supervisor + 5 specialists)`);
347
+ console.log(`All specialists share the same adaptive configuration`);
348
+ console.log(
349
+ `Supervisor tools: transfer_to_data_analyst, transfer_to_security_expert,`
350
+ );
351
+ console.log(
352
+ ` transfer_to_product_designer, transfer_to_devops_engineer,`
353
+ );
354
+ console.log(` transfer_to_legal_advisor`);
355
+ console.log('─'.repeat(60));
356
+ }
357
+ await sleep(3000);
358
+ } catch (error) {
359
+ console.error('Error in supervisor multi-agent test:', error);
360
+ }
361
+ }
362
+
363
+ // Run the test
364
+ testSupervisorMultiAgent();
@@ -0,0 +1,186 @@
1
+ import { config } from 'dotenv';
2
+ config();
3
+
4
+ import { HumanMessage, BaseMessage } from '@langchain/core/messages';
5
+ import { Run } from '@/run';
6
+ import { Providers, GraphEvents } from '@/common';
7
+ import { ChatModelStreamHandler, createContentAggregator } from '@/stream';
8
+ import { ToolEndHandler, ModelEndHandler } from '@/events';
9
+ import type * as t from '@/types';
10
+
11
+ const conversationHistory: BaseMessage[] = [];
12
+
13
+ async function testMultiAgentHandoff() {
14
+ console.log('Testing Multi-Agent Handoff System...\n');
15
+
16
+ // Set up content aggregator
17
+ const { contentParts, aggregateContent } = createContentAggregator();
18
+
19
+ // Define agent configurations
20
+ const agents: t.AgentInputs[] = [
21
+ {
22
+ agentId: 'flight_assistant',
23
+ provider: Providers.ANTHROPIC,
24
+ clientOptions: {
25
+ modelName: 'claude-haiku-4-5',
26
+ apiKey: process.env.ANTHROPIC_API_KEY,
27
+ },
28
+ instructions:
29
+ 'You are a flight booking assistant. Help users book flights between airports.',
30
+ maxContextTokens: 28000,
31
+ },
32
+ {
33
+ agentId: 'hotel_assistant',
34
+ provider: Providers.ANTHROPIC,
35
+ clientOptions: {
36
+ modelName: 'claude-haiku-4-5',
37
+ apiKey: process.env.ANTHROPIC_API_KEY,
38
+ },
39
+ instructions:
40
+ 'You are a hotel booking assistant. Help users book hotel stays.',
41
+ maxContextTokens: 28000,
42
+ },
43
+ ];
44
+
45
+ // Define edges (handoff relationships)
46
+ // These edges create handoff tools that agents can use to transfer control dynamically
47
+ const edges: t.GraphEdge[] = [
48
+ {
49
+ from: 'flight_assistant',
50
+ to: 'hotel_assistant',
51
+ description:
52
+ 'Transfer to hotel booking assistant when user needs hotel assistance',
53
+ // edgeType defaults to 'handoff' for single-to-single edges
54
+ },
55
+ {
56
+ from: 'hotel_assistant',
57
+ to: 'flight_assistant',
58
+ description:
59
+ 'Transfer to flight booking assistant when user needs flight assistance',
60
+ // edgeType defaults to 'handoff' for single-to-single edges
61
+ },
62
+ ];
63
+
64
+ // Create custom handlers similar to examples
65
+ const customHandlers = {
66
+ [GraphEvents.TOOL_END]: new ToolEndHandler(),
67
+ [GraphEvents.CHAT_MODEL_END]: new ModelEndHandler(),
68
+ [GraphEvents.CHAT_MODEL_STREAM]: new ChatModelStreamHandler(),
69
+ [GraphEvents.ON_RUN_STEP_COMPLETED]: {
70
+ handle: (
71
+ event: GraphEvents.ON_RUN_STEP_COMPLETED,
72
+ data: t.StreamEventData
73
+ ): void => {
74
+ console.log('====== ON_RUN_STEP_COMPLETED ======');
75
+ console.dir(data, { depth: null });
76
+ aggregateContent({
77
+ event,
78
+ data: data as unknown as { result: t.ToolEndEvent },
79
+ });
80
+ },
81
+ },
82
+ [GraphEvents.ON_RUN_STEP]: {
83
+ handle: (
84
+ event: GraphEvents.ON_RUN_STEP,
85
+ data: t.StreamEventData
86
+ ): void => {
87
+ console.log('====== ON_RUN_STEP ======');
88
+ console.dir(data, { depth: null });
89
+ aggregateContent({ event, data: data as t.RunStep });
90
+ },
91
+ },
92
+ [GraphEvents.ON_RUN_STEP_DELTA]: {
93
+ handle: (
94
+ event: GraphEvents.ON_RUN_STEP_DELTA,
95
+ data: t.StreamEventData
96
+ ): void => {
97
+ console.log('====== ON_RUN_STEP_DELTA ======');
98
+ console.dir(data, { depth: null });
99
+ aggregateContent({ event, data: data as t.RunStepDeltaEvent });
100
+ },
101
+ },
102
+ [GraphEvents.ON_MESSAGE_DELTA]: {
103
+ handle: (
104
+ event: GraphEvents.ON_MESSAGE_DELTA,
105
+ data: t.StreamEventData
106
+ ): void => {
107
+ console.log('====== ON_MESSAGE_DELTA ======');
108
+ console.dir(data, { depth: null });
109
+ aggregateContent({ event, data: data as t.MessageDeltaEvent });
110
+ },
111
+ },
112
+ [GraphEvents.ON_REASONING_DELTA]: {
113
+ handle: (
114
+ event: GraphEvents.ON_REASONING_DELTA,
115
+ data: t.StreamEventData
116
+ ): void => {
117
+ console.log('====== ON_REASONING_DELTA ======');
118
+ console.dir(data, { depth: null });
119
+ aggregateContent({ event, data: data as t.ReasoningDeltaEvent });
120
+ },
121
+ },
122
+ [GraphEvents.TOOL_START]: {
123
+ handle: (
124
+ _event: string,
125
+ data: t.StreamEventData,
126
+ metadata?: Record<string, unknown>
127
+ ): void => {
128
+ console.log('====== TOOL_START ======');
129
+ console.dir(data, { depth: null });
130
+ },
131
+ },
132
+ };
133
+
134
+ // Create multi-agent run configuration
135
+ const runConfig: t.RunConfig = {
136
+ runId: `multi-agent-test-${Date.now()}`,
137
+ graphConfig: {
138
+ type: 'multi-agent',
139
+ agents,
140
+ edges,
141
+ },
142
+ customHandlers,
143
+ returnContent: true,
144
+ };
145
+
146
+ try {
147
+ // Create and execute the run
148
+ const run = await Run.create(runConfig);
149
+
150
+ const userMessage =
151
+ 'I need to book a flight from Boston to New York, and also need a hotel near Times Square.';
152
+ conversationHistory.push(new HumanMessage(userMessage));
153
+
154
+ console.log('Invoking multi-agent graph...\n');
155
+
156
+ const config = {
157
+ configurable: {
158
+ thread_id: 'multi-agent-conversation-1',
159
+ },
160
+ streamMode: 'values',
161
+ version: 'v2' as const,
162
+ };
163
+
164
+ // Process with streaming
165
+ const inputs = {
166
+ messages: conversationHistory,
167
+ };
168
+
169
+ const finalContentParts = await run.processStream(inputs, config);
170
+ const finalMessages = run.getRunMessages();
171
+
172
+ if (finalMessages) {
173
+ conversationHistory.push(...finalMessages);
174
+ console.log('\n\nConversation history:');
175
+ console.dir(conversationHistory, { depth: null });
176
+ }
177
+
178
+ console.log('\n\nFinal content parts:');
179
+ console.dir(contentParts, { depth: null });
180
+ } catch (error) {
181
+ console.error('Error in multi-agent test:', error);
182
+ }
183
+ }
184
+
185
+ // Run the test
186
+ testMultiAgentHandoff();