@memberjunction/ai-agents 2.59.0 → 2.61.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 +182 -1357
- package/dist/AgentRunner.d.ts.map +1 -1
- package/dist/AgentRunner.js +10 -5
- package/dist/AgentRunner.js.map +1 -1
- package/dist/PayloadManager.d.ts +48 -0
- package/dist/PayloadManager.d.ts.map +1 -0
- package/dist/PayloadManager.js +478 -0
- package/dist/PayloadManager.js.map +1 -0
- package/dist/agent-types/base-agent-type.d.ts +7 -2
- package/dist/agent-types/base-agent-type.d.ts.map +1 -1
- package/dist/agent-types/base-agent-type.js +28 -0
- package/dist/agent-types/base-agent-type.js.map +1 -1
- package/dist/agent-types/loop-agent-response-type.d.ts +4 -3
- package/dist/agent-types/loop-agent-response-type.d.ts.map +1 -1
- package/dist/agent-types/loop-agent-type.d.ts +4 -3
- package/dist/agent-types/loop-agent-type.d.ts.map +1 -1
- package/dist/agent-types/loop-agent-type.js +53 -30
- package/dist/agent-types/loop-agent-type.js.map +1 -1
- package/dist/base-agent.d.ts +21 -19
- package/dist/base-agent.d.ts.map +1 -1
- package/dist/base-agent.js +344 -520
- package/dist/base-agent.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +12 -10
package/README.md
CHANGED
|
@@ -1,21 +1,45 @@
|
|
|
1
1
|
# @memberjunction/ai-agents
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
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:
|
|
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
|
-
//
|
|
340
|
-
const agent = new
|
|
341
|
-
const
|
|
342
|
-
agent:
|
|
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:
|
|
345
|
-
|
|
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
|
-
|
|
73
|
+
## Agent Configuration
|
|
359
74
|
|
|
360
|
-
|
|
75
|
+
Agents are configured through MemberJunction entities:
|
|
361
76
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
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
|
-
|
|
372
|
-
|
|
81
|
+
2. **AIAgent**: Specific agent instance
|
|
82
|
+
- `AgentTypeID`: Links to the agent type
|
|
83
|
+
- Configuration for specific use cases
|
|
373
84
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
85
|
+
3. **AIPrompt**: Reusable prompt templates
|
|
86
|
+
- Support for placeholders and dynamic content
|
|
87
|
+
- Can be chained hierarchically
|
|
377
88
|
|
|
378
|
-
|
|
89
|
+
4. **AIAgentPrompt**: Associates prompts with agents
|
|
90
|
+
- `ExecutionOrder`: Determines prompt execution sequence
|
|
91
|
+
- Links agents to their specific prompts
|
|
379
92
|
|
|
380
|
-
|
|
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 {
|
|
96
|
+
import { BaseAgentType, RegisterClass, BaseAgentNextStep } from '@memberjunction/ai-agents';
|
|
97
|
+
import { AIPromptRunResult } from '@memberjunction/ai-prompts';
|
|
410
98
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
420
|
-
|
|
421
|
-
|
|
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
|
-
|
|
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
|
-
|
|
483
|
-
-
|
|
484
|
-
-
|
|
485
|
-
-
|
|
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
|
-
|
|
490
|
-
-
|
|
491
|
-
-
|
|
492
|
-
-
|
|
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
|
-
|
|
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
|
-
|
|
499
|
-
|
|
500
|
-
|
|
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
|
-
|
|
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
|
-
|
|
147
|
+
### Hierarchical Prompt Execution
|
|
685
148
|
```typescript
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
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
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
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
|
-
|
|
165
|
+
### Action Integration
|
|
714
166
|
```typescript
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
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
|
-
###
|
|
753
|
-
|
|
754
|
-
Each step in the execution chain captures:
|
|
755
|
-
|
|
179
|
+
### Sub-agent Orchestration
|
|
756
180
|
```typescript
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
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
|
-
|
|
191
|
+
## Database Schema
|
|
769
192
|
|
|
770
|
-
|
|
193
|
+
Key entities used by the agent framework:
|
|
771
194
|
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
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
|
-
|
|
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
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
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
|
-
|
|
214
|
+
## Examples
|
|
803
215
|
|
|
216
|
+
### Basic Loop Agent
|
|
804
217
|
```typescript
|
|
805
|
-
|
|
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:
|
|
808
|
-
conversationMessages:
|
|
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
|
-
|
|
230
|
+
### Custom Decision Tree Agent
|
|
1094
231
|
```typescript
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
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
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
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
|
-
|
|
251
|
+
## Architecture Documentation
|
|
1239
252
|
|
|
1240
|
-
|
|
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
|
-
##
|
|
255
|
+
## Payload and State Management
|
|
1260
256
|
|
|
1261
|
-
|
|
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
|
-
|
|
261
|
+
Contributions are welcome! Please see the main MemberJunction [contributing guide](../../../CONTRIBUTING.md).
|
|
1430
262
|
|
|
1431
|
-
|
|
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
|
-
|
|
265
|
+
This package is part of the MemberJunction project. See the [LICENSE](../../../LICENSE) file for details.
|