@memberjunction/ai-agents 2.58.0 → 2.60.0

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 CHANGED
@@ -1,21 +1,45 @@
1
1
  # @memberjunction/ai-agents
2
2
 
3
- The MemberJunction AI Agents package provides a comprehensive framework for creating, managing, and executing AI agents within the MemberJunction ecosystem. This package implements a clean separation of concerns architecture that separates domain execution from orchestration decision-making.
4
-
5
- ## Features
6
-
7
- - **🎯 Separation of Concerns**: Clean architecture separating BaseAgent (execution), ConductorAgent (decisions), and AgentRunner (coordination)
8
- - **🤖 Hierarchical Prompt Execution**: Advanced prompt system with depth-first traversal and parallel execution at each level
9
- - **🏗️ Agent Composition**: Hierarchical agent architecture with parent-child relationships
10
- - **🔄 Mixed Execution**: Action execution and sub-agent delegation with parallel/sequential coordination
11
- - **📝 Comprehensive Tracking**: Agent run and prompt run linking for complete execution visibility
12
- - **🎯 Action Framework**: Extensible action system integrated with ActionEngine
13
- - **🧠 Context Management**: Intelligent conversation context handling and compression
14
- - **🔧 Factory Pattern**: Enhanced AgentFactory for dynamic agent instantiation and extensibility
15
- - **🔐 Metadata-Driven**: Database-driven configuration for agents, types, and prompts
16
- - **📊 Analytics**: Hierarchical execution logging with performance tracking across agent workflows
17
- - **📡 Streaming Support**: Real-time streaming of execution progress and AI model responses
18
- - **🛑 Cancellation Support**: Graceful cancellation of long-running operations with AbortSignal
3
+ This npm package provides a complete framework for building AI agents using the MemberJunction platform. Agents can execute prompts, invoke actions, and orchestrate complex workflows with comprehensive execution tracking.
4
+
5
+ ## Overview
6
+
7
+ The `@memberjunction/ai-agents` package enables developers to create sophisticated AI agents that can:
8
+ - Execute AI prompts in a hierarchical structure (system + agent prompts)
9
+ - Perform actions based on prompt results using the MJ Actions framework
10
+ - Make decisions about next steps through configurable agent types
11
+ - Orchestrate sub-agents for complex, multi-step tasks
12
+ - Track all execution steps in database for analysis and debugging
13
+ - Manage conversation context with automatic compression
14
+
15
+ ## Key Components
16
+
17
+ ### BaseAgent
18
+ The core execution engine that all agents use. Provides functionality for:
19
+ - Hierarchical prompt execution (system prompt as parent, agent prompts as children)
20
+ - Managing conversation context and placeholders
21
+ - Invoking MemberJunction actions
22
+ - Running sub-agents recursively
23
+ - Comprehensive execution tracking via AIAgentRun and AIAgentRunStep entities
24
+ - Automatic context compression for long conversations
25
+
26
+ ### BaseAgentType
27
+ Abstract class that defines reusable agent behavior patterns:
28
+ - Determines next steps based on prompt results
29
+ - Encapsulates decision-making logic
30
+ - Enables different execution patterns (loops, decision trees, etc.)
31
+
32
+ ### LoopAgentType
33
+ Concrete implementation of BaseAgentType that:
34
+ - Executes in a loop until task completion
35
+ - Parses structured JSON responses from prompts
36
+ - Supports actions, sub-agents, and conditional termination
37
+
38
+ ### AgentRunner
39
+ Simple orchestrator that:
40
+ - Loads agent metadata from database
41
+ - Instantiates correct agent class using ClassFactory
42
+ - Executes agents with provided context
19
43
 
20
44
  ## Installation
21
45
 
@@ -23,1418 +47,219 @@ The MemberJunction AI Agents package provides a comprehensive framework for crea
23
47
  npm install @memberjunction/ai-agents
24
48
  ```
25
49
 
26
- ### Type Organization Update (2025)
27
-
28
- As part of improving code organization and reducing circular dependencies:
29
- - **This package** now contains all agent-specific types:
30
- - Agent execution types (`AgentExecutionParams`, `AgentExecutionResult`, etc.)
31
- - Agent runner types (`AgentRunnerParams`, `AgentRunnerResult`)
32
- - Conductor types (`ConductorDecisionInput`, `ConductorDecisionResponse`)
33
- - Progress and streaming callbacks
34
- - **Base AI types** are imported from `@memberjunction/ai` (Core)
35
- - **Prompt types** are imported from `@memberjunction/ai-prompts`
36
- - **Engine types** (agent type definitions) are imported from `@memberjunction/aiengine`
37
-
38
- ## Requirements
39
-
40
- - Node.js 16+
41
- - MemberJunction Core libraries
42
- - [@memberjunction/ai](../Core/README.md) for base AI types and interfaces
43
- - [@memberjunction/ai-prompts](../Prompts/README.md) for advanced prompt management
44
- - [@memberjunction/aiengine](../Engine/README.md) for AI model orchestration and agent type definitions
45
-
46
- ## Core Architecture
47
-
48
- The AI Agents framework implements a clean separation of concerns architecture:
49
-
50
- ### BaseAgent - Domain Execution
51
- - Focuses solely on executing agent-specific prompts and tasks
52
- - Handles template rendering with data context
53
- - Manages conversation context and compression
54
- - Returns standardized execution results
55
-
56
- ### ConductorAgent - Decision Making
57
- - Specialized agent for making orchestration decisions
58
- - Analyzes current state and available resources
59
- - Makes autonomous decisions about next steps
60
- - Plans execution sequences with proper ordering
61
-
62
- ### AgentRunner - Coordination
63
- - Orchestrates interaction between BaseAgent and ConductorAgent
64
- - Implements the core execution loop
65
- - Manages progress tracking and cancellation
66
- - Provides user interface abstraction
67
-
68
- ```typescript
69
- import { GetAgentFactory } from '@memberjunction/ai-agents';
70
- import { UserInfo } from '@memberjunction/core';
71
-
72
- // Get agent factory and create agents
73
- const factory = GetAgentFactory();
74
- const baseAgent = await factory.CreateAgent("Customer Support", null, contextUser);
75
- const conductorAgent = await factory.CreateAgent("Conductor", null, contextUser);
76
-
77
- // Create runner and execute with separation of concerns
78
- const runner = new AgentRunner(conductorAgent, contextUser);
79
- const result = await runner.Run({
80
- agent: baseAgent,
81
- goal: "Help customer with their order",
82
- data: { customerQuery: "Where is my order?" },
83
- conversationMessages: [...],
84
- onProgress: (progress) => console.log(progress.message),
85
- cancellationToken: controller.signal
86
- });
87
-
88
- if (result.success) {
89
- console.log("Task completed:", result.finalDecision?.finalResponse);
90
- console.log("Decisions made:", result.decisionHistory?.length);
91
- console.log("Actions executed:", result.actionResults?.length);
92
- }
93
- ```
94
-
95
-
96
- ## Architecture Deep Dive
97
-
98
- For comprehensive details about the AI Agents framework architecture, data models, workflows, and implementation guidelines, see the [Agent Architecture.md](./Agent%20Architecture.md) document.
99
-
100
- Key architectural concepts covered include:
101
-
102
- - **Hierarchical Agent Composition**: How agents are organized and orchestrated
103
- - **Metadata-Driven Configuration**: Database-driven agent and prompt management
104
- - **Execution Workflows**: Detailed execution patterns and context management
105
- - **Performance Optimization**: Caching, parallel execution, and resource management
106
- - **Extensibility Patterns**: Guidelines for custom agent development
107
-
108
- ## Usage Examples
109
-
110
- ### Basic Agent Implementation
50
+ ## Basic Usage
111
51
 
112
52
  ```typescript
113
- import { GetAgentFactory } from '@memberjunction/ai-agents';
114
- import { AIEngine } from '@memberjunction/aiengine';
115
53
  import { AgentRunner } from '@memberjunction/ai-agents';
116
54
  import { UserInfo } from '@memberjunction/core';
117
55
 
