@wundr.io/autogen-orchestrator 1.0.2-dev.20260530174250.ef0ec927

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/README.md ADDED
@@ -0,0 +1,1074 @@
1
+ # @wundr.io/autogen-orchestrator
2
+
3
+ AutoGen-style conversational multi-agent orchestration for the Wundr platform. This package
4
+ implements sophisticated patterns for coordinating multiple AI agents in group chat settings with
5
+ configurable speaker selection, termination conditions, and nested chat support.
6
+
7
+ ## Table of Contents
8
+
9
+ - [Installation](#installation)
10
+ - [Quick Start](#quick-start)
11
+ - [Core Concepts](#core-concepts)
12
+ - [Agent Conversation Patterns](#agent-conversation-patterns)
13
+ - [Group Chat Management](#group-chat-management)
14
+ - [Speaker Selection](#speaker-selection)
15
+ - [Message Routing](#message-routing)
16
+ - [Conversation History Tracking](#conversation-history-tracking)
17
+ - [Termination Handling](#termination-handling)
18
+ - [Nested Chats](#nested-chats)
19
+ - [Integration with Other Orchestrators](#integration-with-other-orchestrators)
20
+ - [API Reference](#api-reference)
21
+ - [Examples](#examples)
22
+
23
+ ## Installation
24
+
25
+ ```bash
26
+ npm install @wundr.io/autogen-orchestrator
27
+ # or
28
+ yarn add @wundr.io/autogen-orchestrator
29
+ # or
30
+ pnpm add @wundr.io/autogen-orchestrator
31
+ ```
32
+
33
+ ## Quick Start
34
+
35
+ ```typescript
36
+ import {
37
+ GroupChatManager,
38
+ GroupChatBuilder,
39
+ createParticipant,
40
+ TerminationPresets,
41
+ } from '@wundr.io/autogen-orchestrator';
42
+
43
+ // Create participants
44
+ const analyst = createParticipant(
45
+ 'Analyst',
46
+ 'You are a data analyst specializing in market research.',
47
+ ['analysis', 'research', 'data']
48
+ );
49
+
50
+ const developer = createParticipant('Developer', 'You are a senior software developer.', [
51
+ 'coding',
52
+ 'architecture',
53
+ 'debugging',
54
+ ]);
55
+
56
+ const reviewer = createParticipant(
57
+ 'Reviewer',
58
+ 'You are a code reviewer ensuring quality standards.',
59
+ ['review', 'testing', 'quality']
60
+ );
61
+
62
+ // Build and configure the group chat
63
+ const chat = new GroupChatBuilder()
64
+ .withName('Project Discussion')
65
+ .withDescription('Multi-agent collaboration for project planning')
66
+ .withParticipant(analyst)
67
+ .withParticipant(developer)
68
+ .withParticipant(reviewer)
69
+ .withSpeakerSelection('round_robin')
70
+ .withMaxRounds(10)
71
+ .withTerminationCondition(TerminationPresets.taskCompletion())
72
+ .build();
73
+
74
+ // Set up response generator (integrate with your LLM provider)
75
+ chat.setResponseGenerator(async (participant, messages, context) => {
76
+ // Your LLM integration here
77
+ return `Response from ${participant.name}`;
78
+ });
79
+
80
+ // Start the conversation
81
+ const result = await chat.start({
82
+ initialMessage: 'Let us discuss the project requirements.',
83
+ initialSender: 'user',
84
+ });
85
+
86
+ console.log('Chat completed:', result.summary);
87
+ ```
88
+
89
+ ## Core Concepts
90
+
91
+ ### Participants
92
+
93
+ Participants represent agents in the conversation. Each participant has:
94
+
95
+ - **name**: Unique identifier in the chat
96
+ - **type**: `'human'` | `'assistant'` | `'agent'` | `'tool'`
97
+ - **systemPrompt**: Instructions defining behavior
98
+ - **capabilities**: Skills/expertise areas
99
+ - **status**: Current state (`'active'` | `'idle'` | `'busy'` | `'offline'` | `'error'`)
100
+
101
+ ```typescript
102
+ import { ChatParticipant, createParticipant } from '@wundr.io/autogen-orchestrator';
103
+
104
+ // Simple creation
105
+ const agent = createParticipant(
106
+ 'ResearchAgent',
107
+ 'You conduct thorough research and provide citations.',
108
+ ['research', 'citations', 'fact-checking']
109
+ );
110
+
111
+ // Full configuration
112
+ const advancedAgent: ChatParticipant = {
113
+ id: 'agent-001',
114
+ name: 'AdvancedAgent',
115
+ type: 'agent',
116
+ systemPrompt: 'You are an expert in financial analysis.',
117
+ status: 'active',
118
+ capabilities: ['finance', 'analysis', 'forecasting'],
119
+ modelConfig: {
120
+ model: 'claude-3-opus',
121
+ temperature: 0.7,
122
+ maxTokens: 4096,
123
+ },
124
+ maxConsecutiveReplies: 3,
125
+ description: 'Financial analysis specialist',
126
+ };
127
+ ```
128
+
129
+ ### Messages
130
+
131
+ Messages track the conversation flow:
132
+
133
+ ```typescript
134
+ import { Message, MessageRole, ContentType } from '@wundr.io/autogen-orchestrator';
135
+
136
+ // Message structure
137
+ interface Message {
138
+ id: string;
139
+ role: MessageRole; // 'system' | 'user' | 'assistant' | 'function'
140
+ content: string;
141
+ name: string; // Sender name
142
+ timestamp: Date;
143
+ contentType?: ContentType; // 'text' | 'code' | 'image' | 'function_call' | 'function_result'
144
+ functionCall?: FunctionCall;
145
+ metadata?: MessageMetadata;
146
+ status?: MessageStatus;
147
+ }
148
+ ```
149
+
150
+ ### Context
151
+
152
+ The `ChatContext` provides state throughout the conversation:
153
+
154
+ ```typescript
155
+ interface ChatContext {
156
+ chatId: string;
157
+ currentRound: number;
158
+ messageCount: number;
159
+ activeParticipants: string[];
160
+ currentSpeaker?: string;
161
+ previousSpeaker?: string;
162
+ startTime: Date;
163
+ state: Record<string, unknown>; // Custom state storage
164
+ parentContext?: ChatContext; // For nested chats
165
+ }
166
+ ```
167
+
168
+ ## Agent Conversation Patterns
169
+
170
+ ### Round-Robin Conversations
171
+
172
+ Each participant speaks in order:
173
+
174
+ ```typescript
175
+ const chat = new GroupChatBuilder()
176
+ .withName('Round Robin Discussion')
177
+ .withParticipant(agent1)
178
+ .withParticipant(agent2)
179
+ .withParticipant(agent3)
180
+ .withSpeakerSelection('round_robin')
181
+ .withMaxRounds(5)
182
+ .build();
183
+ ```
184
+
185
+ ### Priority-Based Conversations
186
+
187
+ Agents speak based on configured priority:
188
+
189
+ ```typescript
190
+ const chat = new GroupChatManager({
191
+ name: 'Priority Discussion',
192
+ participants: [leader, specialist, assistant],
193
+ speakerSelectionMethod: 'priority',
194
+ speakerSelectionConfig: {
195
+ priorityOrder: ['Leader', 'Specialist', 'Assistant'],
196
+ transitionRules: [
197
+ { from: 'Leader', to: ['Specialist'], weight: 0.8 },
198
+ { from: 'Specialist', to: ['Leader', 'Assistant'], weight: 0.5 },
199
+ ],
200
+ allowedTransitions: {
201
+ Leader: ['Specialist', 'Assistant'],
202
+ Specialist: ['Leader'],
203
+ Assistant: ['Leader', 'Specialist'],
204
+ },
205
+ },
206
+ });
207
+ ```
208
+
209
+ ### LLM-Selected Speakers
210
+
211
+ Let an LLM decide who speaks next based on context:
212
+
213
+ ```typescript
214
+ const chat = new GroupChatBuilder()
215
+ .withName('Dynamic Discussion')
216
+ .withParticipant(analyst)
217
+ .withParticipant(developer)
218
+ .withParticipant(designer)
219
+ .withSpeakerSelection('llm_selected')
220
+ .build();
221
+
222
+ // The LLM selector analyzes:
223
+ // - Recent message content
224
+ // - Participant capabilities
225
+ // - Conversation flow
226
+ // - Mentions of participant names
227
+ ```
228
+
229
+ ### Auto-Adaptive Selection
230
+
231
+ Automatically chooses the best selection strategy:
232
+
233
+ ```typescript
234
+ const chat = new GroupChatBuilder().withSpeakerSelection('auto').build();
235
+
236
+ // Strategy selection logic:
237
+ // - Uses 'priority' if transition rules are configured
238
+ // - Uses 'llm' for complex conversations (>3 participants, >5 messages)
239
+ // - Uses 'llm' if participants have diverse capabilities
240
+ // - Defaults to 'round_robin' for simple cases
241
+ ```
242
+
243
+ ## Group Chat Management
244
+
245
+ ### Creating a Group Chat
246
+
247
+ Using the builder pattern:
248
+
249
+ ```typescript
250
+ import { GroupChatBuilder, TerminationPresets } from '@wundr.io/autogen-orchestrator';
251
+
252
+ const chat = new GroupChatBuilder()
253
+ .withName('Code Review Session')
254
+ .withDescription('Multi-agent code review and improvement')
255
+ .withParticipant(codeWriter)
256
+ .withParticipant(reviewer)
257
+ .withParticipant(tester)
258
+ .withSpeakerSelection('priority')
259
+ .withMaxRounds(15)
260
+ .withMaxMessages(50)
261
+ .withTerminationCondition({ type: 'keyword', value: ['APPROVED', 'MERGED'] })
262
+ .withTimeout(300000) // 5 minutes
263
+ .withAdmin('moderator')
264
+ .withNestedChats()
265
+ .build();
266
+ ```
267
+
268
+ Using direct configuration:
269
+
270
+ ```typescript
271
+ import { GroupChatManager, GroupChatConfig } from '@wundr.io/autogen-orchestrator';
272
+
273
+ const config: GroupChatConfig = {
274
+ name: 'Analysis Team',
275
+ participants: [analyst, researcher, writer],
276
+ speakerSelectionMethod: 'round_robin',
277
+ maxRounds: 10,
278
+ maxMessages: 100,
279
+ terminationConditions: [
280
+ { type: 'keyword', value: 'COMPLETE' },
281
+ { type: 'max_rounds', value: 10 },
282
+ ],
283
+ enableHistory: true,
284
+ maxHistoryLength: 500,
285
+ timeoutMs: 600000,
286
+ };
287
+
288
+ const chat = new GroupChatManager(config);
289
+ ```
290
+
291
+ ### Managing Participants Dynamically
292
+
293
+ ```typescript
294
+ // Add participant during chat
295
+ const newAgent = chat.addParticipant({
296
+ name: 'ExpertConsultant',
297
+ type: 'agent',
298
+ systemPrompt: 'You provide expert consultation on complex issues.',
299
+ capabilities: ['consulting', 'strategy'],
300
+ });
301
+
302
+ // Remove participant
303
+ chat.removeParticipant('ExpertConsultant');
304
+
305
+ // Update participant status
306
+ chat.updateParticipantStatus('Analyst', 'busy');
307
+
308
+ // Get all participants
309
+ const participants = chat.getParticipants();
310
+ ```
311
+
312
+ ### Chat Lifecycle
313
+
314
+ ```typescript
315
+ // Start the chat
316
+ const result = await chat.start({
317
+ initialMessage: 'Begin the analysis.',
318
+ initialSender: 'user',
319
+ initialState: { projectId: 'proj-123' },
320
+ });
321
+
322
+ // Pause and resume
323
+ chat.pause();
324
+ // ... some time later
325
+ chat.resume();
326
+
327
+ // Stop the chat
328
+ const finalResult = await chat.stop('User requested termination');
329
+
330
+ // Get current status
331
+ const status = chat.getStatus(); // 'initializing' | 'active' | 'paused' | 'completed' | 'terminated' | 'error'
332
+ ```
333
+
334
+ ### Event Handling
335
+
336
+ ```typescript
337
+ import { GroupChatEvents } from '@wundr.io/autogen-orchestrator';
338
+
339
+ // Listen to chat events
340
+ chat.on('chat:started', ({ chatId, config }) => {
341
+ console.log(`Chat ${chatId} started with ${config.participants.length} participants`);
342
+ });
343
+
344
+ chat.on('message:received', ({ chatId, message }) => {
345
+ console.log(`[${message.name}]: ${message.content}`);
346
+ });
347
+
348
+ chat.on('speaker:selected', ({ chatId, speaker, reason }) => {
349
+ console.log(`Next speaker: ${speaker} (${reason})`);
350
+ });
351
+
352
+ chat.on('round:started', ({ chatId, round }) => {
353
+ console.log(`Starting round ${round}`);
354
+ });
355
+
356
+ chat.on('termination:triggered', ({ chatId, reason }) => {
357
+ console.log(`Chat terminated: ${reason}`);
358
+ });
359
+
360
+ chat.on('chat:ended', ({ chatId, result }) => {
361
+ console.log(`Chat ended. Total messages: ${result.totalMessages}`);
362
+ });
363
+
364
+ chat.on('chat:error', ({ chatId, error }) => {
365
+ console.error(`Error in chat: ${error.message}`);
366
+ });
367
+ ```
368
+
369
+ ## Speaker Selection
370
+
371
+ ### Available Strategies
372
+
373
+ ```typescript
374
+ import {
375
+ createSpeakerSelector,
376
+ SpeakerSelectionManager,
377
+ RoundRobinSelector,
378
+ RandomSelector,
379
+ LLMSelector,
380
+ PrioritySelector,
381
+ ManualSelector,
382
+ AutoSelector,
383
+ } from '@wundr.io/autogen-orchestrator';
384
+
385
+ // Factory function
386
+ const selector = createSpeakerSelector('llm_selected');
387
+
388
+ // Using the manager
389
+ const manager = new SpeakerSelectionManager('round_robin');
390
+
391
+ // Select next speaker
392
+ const result = await manager.selectSpeaker(participants, messages, context, selectionConfig);
393
+
394
+ console.log(result);
395
+ // {
396
+ // speaker: 'AnalystAgent',
397
+ // reason: 'Round-robin selection: position 2 of 3',
398
+ // confidence: 1.0,
399
+ // alternatives: ['DeveloperAgent', 'ReviewerAgent']
400
+ // }
401
+
402
+ // Change strategy at runtime
403
+ manager.setMethod('priority');
404
+ ```
405
+
406
+ ### Custom Speaker Selection
407
+
408
+ ```typescript
409
+ import { SpeakerSelectionStrategy, SpeakerSelectionResult } from '@wundr.io/autogen-orchestrator';
410
+
411
+ class CapabilityMatchSelector implements SpeakerSelectionStrategy {
412
+ async selectSpeaker(
413
+ participants: ChatParticipant[],
414
+ messages: Message[],
415
+ context: ChatContext,
416
+ config?: SpeakerSelectionConfig
417
+ ): Promise<SpeakerSelectionResult> {
418
+ const lastMessage = messages[messages.length - 1];
419
+
420
+ // Find participant whose capabilities best match the message content
421
+ let bestMatch = participants[0];
422
+ let bestScore = 0;
423
+
424
+ for (const participant of participants) {
425
+ const score = participant.capabilities.filter(cap =>
426
+ lastMessage?.content.toLowerCase().includes(cap.toLowerCase())
427
+ ).length;
428
+
429
+ if (score > bestScore) {
430
+ bestScore = score;
431
+ bestMatch = participant;
432
+ }
433
+ }
434
+
435
+ return {
436
+ speaker: bestMatch.name,
437
+ reason: `Capability match score: ${bestScore}`,
438
+ confidence: bestScore > 0 ? 0.9 : 0.5,
439
+ alternatives: participants.filter(p => p.name !== bestMatch.name).map(p => p.name),
440
+ };
441
+ }
442
+ }
443
+ ```
444
+
445
+ ### Transition Rules
446
+
447
+ ```typescript
448
+ const config: SpeakerSelectionConfig = {
449
+ priorityOrder: ['Manager', 'Developer', 'Tester'],
450
+ transitionRules: [
451
+ {
452
+ from: 'Manager',
453
+ to: ['Developer', 'Tester'],
454
+ condition: 'after assignment',
455
+ weight: 0.9,
456
+ },
457
+ {
458
+ from: 'Developer',
459
+ to: ['Tester'],
460
+ weight: 0.7,
461
+ },
462
+ {
463
+ from: 'Tester',
464
+ to: ['Developer', 'Manager'],
465
+ weight: 0.5,
466
+ },
467
+ ],
468
+ allowedTransitions: {
469
+ Manager: ['Developer', 'Tester'],
470
+ Developer: ['Tester', 'Manager'],
471
+ Tester: ['Developer', 'Manager'],
472
+ },
473
+ };
474
+ ```
475
+
476
+ ## Message Routing
477
+
478
+ ### Adding Messages Programmatically
479
+
480
+ ```typescript
481
+ // Add a user message
482
+ await chat.addMessage({
483
+ role: 'user',
484
+ content: 'Please analyze the latest data.',
485
+ name: 'user',
486
+ });
487
+
488
+ // Add a system message
489
+ await chat.addMessage({
490
+ role: 'system',
491
+ content: 'Context updated: New data available.',
492
+ name: 'system',
493
+ });
494
+
495
+ // Add a function call message
496
+ await chat.addMessage({
497
+ role: 'assistant',
498
+ content: 'Executing data analysis...',
499
+ name: 'AnalystAgent',
500
+ contentType: 'function_call',
501
+ functionCall: {
502
+ name: 'analyzeData',
503
+ arguments: { dataset: 'q4_2024', metrics: ['revenue', 'growth'] },
504
+ },
505
+ });
506
+
507
+ // Add function result
508
+ await chat.addMessage({
509
+ role: 'function',
510
+ content: JSON.stringify({ revenue: 1500000, growth: 0.15 }),
511
+ name: 'analyzeData',
512
+ contentType: 'function_result',
513
+ });
514
+ ```
515
+
516
+ ### Response Generation
517
+
518
+ ```typescript
519
+ import { ResponseGenerator } from '@wundr.io/autogen-orchestrator';
520
+
521
+ // Set custom response generator
522
+ const generator: ResponseGenerator = async (participant, messages, context) => {
523
+ // Build prompt from participant's system prompt and message history
524
+ const systemPrompt = participant.systemPrompt;
525
+ const conversationHistory = messages.map(m => `${m.name}: ${m.content}`).join('\n');
526
+
527
+ // Call your LLM provider
528
+ const response = await callLLM({
529
+ system: systemPrompt,
530
+ messages: conversationHistory,
531
+ model: participant.modelConfig?.model || 'default-model',
532
+ temperature: participant.modelConfig?.temperature || 0.7,
533
+ });
534
+
535
+ return response;
536
+ };
537
+
538
+ chat.setResponseGenerator(generator);
539
+ ```
540
+
541
+ ## Conversation History Tracking
542
+
543
+ ### Accessing History
544
+
545
+ ```typescript
546
+ // Get all messages
547
+ const messages = chat.getMessages();
548
+
549
+ // Get current context
550
+ const context = chat.getContext();
551
+
552
+ // Get metrics
553
+ const metrics = chat.getMetrics();
554
+ console.log(metrics);
555
+ // {
556
+ // totalTokens: 15000,
557
+ // avgResponseTimeMs: 1250,
558
+ // messagesPerParticipant: { 'Agent1': 5, 'Agent2': 4 },
559
+ // tokensPerParticipant: { 'Agent1': 8000, 'Agent2': 7000 },
560
+ // successfulResponses: 9,
561
+ // failedResponses: 0,
562
+ // }
563
+ ```
564
+
565
+ ### State Management
566
+
567
+ ```typescript
568
+ // Update shared state
569
+ chat.updateState('currentTopic', 'performance optimization');
570
+ chat.updateState('analysisComplete', true);
571
+ chat.updateState('findings', { issues: 3, recommendations: 5 });
572
+
573
+ // Read state
574
+ const topic = chat.getState<string>('currentTopic');
575
+ const complete = chat.getState<boolean>('analysisComplete');
576
+ ```
577
+
578
+ ### Chat Results
579
+
580
+ ```typescript
581
+ interface ChatResult {
582
+ chatId: string;
583
+ status: ChatStatus;
584
+ messages: Message[];
585
+ summary?: string;
586
+ terminationReason?: string;
587
+ totalRounds: number;
588
+ totalMessages: number;
589
+ participants: string[];
590
+ durationMs: number;
591
+ metrics?: ChatMetrics;
592
+ nestedResults?: NestedChatResult[];
593
+ error?: ChatError;
594
+ startedAt: Date;
595
+ endedAt: Date;
596
+ }
597
+
598
+ const result = await chat.start({ initialMessage: 'Begin' });
599
+ console.log(`Completed in ${result.durationMs}ms with ${result.totalMessages} messages`);
600
+ ```
601
+
602
+ ## Termination Handling
603
+
604
+ ### Built-in Termination Conditions
605
+
606
+ ```typescript
607
+ import {
608
+ TerminationManager,
609
+ createTerminationHandler,
610
+ TerminationPresets,
611
+ } from '@wundr.io/autogen-orchestrator';
612
+
613
+ // Max rounds
614
+ { type: 'max_rounds', value: 10 }
615
+
616
+ // Max messages
617
+ { type: 'max_messages', value: 50 }
618
+
619
+ // Keyword detection
620
+ { type: 'keyword', value: ['DONE', 'COMPLETE', 'TERMINATE'] }
621
+
622
+ // Timeout (milliseconds)
623
+ { type: 'timeout', value: 300000 }
624
+
625
+ // Consensus-based
626
+ {
627
+ type: 'consensus',
628
+ value: {
629
+ threshold: 0.75,
630
+ agreementKeywords: ['agree', 'approve', 'lgtm'],
631
+ disagreementKeywords: ['disagree', 'reject', 'needs work'],
632
+ minParticipants: 2,
633
+ windowSize: 10,
634
+ }
635
+ }
636
+
637
+ // Custom function
638
+ {
639
+ type: 'function',
640
+ evaluator: async (messages, participants, context) => ({
641
+ shouldTerminate: context.state['taskComplete'] === true,
642
+ reason: 'Task marked as complete',
643
+ summary: 'Conversation ended after task completion',
644
+ }),
645
+ }
646
+ ```
647
+
648
+ ### Termination Presets
649
+
650
+ ```typescript
651
+ import { TerminationPresets } from '@wundr.io/autogen-orchestrator';
652
+
653
+ // Task completion detection
654
+ const taskComplete = TerminationPresets.taskCompletion();
655
+ // Detects: 'TASK_COMPLETE', 'DONE', 'FINISHED', 'COMPLETED', 'END_TASK'
656
+
657
+ // Approval workflow
658
+ const approval = TerminationPresets.approval();
659
+ // Consensus with 75% threshold, detects: 'approve', 'lgtm', 'ship it'
660
+
661
+ // Quick discussions
662
+ const quick = TerminationPresets.quickDiscussion(5);
663
+ // Max 5 rounds + manual termination keywords
664
+
665
+ // Long-running tasks
666
+ const longRunning = TerminationPresets.longRunning(30);
667
+ // 30-minute timeout + 100 message limit + emergency keywords
668
+ ```
669
+
670
+ ### Managing Termination Conditions
671
+
672
+ ```typescript
673
+ const manager = new TerminationManager([
674
+ { type: 'max_rounds', value: 10 },
675
+ { type: 'keyword', value: 'STOP' },
676
+ ]);
677
+
678
+ // Add condition at runtime
679
+ manager.addCondition({ type: 'timeout', value: 60000 });
680
+
681
+ // Remove condition type
682
+ manager.removeCondition('timeout');
683
+
684
+ // Check if condition exists
685
+ const hasKeyword = manager.hasCondition('keyword');
686
+
687
+ // Evaluate all conditions
688
+ const result = await manager.evaluate(messages, participants, context);
689
+ if (result.shouldTerminate) {
690
+ console.log(`Terminating: ${result.reason}`);
691
+ }
692
+
693
+ // Get all conditions
694
+ const conditions = manager.getConditions();
695
+ ```
696
+
697
+ ## Nested Chats
698
+
699
+ Nested chats allow focused sub-discussions within a main conversation.
700
+
701
+ ### Configuration
702
+
703
+ ```typescript
704
+ import { NestedChatManager, NestedChatConfigBuilder } from '@wundr.io/autogen-orchestrator';
705
+
706
+ // Using the builder
707
+ const nestedConfig = new NestedChatConfigBuilder()
708
+ .withId('technical-review')
709
+ .withName('Technical Deep Dive')
710
+ .withKeywordTrigger(['technical review', 'deep dive'])
711
+ .withParticipants(['Developer', 'Architect', 'Tester'])
712
+ .withMaxRounds(5)
713
+ .withSummaryMethod('reflection')
714
+ .withPrompt('Focus on technical implementation details.')
715
+ .withSharedContext()
716
+ .build();
717
+
718
+ // Add to group chat
719
+ const chat = new GroupChatBuilder()
720
+ .withParticipant(developer)
721
+ .withParticipant(architect)
722
+ .withParticipant(tester)
723
+ .withParticipant(manager)
724
+ .withNestedChats()
725
+ .withNestedChatConfig(nestedConfig)
726
+ .build();
727
+ ```
728
+
729
+ ### Trigger Types
730
+
731
+ ```typescript
732
+ // Keyword trigger
733
+ new NestedChatConfigBuilder().withKeywordTrigger(['review code', 'code review']).build();
734
+
735
+ // Participant trigger
736
+ new NestedChatConfigBuilder()
737
+ .withParticipantTrigger(['SecurityExpert', 'ComplianceOfficer'])
738
+ .build();
739
+
740
+ // Condition trigger
741
+ new NestedChatConfigBuilder()
742
+ .withConditionTrigger((message, context) => {
743
+ return context.messageCount > 10 && message.content.includes('complex');
744
+ })
745
+ .build();
746
+
747
+ // Manual trigger
748
+ new NestedChatConfigBuilder().withManualTrigger('startNestedDiscussion').build();
749
+
750
+ // Trigger manually via state
751
+ chat.updateState('startNestedDiscussion', true);
752
+ ```
753
+
754
+ ### Summary Methods
755
+
756
+ ```typescript
757
+ // 'last' - Use the last message as summary
758
+ // 'llm' - Generate summary using LLM (requires implementation)
759
+ // 'reflection' - Structured reflection summary
760
+ // 'custom' - Custom summary logic
761
+
762
+ const config = new NestedChatConfigBuilder().withSummaryMethod('reflection').build();
763
+ ```
764
+
765
+ ### Nested Chat Events
766
+
767
+ ```typescript
768
+ chat.on('nested:started', ({ chatId, nestedChatId }) => {
769
+ console.log(`Nested chat ${nestedChatId} started`);
770
+ });
771
+
772
+ chat.on('nested:ended', ({ chatId, nestedChatId, result }) => {
773
+ console.log(`Nested chat summary: ${result.summary}`);
774
+ });
775
+ ```
776
+
777
+ ## Integration with Other Orchestrators
778
+
779
+ ### With Task Orchestrators
780
+
781
+ ```typescript
782
+ import { GroupChatManager } from '@wundr.io/autogen-orchestrator';
783
+ import { TaskOrchestrator } from '@wundr.io/task-orchestrator';
784
+
785
+ const taskOrchestrator = new TaskOrchestrator();
786
+
787
+ // Create a chat for each complex task
788
+ taskOrchestrator.on('task:complex', async task => {
789
+ const chat = new GroupChatBuilder()
790
+ .withName(`Task: ${task.name}`)
791
+ .withParticipant(createParticipant('Planner', 'Plan the task execution'))
792
+ .withParticipant(createParticipant('Executor', 'Execute the planned steps'))
793
+ .withParticipant(createParticipant('Validator', 'Validate results'))
794
+ .withSpeakerSelection('priority')
795
+ .withTerminationCondition({ type: 'keyword', value: 'TASK_COMPLETE' })
796
+ .build();
797
+
798
+ const result = await chat.start({
799
+ initialMessage: `Execute task: ${task.description}`,
800
+ initialState: { taskId: task.id },
801
+ });
802
+
803
+ return result;
804
+ });
805
+ ```
806
+
807
+ ### With Workflow Engines
808
+
809
+ ```typescript
810
+ import { GroupChatManager } from '@wundr.io/autogen-orchestrator';
811
+
812
+ class WorkflowStep {
813
+ async executeWithAgents(stepConfig: StepConfig) {
814
+ const participants = stepConfig.roles.map(role =>
815
+ createParticipant(role.name, role.prompt, role.capabilities)
816
+ );
817
+
818
+ const chat = new GroupChatBuilder()
819
+ .withName(stepConfig.name)
820
+ .withSpeakerSelection('auto')
821
+ .withMaxRounds(stepConfig.maxIterations || 10)
822
+ .build();
823
+
824
+ participants.forEach(p => chat.addParticipant(p));
825
+
826
+ chat.setResponseGenerator(this.createResponseGenerator(stepConfig));
827
+
828
+ return await chat.start({
829
+ initialMessage: stepConfig.objective,
830
+ initialState: stepConfig.context,
831
+ });
832
+ }
833
+ }
834
+ ```
835
+
836
+ ### With Event-Driven Systems
837
+
838
+ ```typescript
839
+ import { EventEmitter } from 'events';
840
+ import { GroupChatManager, ChatEvent } from '@wundr.io/autogen-orchestrator';
841
+
842
+ class AgentEventBridge extends EventEmitter {
843
+ private chat: GroupChatManager;
844
+
845
+ constructor(chat: GroupChatManager) {
846
+ super();
847
+ this.chat = chat;
848
+ this.setupBridge();
849
+ }
850
+
851
+ private setupBridge() {
852
+ // Forward chat events to external system
853
+ this.chat.on('message:received', ({ message }) => {
854
+ this.emit('agent:message', {
855
+ agent: message.name,
856
+ content: message.content,
857
+ timestamp: message.timestamp,
858
+ });
859
+ });
860
+
861
+ this.chat.on('chat:ended', ({ result }) => {
862
+ this.emit('conversation:complete', {
863
+ summary: result.summary,
864
+ metrics: result.metrics,
865
+ duration: result.durationMs,
866
+ });
867
+ });
868
+ }
869
+
870
+ // Inject external events into the chat
871
+ async injectExternalMessage(source: string, content: string) {
872
+ await this.chat.addMessage({
873
+ role: 'system',
874
+ content: `[External: ${source}] ${content}`,
875
+ name: 'system',
876
+ });
877
+ }
878
+ }
879
+ ```
880
+
881
+ ## API Reference
882
+
883
+ ### GroupChatManager
884
+
885
+ | Method | Description |
886
+ | ------------------------------------------------------------------ | ------------------------------ |
887
+ | `constructor(config: GroupChatConfig)` | Create a new chat manager |
888
+ | `setResponseGenerator(generator: ResponseGenerator)` | Set the LLM response generator |
889
+ | `start(options?: StartChatOptions)` | Start the conversation |
890
+ | `pause()` | Pause the conversation |
891
+ | `resume()` | Resume a paused conversation |
892
+ | `stop(reason?: string)` | Stop the conversation |
893
+ | `addMessage(options: CreateMessageOptions)` | Add a message |
894
+ | `addParticipant(options: AddParticipantOptions)` | Add a participant |
895
+ | `removeParticipant(name: string)` | Remove a participant |
896
+ | `updateParticipantStatus(name: string, status: ParticipantStatus)` | Update participant status |
897
+ | `addTerminationCondition(condition: TerminationCondition)` | Add termination condition |
898
+ | `addNestedChatConfig(config: NestedChatConfig)` | Add nested chat configuration |
899
+ | `getStatus()` | Get current chat status |
900
+ | `getChatId()` | Get the chat ID |
901
+ | `getMessages()` | Get all messages |
902
+ | `getParticipants()` | Get all participants |
903
+ | `getContext()` | Get current context |
904
+ | `getMetrics()` | Get chat metrics |
905
+ | `updateState(key: string, value: T)` | Update context state |
906
+ | `getState<T>(key: string)` | Get context state value |
907
+
908
+ ### SpeakerSelectionManager
909
+
910
+ | Method | Description |
911
+ | --------------------------------------------------------- | -------------------------- |
912
+ | `constructor(method?: SpeakerSelectionMethod)` | Create with initial method |
913
+ | `selectSpeaker(participants, messages, context, config?)` | Select next speaker |
914
+ | `setMethod(method: SpeakerSelectionMethod)` | Change selection method |
915
+ | `getMethod()` | Get current method |
916
+ | `getStrategy(method: SpeakerSelectionMethod)` | Get strategy instance |
917
+
918
+ ### TerminationManager
919
+
920
+ | Method | Description |
921
+ | -------------------------------------------------- | ------------------------------ |
922
+ | `constructor(conditions?: TerminationCondition[])` | Create with initial conditions |
923
+ | `addCondition(condition: TerminationCondition)` | Add a condition |
924
+ | `removeCondition(type: TerminationConditionType)` | Remove conditions by type |
925
+ | `clearConditions()` | Clear all conditions |
926
+ | `evaluate(messages, participants, context)` | Evaluate all conditions |
927
+ | `getConditions()` | Get all conditions |
928
+ | `hasCondition(type: TerminationConditionType)` | Check if type exists |
929
+
930
+ ### NestedChatManager
931
+
932
+ | Method | Description |
933
+ | ------------------------------------------------------------------------------- | --------------------------- |
934
+ | `constructor(configs?: NestedChatConfig[])` | Create with initial configs |
935
+ | `addConfig(config: NestedChatConfig)` | Add configuration |
936
+ | `removeConfig(configId: string)` | Remove configuration |
937
+ | `checkTrigger(message, participants, context)` | Check for triggers |
938
+ | `startNestedChat(config, parentChatId, parentMessageId, participants, context)` | Start nested chat |
939
+ | `addMessage(nestedChatId: string, message: Message)` | Add message to nested chat |
940
+ | `endNestedChat(nestedChatId, status?, reason?)` | End nested chat |
941
+ | `getActiveChats()` | Get active nested chat IDs |
942
+ | `getCompletedChats()` | Get completed results |
943
+ | `hasActiveChats()` | Check for active chats |
944
+
945
+ ## Examples
946
+
947
+ ### Code Review Workflow
948
+
949
+ ```typescript
950
+ import {
951
+ GroupChatBuilder,
952
+ createParticipant,
953
+ TerminationPresets,
954
+ } from '@wundr.io/autogen-orchestrator';
955
+
956
+ const codeAuthor = createParticipant(
957
+ 'CodeAuthor',
958
+ 'You wrote the code and can explain design decisions.',
959
+ ['code', 'architecture', 'explanation']
960
+ );
961
+
962
+ const securityReviewer = createParticipant(
963
+ 'SecurityReviewer',
964
+ 'You review code for security vulnerabilities.',
965
+ ['security', 'vulnerabilities', 'compliance']
966
+ );
967
+
968
+ const performanceReviewer = createParticipant(
969
+ 'PerformanceReviewer',
970
+ 'You review code for performance issues.',
971
+ ['performance', 'optimization', 'efficiency']
972
+ );
973
+
974
+ const chat = new GroupChatBuilder()
975
+ .withName('Code Review')
976
+ .withParticipant(codeAuthor)
977
+ .withParticipant(securityReviewer)
978
+ .withParticipant(performanceReviewer)
979
+ .withSpeakerSelection('priority')
980
+ .withTerminationCondition(TerminationPresets.approval())
981
+ .withMaxRounds(20)
982
+ .build();
983
+
984
+ const result = await chat.start({
985
+ initialMessage: `Review this code:\n\`\`\`javascript\n${codeToReview}\n\`\`\``,
986
+ });
987
+ ```
988
+
989
+ ### Research Collaboration
990
+
991
+ ```typescript
992
+ const researcher = createParticipant(
993
+ 'Researcher',
994
+ 'You search for and analyze relevant information.',
995
+ ['research', 'analysis', 'citations']
996
+ );
997
+
998
+ const critic = createParticipant(
999
+ 'Critic',
1000
+ 'You critically evaluate claims and identify weaknesses.',
1001
+ ['evaluation', 'logic', 'counterarguments']
1002
+ );
1003
+
1004
+ const synthesizer = createParticipant(
1005
+ 'Synthesizer',
1006
+ 'You combine findings into coherent conclusions.',
1007
+ ['synthesis', 'summary', 'conclusions']
1008
+ );
1009
+
1010
+ const chat = new GroupChatBuilder()
1011
+ .withName('Research Collaboration')
1012
+ .withParticipant(researcher)
1013
+ .withParticipant(critic)
1014
+ .withParticipant(synthesizer)
1015
+ .withSpeakerSelection('llm_selected')
1016
+ .withTerminationCondition({
1017
+ type: 'keyword',
1018
+ value: ['CONCLUSION REACHED', 'RESEARCH COMPLETE'],
1019
+ })
1020
+ .build();
1021
+ ```
1022
+
1023
+ ### Customer Support Escalation
1024
+
1025
+ ```typescript
1026
+ const frontlineAgent = createParticipant(
1027
+ 'FrontlineSupport',
1028
+ 'You handle initial customer inquiries.',
1029
+ ['support', 'troubleshooting', 'empathy']
1030
+ );
1031
+
1032
+ const technicalSpecialist = createParticipant(
1033
+ 'TechnicalSpecialist',
1034
+ 'You handle complex technical issues.',
1035
+ ['technical', 'debugging', 'systems']
1036
+ );
1037
+
1038
+ const supervisor = createParticipant(
1039
+ 'Supervisor',
1040
+ 'You handle escalations and make final decisions.',
1041
+ ['escalation', 'decisions', 'policies']
1042
+ );
1043
+
1044
+ const chat = new GroupChatBuilder()
1045
+ .withName('Support Ticket #12345')
1046
+ .withParticipant(frontlineAgent)
1047
+ .withParticipant(technicalSpecialist)
1048
+ .withParticipant(supervisor)
1049
+ .withSpeakerSelection('auto')
1050
+ .withNestedChats()
1051
+ .withNestedChatConfig(
1052
+ new NestedChatConfigBuilder()
1053
+ .withId('escalation')
1054
+ .withName('Supervisor Escalation')
1055
+ .withKeywordTrigger(['escalate', 'supervisor'])
1056
+ .withParticipants(['TechnicalSpecialist', 'Supervisor'])
1057
+ .withMaxRounds(3)
1058
+ .build()
1059
+ )
1060
+ .build();
1061
+ ```
1062
+
1063
+ ## License
1064
+
1065
+ MIT License - see LICENSE file for details.
1066
+
1067
+ ## Contributing
1068
+
1069
+ Contributions are welcome! Please read our contributing guidelines before submitting pull requests.
1070
+
1071
+ ## Support
1072
+
1073
+ - Issues: [GitHub Issues](https://github.com/adapticai/wundr/issues)
1074
+ - Documentation: [Wundr Documentation](https://wundr.io)