Package Exports
- @memberjunction/ai-agents
- @memberjunction/ai-agents/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@memberjunction/ai-agents) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
@memberjunction/ai-agents
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.
Overview
The @memberjunction/ai-agents package enables developers to create sophisticated AI agents that can:
- Execute AI prompts in a hierarchical structure (system + agent prompts)
- Perform actions based on prompt results using the MJ Actions framework
- Make decisions about next steps through configurable agent types
- Orchestrate sub-agents for complex, multi-step tasks
- Track all execution steps in database for analysis and debugging
- Manage conversation context with automatic compression
Key Components
BaseAgent
The core execution engine that all agents use. Provides functionality for:
- Hierarchical prompt execution (system prompt as parent, agent prompts as children)
- Managing conversation context and placeholders
- Invoking MemberJunction actions
- Running sub-agents recursively
- Comprehensive execution tracking via AIAgentRun and AIAgentRunStep entities
- Automatic context compression for long conversations
BaseAgentType
Abstract class that defines reusable agent behavior patterns:
- Determines next steps based on prompt results
- Encapsulates decision-making logic
- Enables different execution patterns (loops, decision trees, etc.)
LoopAgentType
Concrete implementation of BaseAgentType that:
- Executes in a loop until task completion
- Parses structured JSON responses from prompts
- Supports actions, sub-agents, and conditional termination
AgentRunner
Simple orchestrator that:
- Loads agent metadata from database
- Instantiates correct agent class using ClassFactory
- Executes agents with provided context
PayloadManager
Advanced payload access control for hierarchical agent execution:
- Controls which payload paths sub-agents can read (downstream)
- Controls which payload paths sub-agents can write (upstream)
- Supports JSON path patterns with wildcards
- Detects suspicious changes with configurable rules
- Generates human-readable diffs for audit trails
Installation
npm install @memberjunction/ai-agentsBasic Usage
import { AgentRunner } from '@memberjunction/ai-agents';
import { UserInfo } from '@memberjunction/core';
// 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)
const runner = new AgentRunner();
const result = await runner.RunAgent({
agent: agentEntity, // AIAgentEntity from database
conversationMessages: messages,
contextUser: user
});
// Direct instantiation when you want to pick the exact class that gets run
const agent = new YourAgentClass();
const result = await agent.Execute({
agent: agentEntity,
conversationMessages: messages,
contextUser: user
});
// Using run chaining to maintain context across multiple runs
const followUpResult = await runner.RunAgent({
agent: agentEntity,
conversationMessages: newMessages,
contextUser: user,
lastRunId: result.agentRun.ID,
autoPopulateLastRunPayload: true // Automatically use previous run's final payload
});Agent Configuration
Agents are configured through MemberJunction entities:
AIAgentType: Defines the behavior pattern and system prompt
DriverClass: The TypeScript class implementing the behaviorSystemPromptID: Base prompt providing foundational behavior
AIAgent: Specific agent instance
AgentTypeID: Links to the agent type- Configuration for specific use cases
AIPrompt: Reusable prompt templates
- Support for placeholders and dynamic content
- Can be chained hierarchically
AIAgentPrompt: Associates prompts with agents
ExecutionOrder: Determines prompt execution sequence- Links agents to their specific prompts
Creating Custom Agent Types
import { BaseAgentType, RegisterClass, BaseAgentNextStep } from '@memberjunction/ai-agents';
import { AIPromptRunResult } from '@memberjunction/ai-prompts';
@RegisterClass(BaseAgentType, "MyCustomAgentType")
export class MyCustomAgentType extends BaseAgentType {
async DetermineNextStep(promptResult: AIPromptRunResult): Promise<BaseAgentNextStep> {
// Parse the prompt result
const response = JSON.parse(promptResult.FullResult);
// Determine next action based on response
if (response.taskComplete) {
return { type: 'stop', reason: 'Task completed successfully' };
} else if (response.action) {
return {
type: 'action',
actionName: response.action.name,
actionParams: response.action.params
};
} else {
return { type: 'continue' };
}
}
}Execution Flow
Initialization:
- Creates AIAgentRun entity for tracking
- Loads agent configuration and type
- Initializes AI and Action engines
Configuration Loading:
- Loads AIAgentType with system prompt
- Loads agent's prompts ordered by ExecutionOrder
- Validates placeholders and dependencies
Execution Loop:
- Executes prompts hierarchically (system as parent)
- Agent type analyzes results via DetermineNextStep()
- Executes actions or sub-agents as determined
- Creates AIAgentRunStep for each operation
- Continues until stop condition met
Result Tracking:
- All steps recorded with full context
- Execution tree available for analysis
- Errors and outputs captured
Advanced Features
Run Chaining
The framework supports linking multiple agent runs together to maintain context across interactions:
// Execute an agent with run chaining
const result = await agent.Execute({
agent: agentEntity,
conversationMessages: messages,
contextUser: user,
lastRunId: previousRunId, // Links to previous run
autoPopulateLastRunPayload: true // Auto-loads previous payload
});
// The framework will:
// 1. Load the FinalPayload from the previous run
// 2. Set it as StartingPayload for the new run
// 3. Use it as the initial payload if none provided
// 4. Validate against circular references in the chainKey features:
- LastRunID: Links runs in a chain (different from ParentRunID for sub-agents)
- StartingPayload: Captures the initial state of each run
- Auto-population: Reduces bandwidth by avoiding payload round-trips
- Circular reference detection: Prevents infinite loops in run chains
Payload Management and Change Detection
The framework includes sophisticated payload management with automatic change detection:
// Payload changes are automatically analyzed
const changeResult = payloadManager.applyAgentChangeRequest(
originalPayload,
changeRequest,
{
analyzeChanges: true, // Detect suspicious changes
generateDiff: true, // Create audit trail
agentName: 'MyAgent'
}
);
// Suspicious changes are flagged:
// - Content truncation (>70% reduction)
// - Non-empty key removal
// - Type changes (object→primitive)
// - Pattern anomalies (placeholder replacement)Sub-agent Payload Access Control:
// In AIAgent entity configuration:
{
PayloadDownstreamPaths: ["customer.id", "order.*"], // What sub-agent can read
PayloadUpstreamPaths: ["analysis.*", "recommendations"] // What sub-agent can write
}Hierarchical Prompt Execution
// System prompt provides base behavior
// Agent prompts execute as children with shared context
const result = await agent.ExecutePrompt({
systemPrompt: agentType.SystemPrompt,
agentPrompt: currentPrompt,
messages: conversationContext
});Context Management
Agents automatically manage conversation context:
- Maintains message history across steps
- Compresses context when approaching token limits
- Handles placeholder replacement in prompts
- Preserves important context during compression
Action Integration
// In agent type's DetermineNextStep
return {
type: 'action',
actionName: 'SendEmail',
actionParams: {
to: 'user@example.com',
subject: 'Analysis Complete',
body: analysisResult
}
};Sub-agent Orchestration
// Agents can invoke other agents recursively
return {
type: 'sub_agent',
agentName: 'DataValidationAgent',
messages: [
{ role: 'user', content: `Validate this data: ${JSON.stringify(data)}` }
]
};Database Schema
Key entities used by the agent framework:
- AIAgentType: Agent behavior patterns and system prompts
- AIAgent: Configured agent instances
PayloadDownstreamPaths: JSON array of paths sub-agents can readPayloadUpstreamPaths: JSON array of paths sub-agents can write
- AIPrompt: Reusable prompt templates with placeholders
- AIAgentPrompt: Links agents to prompts with execution order
- AIAgentRun: Tracks complete agent executions
LastRunID: Links to previous run in a chain (for run chaining)StartingPayload: Initial payload for the run
- AIAgentRunStep: Records individual steps within runs
PayloadAtStart: JSON snapshot of payload before stepPayloadAtEnd: JSON snapshot of payload after stepOutputData: IncludespayloadChangeResultwith analysis
- AIAgentRunStepAction: Details of actions executed
- AIAgentRunStepPrompt: Prompt execution details
Best Practices
- Hierarchical Design: Use system prompts for base behavior, agent prompts for specifics
- Structured Responses: Design prompts to return parseable JSON for agent types
- Modular Prompts: Break complex tasks into ordered, focused prompts
- Proper Type Registration: Register custom agent types with ClassFactory
- Comprehensive Tracking: Leverage built-in tracking for debugging and analysis
- Context Efficiency: Let the framework handle context compression automatically
- Error Handling: Implement robust error handling in custom agent types
- Payload Security: Use path-based access control for sub-agents
- Change Monitoring: Review payload change warnings in OutputData
Examples
Basic Loop Agent
// Agent type configured with LoopAgentType driver
// System prompt defines JSON response format
// Agent prompts execute tasks iteratively
const result = await runner.RunAgent({
agent: loopAgent,
conversationMessages: [
{ role: 'user', content: 'Analyze these sales figures and create a report' }
],
contextUser: user
});Custom Decision Tree Agent
@RegisterClass(BaseAgentType, "DecisionTreeAgent")
export class DecisionTreeAgent extends BaseAgentType {
async DetermineNextStep(result: AIPromptRunResult): Promise<BaseAgentNextStep> {
const decision = JSON.parse(result.FullResult);
switch(decision.branch) {
case 'needs_data':
return { type: 'action', actionName: 'FetchData', actionParams: decision.params };
case 'analyze':
return { type: 'sub_agent', agentName: 'AnalysisAgent', messages: decision.context };
case 'complete':
return { type: 'stop', reason: decision.summary };
default:
return { type: 'continue' };
}
}
}Architecture Documentation
For detailed architecture information, see agent-architecture.md.
Contributing
Contributions are welcome! Please see the main MemberJunction contributing guide.
License
This package is part of the MemberJunction project. See the LICENSE file for details.