118
- // Initialize AI Engine to access agents and types
119
- await AIEngine.Instance.Config(false, contextUser);
120
-
121
- // Get agent factory and create agents
122
- const factory = GetAgentFactory();
123
- const baseAgent = await factory.CreateAgent('Customer Support', null, contextUser);
124
- const conductorAgent = await factory.CreateAgent('Conductor', null, contextUser);
125
-
126
- // Create and run with separation of concerns architecture
127
- const runner = new AgentRunner(conductorAgent, contextUser);
128
- const result = await runner.Run({
129
- agent: baseAgent,
130
- goal: 'Help customer with their order',
131
- data: {
132
- customerQuery: 'I need help with my order',
133
- customerId: 'cust-123'
134
- },
135
- conversationMessages: [
136
- { role: 'user', content: 'I need help with my order' }
137
- ]
138
- });
139
-
140
- if (result.success) {
141
- console.log('Task completed:', result.finalDecision?.finalResponse);
142
- console.log('Execution summary:', result.metadata);
143
- }
144
- ```
145
-
146
- ### Hierarchical Agent Composition
147
-
148
- ```typescript
149
- import { GetAgentFactory, AgentRunner } from '@memberjunction/ai-agents';
150
-
151
- // Hierarchical agents are handled through conductor decision-making
152
- // Parent agents delegate to child agents based on AI decisions
153
-
154
- // Get factory and create hierarchical agents
155
- const factory = GetAgentFactory();
156
- const managerAgent = await factory.CreateAgent('Customer Service Manager', null, contextUser);
157
- const conductorAgent = await factory.CreateAgent('Conductor', null, contextUser);
158
-
159
- // Create runner and execute - conductor will make autonomous delegation decisions
160
- const runner = new AgentRunner(conductorAgent, contextUser);
161
- const result = await runner.Run({
162
- agent: managerAgent,
163
- goal: 'Resolve complex customer issue',
164
- data: {
165
- customerQuery: 'Complex billing and technical issue',
166
- priority: 'high'
167
- },
168
- conversationMessages: [...],
169
- onProgress: (progress) => {
170
- if (progress.step === 'prompt_execution') {
171
- console.log('Agent coordinating execution:', progress.metadata);
172
- }
173
- }
174
- });
175
-
176
- // The conductor's decision history shows which sub-agents were chosen
177
- result.decisionHistory?.forEach((decision, i) => {
178
- console.log(`Decision ${i + 1}: ${decision.decision}`);
179
- console.log(`Reasoning: ${decision.reasoning}`);
180
- if (decision.executionPlan.length > 0) {
181
- console.log('Execution plan:', decision.executionPlan);
182
- }
183
- });
184
- ```
185
-
186
- ### Context Management and Compression
187
-
188
- ```typescript
189
- import { GetAgentFactory, AgentRunner } from '@memberjunction/ai-agents';
190
-
191
- // Context compression is automatically handled by BaseAgent
192
- // Configure compression through the agent entity properties
193
-
194
- const factory = GetAgentFactory();
195
- const longConversationAgent = AIEngine.Instance.Agents.find(a => {
196
- return a.EnableContextCompression &&
197
- a.ContextCompressionMessageThreshold === 50 &&
198
- a.ContextCompressionMessageRetentionCount === 10;
199
- });
200
-
201
- const baseAgent = factory.CreateAgentFromEntity(longConversationAgent, null, contextUser);
202
- const conductorAgent = await factory.CreateAgent('Conductor', null, contextUser);
203
- const runner = new AgentRunner(conductorAgent, contextUser);
204
-
205
- // Execute with long conversation - compression happens automatically in BaseAgent
206
- const longConversation = Array(60).fill(null).map((_, i) => ({
207
- role: i % 2 === 0 ? 'user' : 'assistant',
208
- content: `Message ${i + 1} in a very long conversation`
209
- }));
210
-
211
- const result = await runner.Run({
212
- agent: baseAgent,
213
- goal: 'Handle long conversation with compression',
214
- conversationMessages: longConversation,
215
- onProgress: (progress) => {
216
- if (progress.step === 'prompt_execution') {
217
- console.log('Processing context (may include compression):', progress.message);
218
- }
219
- }
220
- });
221
-
222
- // Compression is applied automatically by BaseAgent based on agent configuration
223
- // The agent run record tracks the compression activity
224
- ```
225
-
226
- ### Streaming and Progress Tracking
227
-
228
- The AI Agents framework supports real-time streaming of execution progress and AI model responses:
229
-
230
- ```typescript
231
- import { AgentRunner } from '@memberjunction/ai-agents';
232
-
56
+ // Using AgentRunner (recommended) which uses `ClassFactory` to pick the highest priority sub-class of BaseAgent that matches your Agent (and falls back to just using `BaseAgent` if there's no custom sub-class)
233
57
  const runner = new AgentRunner();
234
-
235
- // Execute with streaming and progress callbacks
236
58
  const result = await runner.RunAgent({
237
- agent: myAgent,
59
+ agent: agentEntity, // AIAgentEntity from database
238
60
  conversationMessages: messages,
239
- contextUser: user,
240
-
241
- // Progress callback for execution status updates
242
- onProgress: (progress) => {
243
- console.log(`[${progress.percentage}%] ${progress.step}: ${progress.message}`);
244
-
245
- // Progress steps include:
246
- // - initialization: Setting up the agent
247
- // - validation: Validating agent configuration
248
- // - prompt_execution: Executing AI prompts
249
- // - action_execution: Running actions
250
- // - subagent_execution: Running sub-agents
251
- // - decision_processing: Processing next steps
252
- // - finalization: Completing execution
253
- },
254
-
255
- // Streaming callback for real-time AI responses
256
- onStreaming: (chunk) => {
257
- process.stdout.write(chunk.content);
258
-
259
- if (chunk.isComplete) {
260
- console.log('\n--- Stream complete ---');
261
- }
262
-
263
- // Additional metadata available:
264
- // - chunk.stepType: 'prompt', 'action', 'subagent', or 'chat'
265
- // - chunk.stepEntityId: ID of the step being executed
266
- // - chunk.modelName: AI model producing the content (for prompts)
267
- }
61
+ contextUser: user
268
62
  });
269
- ```
270
-
271
- ### Cancellation Support
272
-
273
- Long-running agent operations can be cancelled gracefully using AbortSignal:
274
-
275
- ```typescript
276
- import { AgentRunner } from '@memberjunction/ai-agents';
277
-
278
- const runner = new AgentRunner();
279
- const controller = new AbortController();
280
-
281
- // Set up cancellation after 30 seconds
282
- setTimeout(() => {
283
- console.log('Cancelling agent execution...');
284
- controller.abort();
285
- }, 30000);
286
-
287
- try {
288
- const result = await runner.RunAgent({
289
- agent: myAgent,
290
- conversationMessages: messages,
291
- contextUser: user,
292
- cancellationToken: controller.signal,
293
- onProgress: (progress) => {
294
- console.log(`Progress: ${progress.message}`);
295
- }
296
- });
297
-
298
- if (result.cancelled) {
299
- console.log('Execution was cancelled:', result.cancellationReason);
300
- }
301
- } catch (error) {
302
- if (controller.signal.aborted) {
303
- console.log('Operation cancelled by user');
304
- } else {
305
- console.error('Execution error:', error);
306
- }
307
- }
308
-
309
- // Cancellation is checked at multiple points:
310
- // - Before starting execution
311
- // - After initialization
312
- // - Before each execution step
313
- // - After prompt/action/sub-agent completion
314
- // The agent run is properly marked as 'Cancelled' in the database
315
- ```
316
-
317
- ### Context Propagation (New in v2.51.0)
318
-
319
- The AI Agents framework now supports type-safe context propagation throughout the execution hierarchy. This allows runtime-specific information to flow from agents to sub-agents and actions without being part of the formal parameters.
320
-
321
- **Note**: Context typing is now done at the parameter level rather than the class level, providing better flexibility and type inference.
322
-
323
- #### Basic Context Usage
324
-
325
- ```typescript
326
- import { BaseAgent, ExecuteAgentParams } from '@memberjunction/ai-agents';
327
-
328
- // Define your context type
329
- interface MyAgentContext {
330
- apiEndpoint: string;
331
- apiKey: string;
332
- environment: 'dev' | 'staging' | 'prod';
333
- userPreferences: {
334
- language: string;
335
- timezone: string;
336
- };
337
- }
338
63
 
