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