@memberjunction/ai-agents 2.108.0 → 2.110.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 +564 -29
- package/dist/AgentDataPreloader.d.ts +25 -0
- package/dist/AgentDataPreloader.d.ts.map +1 -0
- package/dist/AgentDataPreloader.js +264 -0
- package/dist/AgentDataPreloader.js.map +1 -0
- package/dist/PayloadManager.d.ts +1 -1
- package/dist/PayloadManager.d.ts.map +1 -1
- package/dist/PayloadManager.js.map +1 -1
- package/dist/agent-types/flow-agent-type.d.ts.map +1 -1
- package/dist/agent-types/flow-agent-type.js +17 -4
- package/dist/agent-types/flow-agent-type.js.map +1 -1
- package/dist/base-agent.d.ts +1 -0
- package/dist/base-agent.d.ts.map +1 -1
- package/dist/base-agent.js +49 -0
- 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 +8 -8
package/README.md
CHANGED
|
@@ -268,6 +268,302 @@ The callback is invoked:
|
|
|
268
268
|
|
|
269
269
|
## Advanced Features
|
|
270
270
|
|
|
271
|
+
### Agent Data Preloading
|
|
272
|
+
|
|
273
|
+
Agents can declaratively preload reference data without requiring custom application code or action calls. Data sources are configured through the `AIAgentDataSource` entity and automatically loaded before agent execution.
|
|
274
|
+
|
|
275
|
+
#### Overview
|
|
276
|
+
|
|
277
|
+
Data preloading solves the common problem of agents needing access to reference data (like entity lists, configuration values, or initial state) that doesn't change during execution. Instead of:
|
|
278
|
+
- Writing custom application code to load data
|
|
279
|
+
- Having agents call actions to fetch data (which bloats conversation context)
|
|
280
|
+
- Manually passing the same data to every agent invocation
|
|
281
|
+
|
|
282
|
+
Agents can now specify data sources that are automatically loaded and injected into the appropriate destination (`data`, `context`, or `payload`).
|
|
283
|
+
|
|
284
|
+
#### Three Destination Types
|
|
285
|
+
|
|
286
|
+
**1. Data Destination** - For Nunjucks templates in prompts (visible to LLMs)
|
|
287
|
+
```typescript
|
|
288
|
+
// Configuration
|
|
289
|
+
{
|
|
290
|
+
"Name": "ALL_ENTITIES",
|
|
291
|
+
"SourceType": "RunView",
|
|
292
|
+
"EntityName": "Entities",
|
|
293
|
+
"OrderBy": "Name ASC",
|
|
294
|
+
"DestinationType": "Data",
|
|
295
|
+
"DestinationPath": null // Uses "ALL_ENTITIES" at root level
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Result in agent prompt:
|
|
299
|
+
// params.data.ALL_ENTITIES = [{ Name: "Users", ... }, { Name: "Entities", ... }]
|
|
300
|
+
|
|
301
|
+
// Prompt can use Nunjucks:
|
|
302
|
+
// You have access to {{ALL_ENTITIES.length}} entities:
|
|
303
|
+
// {% for entity in ALL_ENTITIES %}
|
|
304
|
+
// - {{entity.Name}}: {{entity.Description}}
|
|
305
|
+
// {% endfor %}
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
**2. Context Destination** - For actions only (NOT visible to LLMs)
|
|
309
|
+
```typescript
|
|
310
|
+
// Configuration
|
|
311
|
+
{
|
|
312
|
+
"Name": "ORG_SETTINGS",
|
|
313
|
+
"SourceType": "RunView",
|
|
314
|
+
"EntityName": "Organization Settings",
|
|
315
|
+
"ExtraFilter": "OrgID='${context.organizationId}'",
|
|
316
|
+
"DestinationType": "Context",
|
|
317
|
+
"DestinationPath": "organization.settings"
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// Result:
|
|
321
|
+
// params.context.organization.settings = { apiEndpoint: "...", features: [...] }
|
|
322
|
+
|
|
323
|
+
// Actions can access context, but prompts/LLMs cannot
|
|
324
|
+
// This keeps API keys and sensitive configuration away from LLMs
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
**3. Payload Destination** - For agent state initialization
|
|
328
|
+
```typescript
|
|
329
|
+
// Configuration
|
|
330
|
+
{
|
|
331
|
+
"Name": "CustomerOrders",
|
|
332
|
+
"SourceType": "RunQuery",
|
|
333
|
+
"QueryName": "Recent Orders by Customer",
|
|
334
|
+
"Parameters": JSON.stringify({ customerId: "{{context.customerId}}" }),
|
|
335
|
+
"DestinationType": "Payload",
|
|
336
|
+
"DestinationPath": "analysis.orders.recent"
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Result:
|
|
340
|
+
// params.payload.analysis.orders.recent = [{ OrderID: "123", ... }]
|
|
341
|
+
|
|
342
|
+
// Agent starts with rich initial state without caller manually loading it
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
#### Data Source Types
|
|
346
|
+
|
|
347
|
+
**RunView Data Sources** - Query entities with filters
|
|
348
|
+
```typescript
|
|
349
|
+
{
|
|
350
|
+
"Name": "ACTIVE_MODELS",
|
|
351
|
+
"SourceType": "RunView",
|
|
352
|
+
"EntityName": "AI Models",
|
|
353
|
+
"ExtraFilter": "IsActive=1 AND Vendor='OpenAI'",
|
|
354
|
+
"OrderBy": "Priority DESC",
|
|
355
|
+
"FieldsToRetrieve": JSON.stringify(["ID", "Name", "Vendor", "MaxInputTokens"]),
|
|
356
|
+
"ResultType": "simple", // or "entity_object"
|
|
357
|
+
"MaxRows": 100,
|
|
358
|
+
"DestinationType": "Data"
|
|
359
|
+
}
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
**RunQuery Data Sources** - Execute stored queries
|
|
363
|
+
```typescript
|
|
364
|
+
{
|
|
365
|
+
"Name": "MONTHLY_STATS",
|
|
366
|
+
"SourceType": "RunQuery",
|
|
367
|
+
"QueryName": "Monthly Analytics",
|
|
368
|
+
"CategoryPath": "/Reports/Analytics",
|
|
369
|
+
"Parameters": JSON.stringify({
|
|
370
|
+
month: "{{context.currentMonth}}",
|
|
371
|
+
year: "{{context.currentYear}}"
|
|
372
|
+
}),
|
|
373
|
+
"DestinationType": "Payload",
|
|
374
|
+
"DestinationPath": "stats.monthly"
|
|
375
|
+
}
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
#### Path Support
|
|
379
|
+
|
|
380
|
+
The `DestinationPath` field supports nested paths using dot notation:
|
|
381
|
+
|
|
382
|
+
```typescript
|
|
383
|
+
// Simple root-level
|
|
384
|
+
{
|
|
385
|
+
"Name": "ENTITIES",
|
|
386
|
+
"DestinationPath": null // Uses "ENTITIES" at root
|
|
387
|
+
}
|
|
388
|
+
// Result: data.ENTITIES
|
|
389
|
+
|
|
390
|
+
// Nested paths
|
|
391
|
+
{
|
|
392
|
+
"Name": "ModelList",
|
|
393
|
+
"DestinationPath": "config.ai.models"
|
|
394
|
+
}
|
|
395
|
+
// Result: data.config.ai.models
|
|
396
|
+
|
|
397
|
+
// Deep nesting
|
|
398
|
+
{
|
|
399
|
+
"Name": "CustomerData",
|
|
400
|
+
"DestinationPath": "analysis.customer.profile.orders"
|
|
401
|
+
}
|
|
402
|
+
// Result: payload.analysis.customer.profile.orders
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
#### Caching Policies
|
|
406
|
+
|
|
407
|
+
Data sources support three caching strategies:
|
|
408
|
+
|
|
409
|
+
**1. None** - No caching (default)
|
|
410
|
+
```typescript
|
|
411
|
+
{
|
|
412
|
+
"CachePolicy": "None"
|
|
413
|
+
// Data is loaded fresh every time
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
**2. PerRun** - Cache for duration of a single agent run
|
|
418
|
+
```typescript
|
|
419
|
+
{
|
|
420
|
+
"CachePolicy": "PerRun"
|
|
421
|
+
// Multiple data sources with same AgentID+Name share cached data within one run
|
|
422
|
+
// Cache is cleared when agent run completes
|
|
423
|
+
}
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
**3. PerAgent** - Global cache with TTL
|
|
427
|
+
```typescript
|
|
428
|
+
{
|
|
429
|
+
"CachePolicy": "PerAgent",
|
|
430
|
+
"CacheTimeoutSeconds": 3600 // 1 hour
|
|
431
|
+
// Cached across all runs for this agent until TTL expires
|
|
432
|
+
// Good for rarely-changing reference data like entity lists
|
|
433
|
+
}
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
#### Execution Control
|
|
437
|
+
|
|
438
|
+
**Disable data preloading** for specific executions:
|
|
439
|
+
```typescript
|
|
440
|
+
const result = await runner.RunAgent({
|
|
441
|
+
agent: myAgent,
|
|
442
|
+
conversationMessages: messages,
|
|
443
|
+
contextUser: user,
|
|
444
|
+
disableDataPreloading: true // Skip automatic data preloading
|
|
445
|
+
});
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
**Caller precedence**: Caller-provided data always takes precedence over preloaded data:
|
|
449
|
+
```typescript
|
|
450
|
+
const result = await runner.RunAgent({
|
|
451
|
+
agent: myAgent,
|
|
452
|
+
conversationMessages: messages,
|
|
453
|
+
contextUser: user,
|
|
454
|
+
data: {
|
|
455
|
+
CUSTOM_ENTITIES: myEntities // Overrides preloaded CUSTOM_ENTITIES
|
|
456
|
+
}
|
|
457
|
+
});
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
#### Configuration Examples
|
|
461
|
+
|
|
462
|
+
**Database Research Agent** - Preload entity metadata
|
|
463
|
+
```typescript
|
|
464
|
+
// Data source 1: All entities for reference
|
|
465
|
+
{
|
|
466
|
+
"AgentID": "database-research-agent-id",
|
|
467
|
+
"Name": "ALL_ENTITIES",
|
|
468
|
+
"SourceType": "RunView",
|
|
469
|
+
"EntityName": "Entities",
|
|
470
|
+
"OrderBy": "Name ASC",
|
|
471
|
+
"FieldsToRetrieve": JSON.stringify(["ID", "Name", "SchemaName", "Description", "BaseView"]),
|
|
472
|
+
"DestinationType": "Data",
|
|
473
|
+
"ExecutionOrder": 1,
|
|
474
|
+
"Status": "Active",
|
|
475
|
+
"CachePolicy": "PerAgent",
|
|
476
|
+
"CacheTimeoutSeconds": 3600
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// Data source 2: Schema information
|
|
480
|
+
{
|
|
481
|
+
"AgentID": "database-research-agent-id",
|
|
482
|
+
"Name": "SCHEMA_INFO",
|
|
483
|
+
"SourceType": "RunView",
|
|
484
|
+
"EntityName": "Entity Fields",
|
|
485
|
+
"DestinationType": "Data",
|
|
486
|
+
"DestinationPath": "schema.fields",
|
|
487
|
+
"ExecutionOrder": 2,
|
|
488
|
+
"Status": "Active",
|
|
489
|
+
"CachePolicy": "PerAgent",
|
|
490
|
+
"CacheTimeoutSeconds": 3600
|
|
491
|
+
}
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
**Customer Service Agent** - Preload customer context
|
|
495
|
+
```typescript
|
|
496
|
+
// Preload customer data into payload
|
|
497
|
+
{
|
|
498
|
+
"AgentID": "customer-service-agent-id",
|
|
499
|
+
"Name": "CUSTOMER_PROFILE",
|
|
500
|
+
"SourceType": "RunView",
|
|
501
|
+
"EntityName": "Customers",
|
|
502
|
+
"ExtraFilter": "ID='{{context.customerId}}'",
|
|
503
|
+
"DestinationType": "Payload",
|
|
504
|
+
"DestinationPath": "customer.profile",
|
|
505
|
+
"Status": "Active",
|
|
506
|
+
"CachePolicy": "PerRun"
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// Preload recent orders
|
|
510
|
+
{
|
|
511
|
+
"AgentID": "customer-service-agent-id",
|
|
512
|
+
"Name": "RECENT_ORDERS",
|
|
513
|
+
"SourceType": "RunQuery",
|
|
514
|
+
"QueryName": "Recent Orders by Customer",
|
|
515
|
+
"Parameters": JSON.stringify({ customerId: "{{context.customerId}}", days: 30 }),
|
|
516
|
+
"DestinationType": "Payload",
|
|
517
|
+
"DestinationPath": "customer.orders",
|
|
518
|
+
"Status": "Active",
|
|
519
|
+
"CachePolicy": "PerRun"
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// Preload organization settings (for actions)
|
|
523
|
+
{
|
|
524
|
+
"AgentID": "customer-service-agent-id",
|
|
525
|
+
"Name": "ORG_CONFIG",
|
|
526
|
+
"SourceType": "RunView",
|
|
527
|
+
"EntityName": "Organization Settings",
|
|
528
|
+
"ExtraFilter": "OrgID='{{context.organizationId}}'",
|
|
529
|
+
"DestinationType": "Context",
|
|
530
|
+
"DestinationPath": "organization.config",
|
|
531
|
+
"Status": "Active",
|
|
532
|
+
"CachePolicy": "PerAgent",
|
|
533
|
+
"CacheTimeoutSeconds": 1800
|
|
534
|
+
}
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
#### Benefits
|
|
538
|
+
|
|
539
|
+
- **Declarative**: Configure data preloading through metadata, not code
|
|
540
|
+
- **Reusable**: Same agent works across different environments
|
|
541
|
+
- **Efficient**: Caching reduces redundant database queries
|
|
542
|
+
- **Clean Separation**: Keeps data in appropriate destinations (data/context/payload)
|
|
543
|
+
- **Flexible**: Supports both RunView and RunQuery with full parameter control
|
|
544
|
+
- **Secure**: Context destination keeps sensitive data away from LLMs
|
|
545
|
+
- **Performance**: Multiple caching strategies for different use cases
|
|
546
|
+
|
|
547
|
+
#### Database Schema
|
|
548
|
+
|
|
549
|
+
The `AIAgentDataSource` table includes:
|
|
550
|
+
- **AgentID**: The agent using this data source
|
|
551
|
+
- **Name**: Variable name (used as fallback if DestinationPath is null)
|
|
552
|
+
- **SourceType**: RunView or RunQuery
|
|
553
|
+
- **EntityName**, **ExtraFilter**, **OrderBy**, **FieldsToRetrieve**, **ResultType**: RunView parameters
|
|
554
|
+
- **QueryName**, **CategoryPath**, **Parameters**: RunQuery parameters
|
|
555
|
+
- **MaxRows**: Limit results (applies to both source types)
|
|
556
|
+
- **DestinationType**: Data, Context, or Payload
|
|
557
|
+
- **DestinationPath**: Nested path using dot notation (optional)
|
|
558
|
+
- **ExecutionOrder**: Order to execute when multiple sources exist
|
|
559
|
+
- **Status**: Active or Disabled
|
|
560
|
+
- **CachePolicy**: None, PerRun, or PerAgent
|
|
561
|
+
- **CacheTimeoutSeconds**: TTL for PerAgent cache
|
|
562
|
+
|
|
563
|
+
**Unique Constraint**: `AgentID + Name + DestinationType + DestinationPath`
|
|
564
|
+
- Allows same Name across different destinations/paths
|
|
565
|
+
- Example: "ENTITIES" can exist in both Data and Payload destinations
|
|
566
|
+
|
|
271
567
|
### Payload Scoping for Sub-Agents
|
|
272
568
|
|
|
273
569
|
The framework now supports narrowing the payload that sub-agents work with through the `PayloadScope` field:
|
|
@@ -987,70 +1283,309 @@ export class DecisionTreeAgent extends BaseAgentType {
|
|
|
987
1283
|
}
|
|
988
1284
|
```
|
|
989
1285
|
|
|
990
|
-
|
|
1286
|
+
## Flow Agent Type - Deterministic Workflows
|
|
1287
|
+
|
|
1288
|
+
Flow agents execute **deterministic, graph-based workflows** where the execution path is determined by boolean conditions evaluated against the payload and step results. Unlike Loop agents that rely on LLM decision-making at each step, Flow agents follow predefined paths through a directed graph.
|
|
1289
|
+
|
|
1290
|
+
### When to Use Flow Agents
|
|
1291
|
+
|
|
1292
|
+
Flow agents are ideal for:
|
|
1293
|
+
- **Predictable workflows** with well-defined decision points
|
|
1294
|
+
- **Approval processes** with conditional routing
|
|
1295
|
+
- **Data pipelines** with validation and transformation steps
|
|
1296
|
+
- **Hybrid workflows** combining deterministic logic with AI prompts
|
|
1297
|
+
- **Multi-step processes** where you need guaranteed execution order
|
|
1298
|
+
|
|
1299
|
+
### Core Concepts
|
|
1300
|
+
|
|
1301
|
+
#### 1. Workflow Steps (AIAgentStep)
|
|
1302
|
+
|
|
1303
|
+
Steps are the nodes in your workflow graph. Each step represents an action to perform:
|
|
1304
|
+
|
|
1305
|
+
```typescript
|
|
1306
|
+
// Three types of steps:
|
|
1307
|
+
{
|
|
1308
|
+
Name: 'ValidateInput',
|
|
1309
|
+
StepType: 'Action', // Execute a MJ Action
|
|
1310
|
+
ActionID: 'validation-action-id',
|
|
1311
|
+
StartingStep: true, // Marks this as an entry point
|
|
1312
|
+
Sequence: 0, // For parallel starting steps
|
|
1313
|
+
Status: 'Active', // Active, Disabled, or Pending
|
|
1314
|
+
TimeoutSeconds: 30 // Optional timeout
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1317
|
+
{
|
|
1318
|
+
Name: 'AnalyzeData',
|
|
1319
|
+
StepType: 'Prompt', // Execute an AI prompt
|
|
1320
|
+
PromptID: 'analysis-prompt-id',
|
|
1321
|
+
Description: 'Analyze data quality and completeness'
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
{
|
|
1325
|
+
Name: 'ProcessWithSubAgent',
|
|
1326
|
+
StepType: 'Sub-Agent', // Invoke another agent
|
|
1327
|
+
SubAgentID: 'processing-agent-id'
|
|
1328
|
+
}
|
|
1329
|
+
```
|
|
1330
|
+
|
|
1331
|
+
#### 2. Workflow Paths (AIAgentStepPath)
|
|
1332
|
+
|
|
1333
|
+
Paths are the edges connecting your workflow nodes. They determine the flow:
|
|
1334
|
+
|
|
1335
|
+
```typescript
|
|
1336
|
+
{
|
|
1337
|
+
OriginStepID: 'step-a-id',
|
|
1338
|
+
DestinationStepID: 'step-b-id',
|
|
1339
|
+
Condition: 'payload.amount > 1000 && payload.approved === true',
|
|
1340
|
+
Priority: 10 // Higher priority paths evaluated first
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
// Path without condition (always valid)
|
|
1344
|
+
{
|
|
1345
|
+
OriginStepID: 'step-a-id',
|
|
1346
|
+
DestinationStepID: 'default-step-id',
|
|
1347
|
+
Condition: null, // No condition = always valid
|
|
1348
|
+
Priority: 0 // Lower priority = fallback
|
|
1349
|
+
}
|
|
1350
|
+
```
|
|
1351
|
+
|
|
1352
|
+
#### 3. Action Input/Output Mapping
|
|
1353
|
+
|
|
1354
|
+
**Action Input Mapping** (`ActionInputMapping`) - Maps payload values to action parameters:
|
|
1355
|
+
|
|
1356
|
+
```typescript
|
|
1357
|
+
// In AIAgentStep.ActionInputMapping
|
|
1358
|
+
{
|
|
1359
|
+
"customerId": "payload.customer.id", // Map from payload
|
|
1360
|
+
"orderDate": "static:2024-01-01", // Static value
|
|
1361
|
+
"includeDetails": true, // Boolean literal
|
|
1362
|
+
"maxResults": 100, // Numeric literal
|
|
1363
|
+
"filters": { // Nested object
|
|
1364
|
+
"status": "payload.filters.orderStatus",
|
|
1365
|
+
"region": "static:US-WEST"
|
|
1366
|
+
},
|
|
1367
|
+
"itemIds": "payload.order.items" // Can map arrays
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
// Supports nested resolution
|
|
1371
|
+
{
|
|
1372
|
+
"searchParams": {
|
|
1373
|
+
"query": "payload.searchTerm",
|
|
1374
|
+
"filters": {
|
|
1375
|
+
"category": "payload.category",
|
|
1376
|
+
"tags": "payload.selectedTags"
|
|
1377
|
+
},
|
|
1378
|
+
"options": {
|
|
1379
|
+
"maxResults": 50,
|
|
1380
|
+
"includeMetadata": true
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
```
|
|
1385
|
+
|
|
1386
|
+
**Action Output Mapping** (`ActionOutputMapping`) - Maps action results back to payload:
|
|
1387
|
+
|
|
1388
|
+
```typescript
|
|
1389
|
+
// In AIAgentStep.ActionOutputMapping
|
|
1390
|
+
{
|
|
1391
|
+
"userId": "payload.customer.id", // Map specific output param
|
|
1392
|
+
"orderTotal": "payload.order.total", // Nested path in payload
|
|
1393
|
+
"metadata": "payload.action.lastResult", // Arbitrary nesting
|
|
1394
|
+
"*": "payload.rawResults.fullData" // Wildcard = entire result
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
// Case-insensitive output parameter matching
|
|
1398
|
+
// If action returns { UserId: "123" }, it matches "userId" in mapping
|
|
1399
|
+
```
|
|
1400
|
+
|
|
1401
|
+
#### 4. Prompt Result Merging
|
|
1402
|
+
|
|
1403
|
+
When a Prompt step executes, its JSON response is **deep merged** into the payload:
|
|
1404
|
+
|
|
1405
|
+
```typescript
|
|
1406
|
+
// Before prompt execution
|
|
1407
|
+
payload = {
|
|
1408
|
+
decision: {
|
|
1409
|
+
status: "pending",
|
|
1410
|
+
reviewerId: "user-123"
|
|
1411
|
+
},
|
|
1412
|
+
metadata: { startTime: "..." }
|
|
1413
|
+
};
|
|
1414
|
+
|
|
1415
|
+
// Prompt returns
|
|
1416
|
+
promptResponse = {
|
|
1417
|
+
decision: {
|
|
1418
|
+
approved: true,
|
|
1419
|
+
confidence: 0.95
|
|
1420
|
+
}
|
|
1421
|
+
};
|
|
1422
|
+
|
|
1423
|
+
// After deep merge (preserves existing keys!)
|
|
1424
|
+
payload = {
|
|
1425
|
+
decision: {
|
|
1426
|
+
approved: true, // NEW from prompt
|
|
1427
|
+
confidence: 0.95, // NEW from prompt
|
|
1428
|
+
status: "pending", // PRESERVED from before
|
|
1429
|
+
reviewerId: "user-123" // PRESERVED from before
|
|
1430
|
+
},
|
|
1431
|
+
metadata: { startTime: "..." } // PRESERVED
|
|
1432
|
+
};
|
|
1433
|
+
```
|
|
1434
|
+
|
|
1435
|
+
**Why Deep Merge?**
|
|
1436
|
+
- **Preserves context** - Existing payload data isn't lost
|
|
1437
|
+
- **Incremental updates** - Prompts can add fields without destroying structure
|
|
1438
|
+
- **Composable decisions** - Multiple prompts can build up complex objects
|
|
991
1439
|
|
|
992
|
-
|
|
1440
|
+
**Special Prompt Response Handling**:
|
|
1441
|
+
```typescript
|
|
1442
|
+
// If prompt response contains Chat step request
|
|
1443
|
+
{
|
|
1444
|
+
"nextStep": { "type": "Chat" },
|
|
1445
|
+
"message": "I need more information from the user",
|
|
1446
|
+
"taskComplete": false
|
|
1447
|
+
}
|
|
1448
|
+
// OR
|
|
1449
|
+
{
|
|
1450
|
+
"taskComplete": true,
|
|
1451
|
+
"message": "Here's the final result..."
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
// Flow agent returns Chat step to bubble message to user
|
|
1455
|
+
// This allows prompts within flows to communicate with users
|
|
1456
|
+
```
|
|
1457
|
+
|
|
1458
|
+
### Complete Flow Agent Example
|
|
993
1459
|
|
|
994
1460
|
```typescript
|
|
995
|
-
// Database configuration for a
|
|
996
|
-
//
|
|
997
|
-
const
|
|
1461
|
+
// Database configuration for a complete approval workflow
|
|
1462
|
+
// 1. Define the workflow steps
|
|
1463
|
+
const steps = [
|
|
998
1464
|
{
|
|
999
|
-
Name: '
|
|
1465
|
+
Name: 'ValidateRequest',
|
|
1000
1466
|
StepType: 'Action',
|
|
1001
|
-
ActionID:
|
|
1467
|
+
ActionID: validateActionId,
|
|
1002
1468
|
StartingStep: true,
|
|
1003
|
-
Sequence: 0
|
|
1469
|
+
Sequence: 0,
|
|
1470
|
+
ActionInputMapping: JSON.stringify({
|
|
1471
|
+
"requestData": "payload.request",
|
|
1472
|
+
"validationRules": "payload.rules"
|
|
1473
|
+
}),
|
|
1474
|
+
ActionOutputMapping: JSON.stringify({
|
|
1475
|
+
"isValid": "payload.validation.isValid",
|
|
1476
|
+
"errors": "payload.validation.errors"
|
|
1477
|
+
})
|
|
1478
|
+
},
|
|
1479
|
+
{
|
|
1480
|
+
Name: 'CheckAmount',
|
|
1481
|
+
StepType: 'Prompt',
|
|
1482
|
+
PromptID: amountCheckPromptId,
|
|
1483
|
+
Description: 'AI analyzes amount and risk factors'
|
|
1484
|
+
// Prompt returns: { risk: "low"|"medium"|"high", reasoning: "..." }
|
|
1485
|
+
// Deep merged into payload.risk and payload.reasoning
|
|
1004
1486
|
},
|
|
1005
1487
|
{
|
|
1006
1488
|
Name: 'AutoApprove',
|
|
1007
1489
|
StepType: 'Action',
|
|
1008
1490
|
ActionID: approveActionId,
|
|
1491
|
+
ActionInputMapping: JSON.stringify({
|
|
1492
|
+
"requestId": "payload.request.id",
|
|
1493
|
+
"approvedBy": "static:SYSTEM_AUTO"
|
|
1494
|
+
}),
|
|
1009
1495
|
ActionOutputMapping: JSON.stringify({
|
|
1010
|
-
|
|
1011
|
-
|
|
1496
|
+
"approvalId": "payload.approval.id",
|
|
1497
|
+
"timestamp": "payload.approval.timestamp"
|
|
1012
1498
|
})
|
|
1013
1499
|
},
|
|
1014
1500
|
{
|
|
1015
1501
|
Name: 'ManagerReview',
|
|
1016
|
-
StepType: '
|
|
1017
|
-
|
|
1018
|
-
|
|
1502
|
+
StepType: 'Sub-Agent',
|
|
1503
|
+
SubAgentID: managerReviewAgentId
|
|
1504
|
+
// Sub-agent payload inherits and can modify parent payload
|
|
1019
1505
|
},
|
|
1020
1506
|
{
|
|
1021
|
-
Name: '
|
|
1507
|
+
Name: 'NotifyUser',
|
|
1022
1508
|
StepType: 'Action',
|
|
1023
|
-
ActionID:
|
|
1509
|
+
ActionID: notificationActionId,
|
|
1510
|
+
ActionInputMapping: JSON.stringify({
|
|
1511
|
+
"userId": "payload.request.userId",
|
|
1512
|
+
"message": "payload.approval.notificationMessage",
|
|
1513
|
+
"channel": "static:email"
|
|
1514
|
+
})
|
|
1024
1515
|
}
|
|
1025
1516
|
];
|
|
1026
1517
|
|
|
1027
|
-
//
|
|
1028
|
-
const
|
|
1518
|
+
// 2. Define the workflow paths
|
|
1519
|
+
const paths = [
|
|
1520
|
+
// From validation
|
|
1029
1521
|
{
|
|
1030
|
-
OriginStepID:
|
|
1031
|
-
DestinationStepID:
|
|
1032
|
-
Condition: 'payload.
|
|
1522
|
+
OriginStepID: validateStepId,
|
|
1523
|
+
DestinationStepID: checkAmountStepId,
|
|
1524
|
+
Condition: 'payload.validation.isValid === true',
|
|
1033
1525
|
Priority: 10
|
|
1034
1526
|
},
|
|
1035
1527
|
{
|
|
1036
|
-
OriginStepID:
|
|
1037
|
-
DestinationStepID:
|
|
1038
|
-
Condition: 'payload.
|
|
1528
|
+
OriginStepID: validateStepId,
|
|
1529
|
+
DestinationStepID: notifyUserStepId,
|
|
1530
|
+
Condition: 'payload.validation.isValid === false',
|
|
1531
|
+
Priority: 10
|
|
1532
|
+
},
|
|
1533
|
+
|
|
1534
|
+
// From AI risk assessment
|
|
1535
|
+
{
|
|
1536
|
+
OriginStepID: checkAmountStepId,
|
|
1537
|
+
DestinationStepID: autoApproveStepId,
|
|
1538
|
+
Condition: 'payload.risk === "low" && payload.request.amount <= 1000',
|
|
1039
1539
|
Priority: 10
|
|
1040
1540
|
},
|
|
1041
1541
|
{
|
|
1042
|
-
OriginStepID:
|
|
1043
|
-
DestinationStepID:
|
|
1044
|
-
Condition: '
|
|
1542
|
+
OriginStepID: checkAmountStepId,
|
|
1543
|
+
DestinationStepID: managerReviewStepId,
|
|
1544
|
+
Condition: 'payload.risk === "medium" || payload.risk === "high"',
|
|
1045
1545
|
Priority: 10
|
|
1046
1546
|
},
|
|
1547
|
+
|
|
1548
|
+
// From manager review
|
|
1047
1549
|
{
|
|
1048
|
-
OriginStepID:
|
|
1049
|
-
DestinationStepID:
|
|
1050
|
-
Condition: '
|
|
1550
|
+
OriginStepID: managerReviewStepId,
|
|
1551
|
+
DestinationStepID: autoApproveStepId,
|
|
1552
|
+
Condition: 'payload.managerDecision.approved === true',
|
|
1051
1553
|
Priority: 10
|
|
1554
|
+
},
|
|
1555
|
+
{
|
|
1556
|
+
OriginStepID: managerReviewStepId,
|
|
1557
|
+
DestinationStepID: notifyUserStepId,
|
|
1558
|
+
Condition: 'payload.managerDecision.approved === false',
|
|
1559
|
+
Priority: 5
|
|
1560
|
+
},
|
|
1561
|
+
|
|
1562
|
+
// Final notification after approval
|
|
1563
|
+
{
|
|
1564
|
+
OriginStepID: autoApproveStepId,
|
|
1565
|
+
DestinationStepID: notifyUserStepId,
|
|
1566
|
+
Condition: null, // Always execute
|
|
1567
|
+
Priority: 0
|
|
1052
1568
|
}
|
|
1053
1569
|
];
|
|
1570
|
+
|
|
1571
|
+
// 3. Execute the flow agent
|
|
1572
|
+
const result = await runner.RunAgent({
|
|
1573
|
+
agent: flowAgentEntity,
|
|
1574
|
+
conversationMessages: messages,
|
|
1575
|
+
contextUser: user,
|
|
1576
|
+
payload: {
|
|
1577
|
+
request: {
|
|
1578
|
+
id: "req-123",
|
|
1579
|
+
userId: "user-456",
|
|
1580
|
+
amount: 5000,
|
|
1581
|
+
description: "Equipment purchase"
|
|
1582
|
+
},
|
|
1583
|
+
rules: {
|
|
1584
|
+
maxAutoApprove: 1000,
|
|
1585
|
+
requiresManagerReview: true
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
});
|
|
1054
1589
|
```
|
|
1055
1590
|
|
|
1056
1591
|
### Flow Agent Features
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { UserInfo } from '@memberjunction/core';
|
|
2
|
+
export interface PreloadedDataResult {
|
|
3
|
+
data: Record<string, unknown>;
|
|
4
|
+
context: Record<string, unknown>;
|
|
5
|
+
payload: Record<string, unknown>;
|
|
6
|
+
}
|
|
7
|
+
export declare class AgentDataPreloader {
|
|
8
|
+
private static _instance;
|
|
9
|
+
private _perAgentCache;
|
|
10
|
+
private _perRunCache;
|
|
11
|
+
private constructor();
|
|
12
|
+
static get Instance(): AgentDataPreloader;
|
|
13
|
+
PreloadAgentData(agentId: string, contextUser: UserInfo, runId?: string): Promise<PreloadedDataResult>;
|
|
14
|
+
clearRunCache(runId: string): void;
|
|
15
|
+
clearAgentCache(): void;
|
|
16
|
+
private loadDataSourcesForAgent;
|
|
17
|
+
private executeDataSource;
|
|
18
|
+
private executeRunView;
|
|
19
|
+
private executeRunQuery;
|
|
20
|
+
private getCachedData;
|
|
21
|
+
private cacheData;
|
|
22
|
+
private getPerAgentCacheKey;
|
|
23
|
+
}
|
|
24
|
+
export declare function LoadAgentDataPreloader(): AgentDataPreloader;
|
|
25
|
+
//# sourceMappingURL=AgentDataPreloader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentDataPreloader.d.ts","sourceRoot":"","sources":["../src/AgentDataPreloader.ts"],"names":[],"mappings":"AAcA,OAAO,EAAqE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAQnH,MAAM,WAAW,mBAAmB;IAChC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AA4BD,qBAAa,kBAAkB;IAC3B,OAAO,CAAC,MAAM,CAAC,SAAS,CAAmC;IAK3D,OAAO,CAAC,cAAc,CAAsC;IAK5D,OAAO,CAAC,YAAY,CAAgD;IAKpE,OAAO;IAOP,WAAkB,QAAQ,IAAI,kBAAkB,CAK/C;IA4BY,gBAAgB,CACzB,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,QAAQ,EACrB,KAAK,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,mBAAmB,CAAC;IA8ExB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAalC,eAAe,IAAI,IAAI;YAchB,uBAAuB;YAuBvB,iBAAiB;YAsCjB,cAAc;YAwCd,eAAe;IAuC7B,OAAO,CAAC,aAAa;IA2CrB,OAAO,CAAC,SAAS;IAwCjB,OAAO,CAAC,mBAAmB;CAG9B;AAKD,wBAAgB,sBAAsB,uBAGrC"}
|