339
- // Execute agent with typed context
340
- const agent = new BaseAgent();
341
- const params: ExecuteAgentParams<MyAgentContext> = {
342
- agent: myAgentEntity,
64
+ // Direct instantiation when you want to pick the exact class that gets run
65
+ const agent = new YourAgentClass();
66
+ const result = await agent.Execute({
67
+ agent: agentEntity,
343
68
  conversationMessages: messages,
344
- contextUser: currentUser,
345
- context: {
346
- apiEndpoint: 'https://api.example.com',
347
- apiKey: process.env.API_KEY,
348
- environment: 'prod',
349
- userPreferences: {
350
- language: 'en',
351
- timezone: 'UTC'
352
- }
353
- }
354
- };
355
- const result = await agent.Execute(params);
69
+ contextUser: user
70
+ });
356
71
  ```
357
72
 
358
- #### Context Flow Through Hierarchy
73
+ ## Agent Configuration
359
74
 
360
- Context automatically flows through the entire execution hierarchy:
75
+ Agents are configured through MemberJunction entities:
361
76
 
362
- ```typescript
363
- // Parent agent execution
364
- const parentParams: ExecuteAgentParams<MyContext> = {
365
- agent: parentAgentEntity,
366
- conversationMessages: messages,
367
- context: myContext // Context passed here
368
- };
369
- const parentResult = await parentAgent.Execute(parentParams);
77
+ 1. **AIAgentType**: Defines the behavior pattern and system prompt
78
+ - `DriverClass`: The TypeScript class implementing the behavior
79
+ - `SystemPromptID`: Base prompt providing foundational behavior
370
80
 
371
- // When parent executes sub-agents, context flows automatically
372
- // Sub-agents receive the same context without manual passing
81
+ 2. **AIAgent**: Specific agent instance
82
+ - `AgentTypeID`: Links to the agent type
83
+ - Configuration for specific use cases
373
84
 
374
- // When agents execute actions, context flows to them as well
375
- // Actions can access context via params.Context
376
- ```
85
+ 3. **AIPrompt**: Reusable prompt templates
86
+ - Support for placeholders and dynamic content
87
+ - Can be chained hierarchically
377
88
 
378
- #### Using Context in Custom Agents
89
+ 4. **AIAgentPrompt**: Associates prompts with agents
90
+ - `ExecutionOrder`: Determines prompt execution sequence
91
+ - Links agents to their specific prompts
379
92
 
380
- ```typescript
381
- export class CustomAgent extends BaseAgent {
382
- protected async preparePromptParams(
383
- agentType: AIAgentTypeEntity,
384
- systemPrompt: any,
385
- childPrompt: any,
386
- params: ExecuteAgentParams<MyAgentContext>
387
- ): Promise<AIPromptParams> {
388
- const promptParams = await super.preparePromptParams(agentType, systemPrompt, childPrompt, params);
389
-
390
- // Access typed context
391
- if (params.context) {
392
- promptParams.data.apiEndpoint = params.context.apiEndpoint;
393
- promptParams.data.environment = params.context.environment;
394
-
395
- // Use context to modify behavior
396
- if (params.context.environment === 'dev') {
397
- promptParams.data.debugMode = true;
398
- }
399
- }
400
-
401
- return promptParams;
402
- }
403
- }
404
- ```
405
-
406
- #### Using Context in Actions
93
+ ## Creating Custom Agent Types
407
94
 
408
95
  ```typescript
409
- import { BaseAction, RunActionParams } from '@memberjunction/actions';
96
+ import { BaseAgentType, RegisterClass, BaseAgentNextStep } from '@memberjunction/ai-agents';
97
+ import { AIPromptRunResult } from '@memberjunction/ai-prompts';
410
98
 
