@memberjunction/ai-agent-manager-actions
Version:
Agent Management actions for creating and managing AI agents in MemberJunction
181 lines (157 loc) • 7.6 kB
text/typescript
import { ActionResultSimple, RunActionParams } from "@memberjunction/actions-base";
import { RegisterClass } from "@memberjunction/global";
import { AIAgentEntity, AIPromptEntityExtended, AIAgentPromptEntity } from "@memberjunction/core-entities";
import { BaseAgentManagementAction } from "./base-agent-management.action";
import { AIEngineBase } from "@memberjunction/ai-engine-base";
import { BaseAction } from "@memberjunction/actions";
/**
* Creates a new AI agent with specified configuration.
* This action is restricted to the Agent Manager agent only.
* Supports creating both top-level agents and sub-agents.
* Optionally creates and associates a system prompt if PromptText is provided.
*
* @example
* ```typescript
* const result = await runAction({
* ActionName: 'Create Agent',
* Params: [
* { Name: 'Name', Value: 'Customer Feedback Analyzer' },
* { Name: 'Description', Value: 'Analyzes customer feedback...' },
* { Name: 'Type', Value: 'Loop' }, // Optional, use Type OR TypeID
* { Name: 'TypeID', Value: 'loop-agent-type-id' }, // Optional, use Type OR TypeID
* { Name: 'PromptText', Value: 'You are a feedback analyzer...' }, // Optional, creates prompt
* { Name: 'ParentID', Value: 'parent-agent-id' } // Optional, for sub-agents
* ]
* });
* // Returns AgentID and optionally PromptID in output params
* ```
*/
export class CreateAgentAction extends BaseAgentManagementAction {
protected async InternalRunAction(params: RunActionParams): Promise<ActionResultSimple> {
try {
// Validate permission
const permissionError = await this.validateAgentManagerPermission(params);
if (permissionError) return permissionError;
// Extract parameters
const nameResult = this.getStringParam(params, 'Name');
if (nameResult.error) return nameResult.error;
const descriptionResult = this.getStringParam(params, 'Description');
if (descriptionResult.error) return descriptionResult.error;
// Handle Type/TypeID - one is required
const typeResult = this.getStringParam(params, 'Type', false);
const typeIDResult = this.getStringParam(params, 'TypeID', false);
if (!typeResult.value && !typeIDResult.value) {
return {
Success: false,
ResultCode: 'MISSING_PARAMETER',
Message: 'Either Type or TypeID parameter is required'
};
}
// Resolve TypeID if Type was provided
let resolvedTypeID: string;
if (typeIDResult.value) {
resolvedTypeID = typeIDResult.value;
} else {
// Look up TypeID from Type name
const aiEngine = AIEngineBase.Instance;
const agentType = aiEngine.AgentTypes.find((t: any) =>
t.Name.toLowerCase() === typeResult.value!.toLowerCase()
);
if (!agentType) {
return {
Success: false,
ResultCode: 'INVALID_TYPE',
Message: `Agent type '${typeResult.value}' not found. Available types: ${aiEngine.AgentTypes.map((t: any) => t.Name).join(', ')}`
};
}
resolvedTypeID = agentType.ID;
}
const promptTextResult = this.getStringParam(params, 'PromptText', false);
if (promptTextResult.error) return promptTextResult.error;
const parentIDResult = this.getStringParam(params, 'ParentID', false);
if (parentIDResult.error) return parentIDResult.error;
// Validate agent type exists
const typeValidation = await this.validateAgentType(resolvedTypeID, params.ContextUser);
if (typeValidation.error) return typeValidation.error;
// Validate parent agent exists if provided
if (parentIDResult.value) {
const parentValidation = await this.loadAgent(parentIDResult.value, params.ContextUser);
if (parentValidation.error) return parentValidation.error;
}
// Create new agent
const md = this.getMetadata();
const agent = await md.GetEntityObject<AIAgentEntity>('AI Agents', params.ContextUser);
if (!agent) {
return {
Success: false,
ResultCode: 'FAILED',
Message: 'Failed to create AI Agent entity object'
};
}
// Set agent properties
agent.NewRecord();
agent.Name = nameResult.value!;
agent.Description = descriptionResult.value!;
agent.TypeID = resolvedTypeID;
agent.Status = 'Active';
agent.ExecutionOrder = 0;
agent.ExposeAsAction = false; // Default to not exposed
if (parentIDResult.value) {
agent.ParentID = parentIDResult.value;
}
// Save the agent
const saveResult = await agent.Save();
if (saveResult) {
// Add output parameter with the new agent ID
params.Params.push({
Name: 'AgentID',
Value: agent.ID,
Type: 'Output'
});
// If prompt text was provided, create and associate the prompt
if (promptTextResult.value) {
const promptResult = await this.createAndAssociatePrompt(
agent,
promptTextResult.value,
params.ContextUser
);
if (!promptResult.success) {
// Agent was created but prompt failed - return partial success
return {
Success: true,
ResultCode: 'PARTIAL_SUCCESS',
Message: `Agent '${agent.Name}' created successfully, but prompt creation failed: ${promptResult.error}`,
Params: params.Params
};
}
// Add prompt ID to output
params.Params.push({
Name: 'PromptID',
Value: promptResult.promptId,
Type: 'Output'
});
}
return {
Success: true,
ResultCode: 'SUCCESS',
Message: `Successfully created agent '${agent.Name}' with ID ${agent.ID}`,
Params: params.Params
};
} else {
const latestResult = agent.LatestResult;
return {
Success: false,
ResultCode: 'SAVE_FAILED',
Message: latestResult?.Message || 'Failed to save agent'
};
}
} catch (e) {
return this.handleError(e, 'create agent');
}
}
}
export function LoadCreateAgentAction() {
// This function exists to prevent tree shaking from removing the action class
// The side effect of loading this file is that the @RegisterClass decorator runs
}