411
- export class APICallAction extends BaseAction {
412
- protected async InternalRunAction(params: RunActionParams<MyAgentContext>): Promise<ActionResultSimple> {
413
- // Access typed context
414
- const endpoint = params.Context?.apiEndpoint;
415
- const apiKey = params.Context?.apiKey;
99
+ @RegisterClass(BaseAgentType, "MyCustomAgentType")
100
+ export class MyCustomAgentType extends BaseAgentType {
101
+ async DetermineNextStep(promptResult: AIPromptRunResult): Promise<BaseAgentNextStep> {
102
+ // Parse the prompt result
103
+ const response = JSON.parse(promptResult.FullResult);
416
104
 
417
- if (!endpoint || !apiKey) {
105
+ // Determine next action based on response
106
+ if (response.taskComplete) {
107
+ return { type: 'stop', reason: 'Task completed successfully' };
108
+ } else if (response.action) {
418
109
  return {
419
- Success: false,
420
- ResultCode: 'MISSING_CONTEXT',
421
- Message: 'Required API configuration not found in context'
110
+ type: 'action',
111
+ actionName: response.action.name,
112
+ actionParams: response.action.params
422
113
  };
114
+ } else {
115
+ return { type: 'continue' };
423
116
  }
424
-
425
- // Use context for action execution
426
- const response = await fetch(endpoint, {
427
- headers: {
428
- 'Authorization': `Bearer ${apiKey}`,
429
- 'Accept-Language': params.Context.userPreferences.language
430
- }
431
- });
432
-
433
- return {
434
- Success: true,
435
- ResultCode: 'SUCCESS',
436
- Message: 'API call completed'
437
- };
438
117
  }
439
118
  }
440
119
  ```
441
120
 
442
- #### Common Context Use Cases
443
-
444
- 1. **Environment Configuration**
445
- ```typescript
446
- interface EnvironmentContext {
447
- apiEndpoints: Record<string, string>;
448
- featureFlags: Record<string, boolean>;
449
- debugMode: boolean;
450
- }
451
- ```
452
-
453
- 2. **User Session Information**
454
- ```typescript
455
- interface SessionContext {
456
- sessionId: string;
457
- correlationId: string;
458
- userPreferences: UserPreferences;
459
- authTokens: Record<string, string>;
460
- }
461
- ```
462
-
463
- 3. **Runtime Service Connections**
464
- ```typescript
465
- interface ServiceContext {
466
- databaseConnection: string;
467
- cacheClient: CacheClient;
468
- messageQueue: QueueService;
469
- }
470
- ```
471
-
472
- #### Best Practices for Context Usage
473
-
474
- 1. **Define Clear Context Types**: Create well-defined interfaces for your context objects
475
- 2. **Keep Context Focused**: Include only runtime-specific data, not business logic parameters
476
- 3. **Avoid Sensitive Data**: While context can contain API keys when necessary, minimize sensitive data exposure
477
- 4. **Document Context Requirements**: Clearly document what context your agents and actions expect
478
- 5. **Provide Defaults**: Handle cases where context might be undefined or partial
479
-
480
- #### Context vs Parameters
121
+ ## Execution Flow
481
122
 
482
- Use **Context** for:
483
- - Environment-specific configuration
484
- - Runtime credentials and connections
485
- - User session information
486
- - Feature flags and toggles
487
- - Cross-cutting concerns
123
+ 1. **Initialization**:
124
+ - Creates AIAgentRun entity for tracking
125
+ - Loads agent configuration and type
126
+ - Initializes AI and Action engines
488
127
 
489
- Use **Parameters** for:
490
- - Business logic inputs
491
- - Data to be processed
492
- - Explicit action configuration
493
- - Values that should be logged/audited
494
- - Data that varies per execution
128
+ 2. **Configuration Loading**:
129
+ - Loads AIAgentType with system prompt
130
+ - Loads agent's prompts ordered by ExecutionOrder
131
+ - Validates placeholders and dependencies
495
132
 
496
- ## Extending BaseAgent
133
+ 3. **Execution Loop**:
134
+ - Executes prompts hierarchically (system as parent)
135
+ - Agent type analyzes results via DetermineNextStep()
136
+ - Executes actions or sub-agents as determined
137
+ - Creates AIAgentRunStep for each operation
138
+ - Continues until stop condition met
497
139
 
498
- The BaseAgent class provides a flexible execution pipeline that can be extended and customized through protected methods. This allows subclasses to override specific parts of the execution flow while maintaining the overall architecture.
499
-
500
- ### Execution Pipeline Overview
501
-
502
- The BaseAgent execution pipeline consists of the following overridable methods:
503
-
504
- 1. **`initializeEngines()`** - Initialize AI and Action engines
505
- 2. **`validateAgent()`** - Validate agent readiness
506
- 3. **`loadAgentConfiguration()`** - Load agent type and prompts
507
- 4. **`preparePromptParams()`** - Prepare hierarchical prompt parameters
508
- 5. **`executePrompt()`** - Execute the configured prompts
509
- 6. **`processNextStep()`** - Process agent type decisions
510
- 7. **`handleActionResults()`** - Handle action execution and recursion
511
- 8. **`handleSubAgentResult()`** - Handle sub-agent execution and recursion
512
- 9. **`createActionResultMessage()`** - Format action results as chat messages
513
- 10. **`createSubAgentResultMessage()`** - Format sub-agent results as chat messages
514
-
515
- ### Creating Custom Agent Classes
516
-
517
- ```typescript
518
- import { BaseAgent, ExecuteAgentParams, ExecuteAgentResult } from '@memberjunction/ai-agents';
519
- import { AIPromptParams } from '@memberjunction/ai-prompts';
520
-
521
- export class CustomAnalysisAgent extends BaseAgent {
522
- // Override initialization to add custom setup
523
- protected async initializeEngines(contextUser?: UserInfo): Promise<void> {
524
- await super.initializeEngines(contextUser);
525
-
526
- // Add custom initialization
527
- await this.initializeAnalysisTools();
528
- }
529
-
530
- // Override validation to add custom checks
531
- protected async validateAgent(agent: AIAgentEntity): Promise<ExecuteAgentResult | null> {
532
- const baseValidation = await super.validateAgent(agent);
533
- if (baseValidation) return baseValidation;
534
-
535
- // Add custom validation
536
- if (!this.hasRequiredPermissions(agent)) {
537
- return {
538
- nextStep: 'failed',
539
- errorMessage: 'Agent lacks required analysis permissions'
540
- };
541
- }
542
-
543
- return null;
544
- }
545
-
546
- // Override prompt preparation to inject custom data
547
- protected async preparePromptParams(
548
- agentType: AIAgentTypeEntity,
549
- systemPrompt: any,
550
- childPrompt: any,
551
- params: ExecuteAgentParams
552
- ): Promise<AIPromptParams> {
553
- const promptParams = await super.preparePromptParams(agentType, systemPrompt, childPrompt, params);
554
-
555
- // Add custom context data
556
- promptParams.data = {
557
- ...promptParams.data,
558
- analysisContext: await this.gatherAnalysisContext(),
559
- historicalData: await this.loadHistoricalData()
560
- };
561
-
562
- return promptParams;
563
- }
564
-
565
- // Override action result formatting
566
- protected createActionResultMessage(actions: AgentAction[], results: any[]): ChatMessage {
567
- // Custom formatting for analysis results
568
- const analysisResults = results.map((result, index) => {
569
- return {
570
- action: actions[index].name,
571
- success: result.Success,
572
- analysisScore: result.Params?.find(p => p.Name === 'score')?.Value,
573
- insights: result.Params?.find(p => p.Name === 'insights')?.Value
574
- };
575
- });
576
-
577
- return {
578
- role: 'user',
579
- content: `Analysis completed:\n${JSON.stringify(analysisResults, null, 2)}`
580
- };
581
- }
582
- }
583
- ```
140
+ 4. **Result Tracking**:
141
+ - All steps recorded with full context
142
+ - Execution tree available for analysis
143
+ - Errors and outputs captured
584
144
 
585
- ### Selective Method Overriding
586
-
587
- You can override just the methods you need to customize:
588
-
589
- ```typescript
590
- export class StreamingAgent extends BaseAgent {
591
- // Only override prompt execution to add streaming
592
- protected async executePrompt(promptParams: AIPromptParams): Promise<any> {
593
- // Add streaming configuration
594
- promptParams.streaming = true;
595
- promptParams.streamingCallback = (chunk) => {
596
- this.handleStreamingChunk(chunk);
597
- };
598
-
599
- return await super.executePrompt(promptParams);
600
- }
601
-
602
- private handleStreamingChunk(chunk: string): void {
603
- // Process streaming response chunks
604
- console.log('Streaming:', chunk);
605
- }
606
- }
607
- ```
608
-
609
- ### Customizing Recursion Behavior
610
-
611
- Override the action/sub-agent handling methods to customize recursion:
612
-
613
- ```typescript
614
- export class BatchProcessingAgent extends BaseAgent {
615
- protected async handleActionResults(
616
- params: ExecuteAgentParams,
617
- nextStep: any,
618
- promptResult: any
619
- ): Promise<ExecuteAgentResult> {
620
- // Execute actions
621
- const actionResults = await this.ExecuteActions(nextStep.actions, params.contextUser);
622
-
623
- // Batch results instead of immediate recursion
624
- if (this.shouldBatchResults(actionResults)) {
625
- this.batchedResults.push(...actionResults);
626
-
627
- // Continue without recursion if batching
628
- return {
629
- nextStep: 'retry',
630
- returnValue: { batching: true, count: this.batchedResults.length }
631
- };
632
- }
633
-
634
- // Otherwise use default recursion behavior
635
- return await super.handleActionResults(params, nextStep, promptResult);
636
- }
637
- }
638
- ```
639
-
640
- ### Advanced Pipeline Customization
641
-
642
- For complex scenarios, you can completely override the Execute method while still using the helper methods:
643
-
644
- ```typescript
645
- export class MultiStageAgent extends BaseAgent {
646
- public async Execute(params: ExecuteAgentParams): Promise<ExecuteAgentResult> {
647
- // Stage 1: Initial analysis
648
- const stage1Result = await this.executeStage1(params);
649
- if (stage1Result.nextStep === 'failed') return stage1Result;
650
-
651
- // Stage 2: Deep processing based on stage 1
652
- const stage2Params = this.prepareStage2Params(params, stage1Result);
653
- const stage2Result = await this.executeStage2(stage2Params);
654
- if (stage2Result.nextStep === 'failed') return stage2Result;
655
-
656
- // Stage 3: Synthesis and final execution
657
- return await this.executeFinalStage(params, stage1Result, stage2Result);
658
- }
659
-
660
- private async executeStage1(params: ExecuteAgentParams): Promise<ExecuteAgentResult> {
661
- // Use base methods for configuration loading
662
- const config = await this.loadAgentConfiguration(params.agent);
663
- if (!config.success) {
664
- return { nextStep: 'failed', errorMessage: config.errorMessage };
665
- }
666
-
667
- // Custom stage 1 logic...
668
- }
669
- }
670
- ```
671
-
672
- ### Best Practices for Extending BaseAgent
673
-
674
- 1. **Always call super methods** when overriding unless completely replacing functionality
675
- 2. **Maintain the contract** - return the expected types from overridden methods
676
- 3. **Use protected methods** for extensibility rather than duplicating logic
677
- 4. **Document overrides** clearly in your subclass
678
- 5. **Test thoroughly** - ensure your overrides work with the recursion logic
679
- 6. **Handle errors gracefully** - follow the error result pattern
680
- 7. **Preserve metadata** - pass through rawResult and other metadata
681
-
682
- ### Common Extension Patterns
145
+ ## Advanced Features
683
146
 
684
- #### Adding Pre/Post Processing
147
+ ### Hierarchical Prompt Execution
685
148
  ```typescript
686
- protected async executePrompt(promptParams: AIPromptParams): Promise<any> {
687
- // Pre-processing
688
- await this.beforePromptExecution(promptParams);
689
-
690
- // Execute
691
- const result = await super.executePrompt(promptParams);
692
-
693
- // Post-processing
694
- await this.afterPromptExecution(result);
695
-
696
- return result;
697
- }
149
+ // System prompt provides base behavior
150
+ // Agent prompts execute as children with shared context
151
+ const result = await agent.ExecutePrompt({
152
+ systemPrompt: agentType.SystemPrompt,
153
+ agentPrompt: currentPrompt,
154
+ messages: conversationContext
155
+ });
698
156
  ```
699
157
 
700
- #### Custom Context Injection
701
- ```typescript
702
- protected async preparePromptParams(...args): Promise<AIPromptParams> {
703
- const params = await super.preparePromptParams(...args);
704
-
705
- // Inject custom context
706
- params.data.customContext = await this.loadCustomContext();
707
- params.conversationMessages = this.preprocessMessages(params.conversationMessages);
708
-
709
- return params;
710
- }
711
- ```
158
+ ### Context Management
159
+ Agents automatically manage conversation context:
160
+ - Maintains message history across steps
161
+ - Compresses context when approaching token limits
162
+ - Handles placeholder replacement in prompts
163
+ - Preserves important context during compression
712
164
 
713
- #### Conditional Execution Flow
165
+ ### Action Integration
714
166
  ```typescript
715
- protected async processNextStep(
716
- params: ExecuteAgentParams,
717
- agentType: AIAgentTypeEntity,
718
- promptResult: any
719
- ): Promise<ExecuteAgentResult> {
720
- // Check for special conditions
721
- if (this.shouldUseAlternativeFlow(promptResult)) {
722
- return await this.executeAlternativeFlow(params, promptResult);
167
+ // In agent type's DetermineNextStep
168
+ return {
169
+ type: 'action',
170
+ actionName: 'SendEmail',
171
+ actionParams: {
172
+ to: 'user@example.com',
173
+ subject: 'Analysis Complete',
174
+ body: analysisResult
723
175
  }
724
-
725
- // Otherwise use default flow
726
- return await super.processNextStep(params, agentType, promptResult);
727
- }
728
- ```
729
-
730
- ## Enhanced Execution Result Structure
731
-
732
- The AI Agents framework now provides comprehensive execution tracking through the enhanced `ExecuteAgentResult` type. This structure gives complete visibility into every step of agent execution, including all prompts, actions, sub-agents, and decisions made along the way.
733
-
734
- ### ExecuteAgentResult
735
-
736
- The main result structure returned from agent execution:
737
-
738
- ```typescript
739
- interface ExecuteAgentResult {
740
- // Core execution outcome
741
- success: boolean; // Whether the overall execution was successful
742
- finalStep: BaseAgentNextStep['step']; // The final step type that terminated execution
743
- returnValue?: any; // Optional return value from the agent
744
- errorMessage?: string; // Error message if execution failed
745
-
746
- // Tracking and history
747
- agentRun: AIAgentRunEntity; // Database entity tracking this execution
748
- executionChain: ExecutionChainStep[]; // Complete chain of execution steps
749
- }
176
+ };
750
177
  ```
751
178
 
752
- ### ExecutionChainStep
753
-
754
- Each step in the execution chain captures:
755
-
179
+ ### Sub-agent Orchestration
756
180
  ```typescript
757
- interface ExecutionChainStep {
758
- stepEntity: AIAgentRunStepEntity; // Database entity for this step
759
- executionType: 'prompt' | 'action' | 'sub-agent' | 'decision' | 'chat' | 'validation';
760
- executionResult: StepExecutionResult; // The actual result (varies by type)
761
- nextStepDecision: NextStepDecision; // What was decided after this step
762
- startTime: Date; // When the step started
763
- endTime?: Date; // When the step completed
764
- durationMs?: number; // Execution duration in milliseconds
765
- }
181
+ // Agents can invoke other agents recursively
182
+ return {
183
+ type: 'sub_agent',
184
+ agentName: 'DataValidationAgent',
185
+ messages: [
186
+ { role: 'user', content: `Validate this data: ${JSON.stringify(data)}` }
187
+ ]
188
+ };
766
189
  ```
767
190
 
768
- ### Step Execution Results
191
+ ## Database Schema
769
192
 
770
- Different execution types have specialized result structures:
193
+ Key entities used by the agent framework:
771
194
 
772
- #### PromptExecutionResult
773
- ```typescript
774
- {
775
- type: 'prompt';
776
- promptId: string;
777
- promptName: string;
778
- result: AIPromptRunResult; // Native result from @memberjunction/ai-prompts
779
- }
780
- ```
195
+ - **AIAgentType**: Agent behavior patterns and system prompts
196
+ - **AIAgent**: Configured agent instances
197
+ - **AIPrompt**: Reusable prompt templates with placeholders
198
+ - **AIAgentPrompt**: Links agents to prompts with execution order
199
+ - **AIAgentRun**: Tracks complete agent executions
200
+ - **AIAgentRunStep**: Records individual steps within runs
201
+ - **AIAgentRunStepAction**: Details of actions executed
202
+ - **AIAgentRunStepPrompt**: Prompt execution details
781
203
 
782
- #### ActionExecutionResult
783
- ```typescript
784
- {
785
- type: 'action';
786
- actionId: string;
787
- actionName: string;
788
- result: ActionResult | ActionResultSimple; // Native result from @memberjunction/actions
789
- }
790
- ```
204
+ ## Best Practices
791
205
 
792
- #### SubAgentExecutionResult
793
- ```typescript
794
- {
795
- type: 'sub-agent';
796
- subAgentId: string;
797
- subAgentName: string;
798
- result: ExecuteAgentResult; // Recursive - full execution result of sub-agent
799
- }
800
- ```
206
+ 1. **Hierarchical Design**: Use system prompts for base behavior, agent prompts for specifics
207
+ 2. **Structured Responses**: Design prompts to return parseable JSON for agent types
208
+ 3. **Modular Prompts**: Break complex tasks into ordered, focused prompts
209
+ 4. **Proper Type Registration**: Register custom agent types with ClassFactory
210
+ 5. **Comprehensive Tracking**: Leverage built-in tracking for debugging and analysis
211
+ 6. **Context Efficiency**: Let the framework handle context compression automatically
212
+ 7. **Error Handling**: Implement robust error handling in custom agent types
801
213
 
802
- ### Usage Example
214
+ ## Examples
803
215
 
216
+ ### Basic Loop Agent
804
217
  ```typescript
805
- const runner = new AgentRunner();
218
+ // Agent type configured with LoopAgentType driver
219
+ // System prompt defines JSON response format
220
+ // Agent prompts execute tasks iteratively
806
221
  const result = await runner.RunAgent({
807
- agent: myAgent,
808
- conversationMessages: messages,
222
+ agent: loopAgent,
223
+ conversationMessages: [
224
+ { role: 'user', content: 'Analyze these sales figures and create a report' }
225
+ ],
809
226
  contextUser: user
810
227
  });
811
-
812
- // Access execution outcome
813
- console.log(`Success: ${result.success}`);
814
- console.log(`Final step: ${result.finalStep}`);
815
- console.log(`Return value:`, result.returnValue);
816
-
817
- // Access the agent run record
818
- console.log(`Agent run ID: ${result.agentRun.ID}`);
819
- console.log(`Started at: ${result.agentRun.StartedAt}`);
820
- console.log(`Duration: ${result.agentRun.CompletedAt - result.agentRun.StartedAt}ms`);
821
-
822
- // Analyze the execution chain
823
- result.executionChain.forEach((step, index) => {
824
- console.log(`\nStep ${index + 1}: ${step.executionType}`);
825
- console.log(` Name: ${step.stepEntity.StepName}`);
826
- console.log(` Duration: ${step.durationMs}ms`);
827
- console.log(` Success: ${step.stepEntity.Success}`);
828
-
829
- // Access type-specific results
830
- switch (step.executionResult.type) {
831
- case 'prompt':
832
- console.log(` Prompt: ${step.executionResult.promptName}`);
833
- console.log(` Tokens used: ${step.executionResult.result.tokensUsed}`);
834
- break;
835
- case 'action':
836
- console.log(` Action: ${step.executionResult.actionName}`);
837
- console.log(` Result: ${step.executionResult.result.Success}`);
838
- break;
839
- case 'sub-agent':
840
- console.log(` Sub-agent: ${step.executionResult.subAgentName}`);
841
- console.log(` Sub-steps: ${step.executionResult.result.executionChain.length}`);
842
- break;
843
- }
844
-
845
- // Show what was decided next
846
- console.log(` Next decision: ${step.nextStepDecision.decision}`);
847
- console.log(` Reasoning: ${step.nextStepDecision.reasoning}`);
848
- });
849
-
850
- // Visualize the execution flow
851
- const executionFlow = result.executionChain
852
- .map(step => `${step.executionType} → ${step.nextStepDecision.decision}`)
853
- .join(' → ');
854
- console.log(`\nExecution flow: ${executionFlow}`);
855
- ```
856
-
857
- ### Database Persistence
858
-
859
- All execution data is automatically persisted to the database:
860
-
861
- - **AIAgentRun**: Tracks the overall agent execution
862
- - Links to parent runs for sub-agent tracking
863
- - Stores final results and state
864
- - Tracks timing and success status
865
-
866
- - **AIAgentRunStep**: Tracks individual execution steps
867
- - Links to the parent run
868
- - Stores step-specific data (input/output)
869
- - Tracks step timing and success
870
-
871
- This enables:
872
- - Historical analysis of agent behavior
873
- - Performance optimization based on real data
874
- - Debugging complex agent interactions
875
- - Compliance and audit trails
876
-
877
- ### Analyzing Sub-Agent Execution
878
-
879
- Sub-agent results are fully recursive, allowing deep analysis:
880
-
881
- ```typescript
882
- function analyzeExecutionDepth(result: ExecuteAgentResult, depth = 0): void {
883
- const indent = ' '.repeat(depth);
884
- console.log(`${indent}Agent: ${result.agentRun.AgentID}`);
885
- console.log(`${indent}Steps: ${result.executionChain.length}`);
886
-
887
- // Find sub-agent executions
888
- const subAgentSteps = result.executionChain.filter(
889
- step => step.executionType === 'sub-agent'
890
- ) as Array<{ executionResult: SubAgentExecutionResult }>;
891
-
892
- // Recursively analyze sub-agents
893
- for (const step of subAgentSteps) {
894
- analyzeExecutionDepth(step.executionResult.result, depth + 1);
895
- }
896
- }
897
-
898
- // Analyze the entire execution tree
899
- analyzeExecutionDepth(result);
900
- ```
901
-
902
- ### Performance Analysis
903
-
904
- Use the execution chain for performance optimization:
905
-
906
- ```typescript
907
- // Calculate time spent in each type of operation
908
- const timingAnalysis = result.executionChain.reduce((acc, step) => {
909
- const type = step.executionType;
910
- acc[type] = (acc[type] || 0) + (step.durationMs || 0);
911
- return acc;
912
- }, {} as Record<string, number>);
913
-
914
- console.log('Time spent by operation type:', timingAnalysis);
915
-
916
- // Find slowest steps
917
- const slowestSteps = result.executionChain
918
- .filter(step => step.durationMs)
919
- .sort((a, b) => b.durationMs! - a.durationMs!)
920
- .slice(0, 5);
921
-
922
- console.log('Top 5 slowest steps:', slowestSteps.map(s => ({
923
- name: s.stepEntity.StepName,
924
- duration: s.durationMs,
925
- type: s.executionType
926
- })));
927
- ```
928
-
929
- ## Type Exports
930
-
931
- The Agents package exports comprehensive types for agent operations:
932
-
933
- ### Core Agent Types
934
- - `AgentExecutionParams` - Parameters for agent execution
935
- - `AgentExecutionResult` - Result from agent execution
936
- - `BaseAgentNextStep` - Next step decision structure
937
- - `ExecutionChainStep` - Individual step in execution chain
938
-
939
- ### Agent Runner Types
940
- - `AgentRunnerParams` - Parameters for AgentRunner
941
- - `AgentRunnerResult` - Enhanced result with decision history
942
- - `AgentProgressUpdate` - Progress tracking structure
943
- - `AgentStreamingUpdate` - Streaming content structure
944
-
945
- ### Conductor Types
946
- - `ConductorDecisionInput` - Input for conductor decisions
947
- - `ConductorDecisionResponse` - Structured decision response
948
- - `ExecutionStep` - Individual execution plan step
949
- - `ConductorDecisionType` - Decision type enumeration
950
-
951
- ### Factory and Interface Types
952
- - `IAgentFactory` - Factory interface for agent creation
953
- - `BaseAgent` - Base class for all agents
954
- - `ConductorAgent` - Specialized conductor agent class
955
-
956
- ## Import Examples
957
-
958
- ```typescript
959
- // Import main classes
960
- import { BaseAgent, ConductorAgent, AgentRunner } from '@memberjunction/ai-agents';
961
- import { GetAgentFactory } from '@memberjunction/ai-agents';
962
-
963
- // Import types
964
- import {
965
- AgentExecutionParams,
966
- AgentExecutionResult,
967
- AgentRunnerParams,
968
- AgentRunnerResult,
969
- ConductorDecisionResponse
970
- } from '@memberjunction/ai-agents';
971
-
972
- // Import base AI types from Core
973
- import { ChatMessage, ChatResult } from '@memberjunction/ai';
974
-
975
- // Import prompt types when needed
976
- import { AIPromptParams, AIPromptRunResult } from '@memberjunction/ai-prompts';
977
-
978
- // Import entity types
979
- import { AIAgentEntity, AIAgentTypeEntity } from '@memberjunction/core-entities';
980
- ```
981
-
982
- ## API Reference
983
-
984
- ### AgentRunner Class
985
-
986
- The core coordination engine for orchestrating BaseAgent and ConductorAgent interactions.
987
-
988
- #### Constructor
989
- ```typescript
990
- constructor(conductor: ConductorAgent, contextUser: UserInfo)
991
- ```
992
-
993
- **Parameters:**
994
- - `conductor: ConductorAgent` - The conductor agent that makes orchestration decisions
995
- - `contextUser: UserInfo` - User context for authentication and permissions
996
-
997
- #### Methods
998
-
999
- ##### `Run(params: AgentRunnerParams): Promise<AgentRunnerResult>`
1000
- Runs the agent using the BaseAgent + ConductorAgent separation of concerns pattern.
1001
-
1002
- **Parameters:**
1003
- - `params: AgentRunnerParams` - Execution parameters including base agent, goal, and configuration
1004
-
1005
- **Returns:** `Promise<AgentRunnerResult>` - Enhanced execution result with decision history and outcomes
1006
-
1007
- **Key Features:**
1008
- - Clean separation between execution and decision-making
1009
- - Iterative BaseAgent → ConductorAgent → Action execution pattern
1010
- - Mixed action and sub-agent execution with proper ordering
1011
- - Progress tracking and cancellation support
1012
- - Comprehensive execution step tracking
1013
-
1014
- ### BaseAgent Class
1015
-
1016
- The domain execution engine that focuses solely on executing agent-specific prompts.
1017
-
1018
- #### Constructor
1019
- ```typescript
1020
- constructor(agent: AIAgentEntityExtended, factory: IAgentFactory, contextUser: UserInfo, promptRunner?: AIPromptRunner)
1021
- ```
1022
-
1023
- **Parameters:**
1024
- - `agent: AIAgentEntityExtended` - The agent entity definition
1025
- - `factory: IAgentFactory` - Factory for creating additional agent instances
1026
- - `contextUser: UserInfo` - User context for authentication and permissions
1027
- - `promptRunner: AIPromptRunner` - Optional prompt runner instance
1028
-
1029
- #### Methods
1030
-
1031
- ##### `Execute(params: AgentExecutionParams): Promise<AgentExecutionResult>`
1032
- Executes the agent's specific prompts and returns the result.
1033
-
1034
- **Parameters:**
1035
- - `params: AgentExecutionParams` - Execution parameters including context, data, and callbacks
1036
-
1037
- **Returns:** `Promise<AgentExecutionResult>` - The execution result
1038
-
1039
- **Key Features:**
1040
- - Single responsibility: execute agent-specific prompts only
1041
- - Conversation context management and compression
1042
- - Progress monitoring and streaming response support
1043
- - Cancellation support with graceful cleanup
1044
-
1045
- ### ConductorAgent Class
1046
-
1047
- The decision-making engine that analyzes context and makes orchestration decisions.
1048
-
1049
- #### Constructor
1050
- ```typescript
1051
- constructor(agent: AIAgentEntityExtended, factory: IAgentFactory, contextUser: UserInfo)
1052
- ```
1053
-
1054
- #### Methods
1055
-
1056
- ##### `MakeDecision(decisionInput: ConductorDecisionInput): Promise<ConductorDecisionResponse>`
1057
- Makes an autonomous decision about what to do next based on current context.
1058
-
1059
- **Parameters:**
1060
- - `decisionInput: ConductorDecisionInput` - Complete context for decision-making
1061
-
1062
- **Returns:** `Promise<ConductorDecisionResponse>` - Structured decision response
1063
-
1064
- ##### `executeAction(actionId: string, parameters: Record<string, unknown>): Promise<ActionResult>`
1065
- Executes an action using the ActionEngine.
1066
-
1067
- ##### `executeSubAgent(subAgentId: string, parameters: Record<string, unknown>, parentContext?: Record<string, unknown>): Promise<AgentExecutionResult>`
1068
- Executes a sub-agent with the provided parameters.
1069
-
1070
- ### Types and Interfaces
1071
-
1072
- #### AgentRunnerParams
1073
- ```typescript
1074
- interface AgentRunnerParams extends AgentExecutionParams {
1075
- agent: BaseAgent;
1076
- maxIterations?: number;
1077
- goal?: string;
1078
- enableDetailedLogging?: boolean;
1079
- }
1080
- ```
1081
-
1082
- #### AgentRunnerResult
1083
- ```typescript
1084
- interface AgentRunnerResult extends AgentExecutionResult {
1085
- decisionHistory?: ConductorDecisionResponse[];
1086
- actionResults?: ActionResult[];
1087
- finalDecision?: ConductorDecisionResponse;
1088
- iterationCount?: number;
1089
- executionSteps?: ExecutionHistoryItem[];
1090
- }
1091
228
  ```
1092
229
 
1093
- #### ConductorDecisionResponse
230
+ ### Custom Decision Tree Agent
1094
231
  ```typescript
1095
- interface ConductorDecisionResponse {
1096
- decision: ConductorDecisionType;
1097
- reasoning: string;
1098
- executionPlan: ExecutionStep[];
1099
- isTaskComplete: boolean;
1100
- finalResponse?: string;
1101
- confidence: number;
1102
- metadata?: {
1103
- estimatedDuration?: number;
1104
- riskLevel?: 'low' | 'medium' | 'high';
1105
- failureStrategy?: string;
1106
- };
1107
- }
1108
- ```
1109
-
1110
- #### ExecutionStep
1111
- ```typescript
1112
- interface ExecutionStep {
1113
- type: 'action' | 'subagent';
1114
- targetId: string;
1115
- parameters?: Record<string, unknown>;
1116
- executionOrder: number;
1117
- allowParallel?: boolean;
1118
- description?: string;
1119
- }
1120
- ```
1121
-
1122
- #### AgentProgressUpdate
1123
- ```typescript
1124
- interface AgentProgressUpdate {
1125
- step: 'initialization' | 'prompt_execution' | 'completion';
1126
- percentage: number;
1127
- message: string;
1128
- metadata?: Record<string, unknown>;
1129
- }
1130
- ```
1131
-
1132
- ## Configuration
1133
-
1134
- Agents are configured through the MemberJunction metadata system. Key configuration options include:
1135
-
1136
- ### Agent Configuration (AIAgent Entity)
1137
-
1138
- | Field | Description | Default |
1139
- |-------|-------------|---------|
1140
- | `Name` | Unique agent identifier | Required |
1141
- | `Description` | Agent purpose and capabilities | Required |
1142
- | `ParentID` | Parent agent for hierarchical composition | null |
1143
- | `ExecutionMode` | How child agents execute (Sequential/Parallel) | Sequential |
1144
- | `EnableContextCompression` | Whether to compress long conversations | false |
1145
- | `ContextCompressionMessageThreshold` | Messages before compression triggers | 50 |
1146
- | `ContextCompressionMessageRetentionCount` | Recent messages to keep uncompressed | 10 |
1147
-
1148
- ### Integration with Prompts
1149
-
1150
- Agents use prompts through the `AIAgentPrompt` entity:
1151
-
1152
- ```typescript
1153
- // Example: Associate a prompt with an agent
1154
- const agentPrompt = await md.GetEntityObject<AIAgentPromptEntity>('AI Agent Prompts');
1155
- agentPrompt.NewRecord();
1156
- agentPrompt.AgentID = agent.ID;
1157
- agentPrompt.PromptID = prompt.ID;
1158
- agentPrompt.Purpose = 'Main conversation handler';
1159
- agentPrompt.ExecutionOrder = 1;
1160
- agentPrompt.ContextBehavior = 'Recent'; // or 'Full', 'None'
1161
- agentPrompt.ContextMessageCount = 20;
1162
- await agentPrompt.Save();
1163
- ```
1164
-
1165
- ## Dependencies
1166
-
1167
- - `@memberjunction/core`: ^2.43.0 - MemberJunction core library
1168
- - `@memberjunction/global`: ^2.43.0 - MemberJunction global utilities
1169
- - `@memberjunction/core-entities`: ^2.43.0 - MemberJunction entity definitions
1170
- - `@memberjunction/ai`: ^2.43.0 - Base AI types and interfaces (imported for core types)
1171
- - `@memberjunction/aiengine`: ^2.43.0 - AI model orchestration and agent type definitions
1172
- - `@memberjunction/ai-prompts`: ^2.43.0 - Advanced prompt management
1173
- - `@memberjunction/templates`: ^2.43.0 - Template rendering support
1174
- - `rxjs`: ^7.8.1 - Reactive programming support
1175
- - `dotenv`: ^16.4.1 - Environment configuration
1176
-
1177
- ## Related Packages
1178
-
1179
- - `@memberjunction/aiengine`: Core AI engine and model management
1180
- - `@memberjunction/ai-prompts`: Advanced prompt execution and management
1181
- - `@memberjunction/templates`: Template rendering for dynamic content
1182
-
1183
- ## Advanced Features
1184
-
1185
- ### Parallel Agent Execution
1186
-
1187
- ```typescript
1188
- class ParallelAnalysisAgent extends BaseAgent {
1189
- async execute(context: AgentContext): Promise<AgentResult> {
1190
- // Execute multiple sub-agents in parallel
1191
- const [sentiment, intent, entities] = await Promise.all([
1192
- this.sentimentAgent.execute(context),
1193
- this.intentAgent.execute(context),
1194
- this.entityExtractorAgent.execute(context)
1195
- ]);
232
+ @RegisterClass(BaseAgentType, "DecisionTreeAgent")
233
+ export class DecisionTreeAgent extends BaseAgentType {
234
+ async DetermineNextStep(result: AIPromptRunResult): Promise<BaseAgentNextStep> {
235
+ const decision = JSON.parse(result.FullResult);
1196
236
 
1197
- // Combine results
1198
- return {
1199
- response: this.synthesizeResults(sentiment, intent, entities),
1200
- success: true,
1201
- metadata: {
1202
- childAgentResults: [sentiment, intent, entities]
1203
- }
1204
- };
1205
- }
1206
- }
1207
- ```
1208
-
1209
- ### Agent Learning and Adaptation
1210
-
1211
- ```typescript
1212
- class LearningAgent extends BaseAgent {
1213
- async execute(context: AgentContext): Promise<AgentResult> {
1214
- try {
1215
- const result = await super.execute(context);
1216
-
1217
- // Learn from successful execution
1218
- if (result.success) {
1219
- await this.addNote(
1220
- `Successfully handled query type: ${this.classifyQuery(context)}`,
1221
- 'learning'
1222
- );
1223
- }
1224
-
1225
- return result;
1226
- } catch (error) {
1227
- // Learn from errors
1228
- await this.addNote(
1229
- `Error handling query: ${error.message}`,
1230
- 'error'
1231
- );
1232
- throw error;
237
+ switch(decision.branch) {
238
+ case 'needs_data':
239
+ return { type: 'action', actionName: 'FetchData', actionParams: decision.params };
240
+ case 'analyze':
241
+ return { type: 'sub_agent', agentName: 'AnalysisAgent', messages: decision.context };
242
+ case 'complete':
243
+ return { type: 'stop', reason: decision.summary };
244
+ default:
245
+ return { type: 'continue' };
1233
246
  }
1234
247
  }
1235
248
  }
1236
249
  ```
1237
250
 
1238
- ### Custom Action Implementation
251
+ ## Architecture Documentation
1239
252
 
1240
- ```typescript
1241
- class DataAnalysisAgent extends BaseAgent {
1242
- async initialize(): Promise<void> {
1243
- await super.initialize();
1244
-
1245
- // Register custom actions
1246
- this.registerAction('analyzeData', this.analyzeData.bind(this));
1247
- this.registerAction('generateReport', this.generateReport.bind(this));
1248
- this.registerAction('exportResults', this.exportResults.bind(this));
1249
- }
1250
-
1251
- private async analyzeData(params: { datasetId: string }): Promise<any> {
1252
- // Implementation for data analysis
1253
- const dataset = await this.loadDataset(params.datasetId);
1254
- return this.performAnalysis(dataset);
1255
- }
1256
- }
1257
- ```
253
+ For detailed architecture information, see [agent-architecture.md](./agent-architecture.md).
1258
254
 
1259
- ## Error Handling
255
+ ## Payload and State Management
1260
256
 
1261
- The framework provides comprehensive error handling:
1262
-
1263
- ```typescript
1264
- try {
1265
- const result = await agent.execute(context);
1266
- console.log('Success:', result);
1267
- } catch (error) {
1268
- if (error instanceof AgentExecutionError) {
1269
- console.error('Execution failed:', error.message);
1270
- console.error('Agent:', error.agentName);
1271
- console.error('Context:', error.context);
1272
- } else if (error instanceof AgentInitializationError) {
1273
- console.error('Failed to initialize agent:', error.message);
1274
- } else {
1275
- console.error('Unexpected error:', error);
1276
- }
1277
- }
1278
- ```
1279
-
1280
- ## Performance Considerations
1281
-
1282
- 1. **Context Compression**: Enable for long conversations to reduce token usage
1283
- 2. **Caching**: Leverage result caching for repeated queries
1284
- 3. **Parallel Execution**: Use parallel mode for independent sub-agents
1285
- 4. **Resource Limits**: Configure appropriate timeouts and token limits
1286
-
1287
- ## Development Status
1288
-
1289
- ✅ **Core Framework Complete** - The MJ AI Agent framework now provides a comprehensive, metadata-driven system for creating and executing AI agents.
1290
-
1291
- ### Current Implementation Status
1292
-
1293
- - ✅ Package structure and configuration
1294
- - ✅ BaseAgent class implementation with full metadata-driven execution
1295
- - ✅ AgentFactory for dynamic agent instantiation
1296
- - ✅ Hierarchical agent composition with parent-child relationships
1297
- - ✅ Context management and compression
1298
- - ✅ AI Prompt system integration
1299
- - ✅ Progress tracking and streaming support
1300
- - ✅ ClassFactory integration for extensible agent types
1301
- - ✅ Comprehensive error handling and cancellation support
1302
- - ✅ Example agents and usage patterns
1303
-
1304
- ### Architecture Highlights
1305
-
1306
- 1. **Metadata-Driven**: Agents configured through database entities (AIAgent, AIAgentPrompt, etc.)
1307
- 2. **Hierarchical Composition**: Support for conductor patterns with child agents
1308
- 3. **Intelligent Context Management**: Automatic compression and filtering
1309
- 4. **Advanced Prompt Integration**: Full integration with AI Prompt system
1310
- 5. **Extensible Design**: Easy custom agent creation through class registration
1311
-
1312
- ### Current Architecture (Implemented)
1313
-
1314
- The framework provides a separation of concerns architecture with specialized responsibilities:
1315
-
1316
- ```typescript
1317
- // Get factory and create specialized agents
1318
- const factory = GetAgentFactory();
1319
- const baseAgent = await factory.CreateAgent("CustomerSupport", null, contextUser);
1320
- const conductorAgent = await factory.CreateAgent("Conductor", null, contextUser);
1321
-
1322
- // Execute with clean separation of concerns
1323
- const runner = new AgentRunner(conductorAgent, contextUser);
1324
- const result = await runner.Run({
1325
- agent: baseAgent,
1326
- goal: "Help customer with their issue",
1327
- data: { customerName: "John" },
1328
- conversationMessages: [...],
1329
- onProgress: (progress) => console.log(progress),
1330
- cancellationToken: controller.signal
1331
- });
1332
-
1333
- // BaseAgent handles domain execution, ConductorAgent makes decisions
1334
- // AgentRunner coordinates the interaction between them
1335
- ```
1336
-
1337
- ### Hierarchical Prompt Integration
1338
-
1339
- The framework integrates with the AI Prompts system through hierarchical prompt execution:
1340
-
1341
- ```typescript
1342
- // Agent types define system prompts for behavioral characteristics
1343
- AIAgentType.SystemPromptID -> AIPrompt (system template)
1344
-
1345
- // Agent-specific prompts provide domain logic
1346
- AIAgent -> AIAgentPrompt -> AIPrompt (agent-specific instructions)
1347
-
1348
- // Runtime: Hierarchical execution with parent-child relationships
1349
- // Parent prompts specify children via childPrompts array
1350
- // Depth-first traversal with parallel execution at each level
1351
- ```
1352
-
1353
- ## License
1354
-
1355
- ISC
1356
-
1357
- ---
1358
-
1359
- ## Testing
1360
-
1361
- ```typescript
1362
- import { BaseAgent } from '@memberjunction/ai-agents';
1363
- import { MockAgentEntity } from './test-utils';
1364
-
1365
- describe('CustomerSupportAgent', () => {
1366
- let agent: CustomerSupportAgent;
1367
-
1368
- beforeEach(async () => {
1369
- const mockEntity = new MockAgentEntity({
1370
- Name: 'Test Agent',
1371
- EnableContextCompression: true,
1372
- ContextCompressionMessageThreshold: 10
1373
- });
1374
-
1375
- agent = new CustomerSupportAgent(mockEntity);
1376
- await agent.initialize();
1377
- });
1378
-
1379
- test('should handle customer query', async () => {
1380
- const result = await agent.execute({
1381
- conversationId: 'test-123',
1382
- messages: [
1383
- { role: 'user', content: 'What is my order status?' }
1384
- ]
1385
- });
1386
-
1387
- expect(result.success).toBe(true);
1388
- expect(result.response).toContain('order');
1389
- });
1390
-
1391
- test('should compress long conversations', async () => {
1392
- const longContext = {
1393
- conversationId: 'test-456',
1394
- messages: Array(15).fill(null).map((_, i) => ({
1395
- role: i % 2 === 0 ? 'user' : 'assistant',
1396
- content: `Message ${i}`
1397
- }))
1398
- };
1399
-
1400
- const result = await agent.execute(longContext);
1401
- expect(result.metadata.contextCompressed).toBe(true);
1402
- });
1403
- });
1404
- ```
1405
-
1406
- ## Troubleshooting
1407
-
1408
- ### Common Issues
1409
-
1410
- 1. **Agent Not Found**: Ensure the agent is properly registered in the database
1411
- 2. **Initialization Failures**: Check that all required prompts and configurations exist
1412
- 3. **Context Overflow**: Enable context compression for long conversations
1413
- 4. **Performance Issues**: Review parallel execution settings and caching configuration
1414
-
1415
- ### Debug Mode
1416
-
1417
- ```typescript
1418
- // Enable debug logging
1419
- process.env.MJ_AI_AGENT_DEBUG = 'true';
1420
-
1421
- const agent = new MyAgent(entity);
1422
- agent.on('debug', (message) => {
1423
- console.log('[Agent Debug]:', message);
1424
- });
1425
- ```
257
+ For comprehensive information about managing payload flow between agents and sub-agents, including access control and best practices, see [PAYLOAD_STATE_MANAGEMENT.md](./PAYLOAD_STATE_MANAGEMENT.md).
1426
258
 
1427
259
  ## Contributing
1428
260
 
1429
- When developing agents using this framework:
261
+ Contributions are welcome! Please see the main MemberJunction [contributing guide](../../../CONTRIBUTING.md).
1430
262
 
1431
- 1. **Always extend BaseAgent** for consistency and built-in functionality
1432
- 2. **Follow the lifecycle patterns** defined in the base class
1433
- 3. **Use meaningful names and descriptions** for agents and actions
1434
- 4. **Implement proper error handling** in custom execution logic
1435
- 5. **Leverage the note system** for agent learning and improvement
1436
- 6. **Test with various context scenarios** to ensure robustness
1437
- 7. **Document custom actions and behaviors** in your agent implementations
1438
- 8. **Follow TypeScript best practices** and avoid `any` types
263
+ ## License
1439
264
 
1440
- For detailed development guidelines and best practices, refer to the [Agent Architecture.md](./Agent%20Architecture.md) documentation.
265
+ This package is part of the MemberJunction project. See the [LICENSE](../../../LICENSE) file for details.