import { AFS, type AFSExecOptions, type AFSExecResult, type AFSListOptions, type AFSListResult, type AFSModule, type AFSOptions, type AFSReadResult, type AFSSearchOptions } from "@aigne/afs"; import { nodejs } from "@aigne/platform-helpers/nodejs/index.js"; import type * as prompts from "@inquirer/prompts"; import { type ZodObject, type ZodType, z } from "zod"; import type { AgentEvent, Context, UserContext } from "../aigne/context.js"; import type { MessagePayload } from "../aigne/message-queue.js"; import type { ContextUsage } from "../aigne/usage.js"; import type { Memory, MemoryAgent } from "../memory/memory.js"; import type { MemoryRecorderInput } from "../memory/recorder.js"; import type { MemoryRetrieverInput } from "../memory/retriever.js"; import { type Nullish, type PromiseOrValue, type XOr } from "../utils/type-utils.js"; import type { ChatModel, ChatModelInputMessage } from "./chat-model.js"; import type { GuideRailAgent, GuideRailAgentOutput } from "./guide-rail-agent.js"; import type { ImageModel } from "./image-model.js"; import { type GetterSchema, type TransferAgentOutput } from "./types.js"; export * from "./types.js"; export declare const DEFAULT_INPUT_ACTION_GET = "$get"; /** * Basic message type that can contain any key-value pairs */ export interface Message extends Record { $meta?: { usage?: ContextUsage; [key: string]: unknown; }; } /** * Topics the agent subscribes to, can be a single topic string or an array of topic strings */ export type SubscribeTopic = string | string[]; /** * Topics the agent publishes to, can be: * - A single topic string * - An array of topic strings * - A function that receives the output and returns topic(s) * * @template O The agent output message type */ export type PublishTopic = string | string[] | ((output: O) => PromiseOrValue>); export type TaskRenderMode = "hide" | "collapse"; /** * Configuration options for an agent * * @template I The agent input message type * @template O The agent output message type */ export interface AgentOptions extends Partial> { /** * Topics the agent should subscribe to * * These topics determine which messages the agent will receive * from the system */ subscribeTopic?: SubscribeTopic; /** * Topics the agent should publish to * * These topics determine where the agent's output messages * will be sent in the system */ publishTopic?: PublishTopic; /** * Name of the agent * * Used for identification and logging. Defaults to the constructor name * if not specified */ name?: string; /** * Alias for the agent, can be used to refer to the agent by multiple names, especially in AIGNE CLI */ alias?: string[]; /** * Description of the agent * * A human-readable description of what the agent does, useful * for documentation and debugging */ description?: string; model?: ChatModel; imageModel?: ImageModel; taskTitle?: string | ((input: I) => PromiseOrValue); taskRenderMode?: TaskRenderMode; /** * Zod schema defining the input message structure * * Used to validate that input messages conform to the expected format */ inputSchema?: AgentInputOutputSchema; /** * Default input message for the agent, it can be used to provide partial input * or default values for the agent's input schema. */ defaultInput?: Agent["defaultInput"]; /** * Zod schema defining the output message structure * * Used to validate that output messages conform to the expected format */ outputSchema?: AgentInputOutputSchema; /** * Whether to include input in the output * * When true, the agent will merge input fields into the output object */ includeInputInOutput?: boolean; /** * List of skills (other agents or functions) this agent has * * These skills can be used by the agent to delegate tasks or * extend its capabilities */ skills?: (Agent | FunctionAgentFn)[]; /** * Whether to disable emitting events for agent actions * * When true, the agent won't emit events like agentStarted, * agentSucceed, or agentFailed */ disableEvents?: boolean; /** * One or more memory agents this agent can use */ memory?: MemoryAgent | MemoryAgent[]; afs?: true | AFSOptions | AFS | ((afs: AFS) => AFS); asyncMemoryRecord?: boolean; /** * Maximum number of memory items to retrieve */ maxRetrieveMemoryCount?: number; hooks?: AgentHooks | AgentHooks[]; retryOnError?: Agent["retryOnError"] | boolean; } export declare const agentOptionsSchema: ZodObject<{ [key in keyof AgentOptions]: ZodType; }>; export interface AgentInvokeOptions { /** * The execution context for the agent * * The context provides the runtime environment for agent execution, including: * - Event emission and subscription management * - Inter-agent communication and message passing * - Resource usage tracking and limits enforcement * - Timeout and status management * - Memory and state management across agent invocations * * Each agent invocation requires a context to coordinate with the broader * agent system and maintain proper isolation and resource control. */ context: Context; model?: ChatModel; imageModel?: ImageModel; /** * Whether to enable streaming response * * When true, the invoke method returns a ReadableStream that emits * chunks of the response as they become available, allowing for * real-time display of results * * When false or undefined, the invoke method waits for full completion * and returns the final JSON result */ streaming?: boolean; /** * Optional hooks for agent invocation */ hooks?: AgentHooks | AgentHooks[]; /** * @inquirer/prompts used for collecting user input during agent execution * * This property only exists in the CLI context by command `aigne run` */ prompts?: typeof prompts; /** * The caller agent that invoked this agent */ caller?: Agent; } /** * Agent is the base class for all agents. * It provides a mechanism for defining input/output schemas and implementing processing logic, * serving as the foundation of the entire agent system. * * By extending the Agent class and implementing the process method, you can create custom agents * with various capabilities: * - Process structured input and output data * - Validate data formats using schemas * - Communicate between agents through contexts * - Support streaming or non-streaming responses * - Maintain memory of past interactions * - Output in multiple formats (JSON/text) * - Forward tasks to other agents * * @template I The input message type the agent accepts * @template O The output message type the agent returns * * @example * Here's an example of how to create a custom agent: * {@includeCode ../../test/agents/agent.test.ts#example-custom-agent} */ export declare abstract class Agent implements AFSModule { /** * Custom object inspection behavior * * When using Node.js's util.inspect function to inspect an agent, * only the agent's name will be shown, making output more concise * * @returns Agent name */ [nodejs.customInspect]: () => string; static load(_options: { filepath: string; parsed: object; }): Promise>; constructor(options?: AgentOptions); afs?: AFS; tag?: string; /** * List of memories this agent can use * * @deprecated use afs instead */ readonly memories: MemoryAgent[]; asyncMemoryRecord?: boolean; /** * Maximum number of memory items to retrieve */ maxRetrieveMemoryCount?: number; /** * Lifecycle hooks for agent processing. * * Hooks enable tracing, logging, monitoring, and custom behavior * without modifying the core agent implementation * * @example * Here's an example of using hooks: * {@includeCode ../../test/agents/agent.test.ts#example-agent-hooks} */ readonly hooks: AgentHooks[]; retryOnError?: { retries?: number; minTimeout?: number; factor?: number; randomize?: boolean; shouldRetry?: (error: Error) => boolean | Promise; }; /** * List of GuideRail agents applied to this agent * * GuideRail agents validate, transform, or control the message flow by: * - Enforcing rules and safety policies * - Validating inputs/outputs against specific criteria * - Implementing business logic validations * - Monitoring and auditing agent behavior * * Each GuideRail agent can examine both input and expected output, * and has the ability to abort the process with an explanation * * @example * Here's an example of using GuideRail agents: * * {@includeCode ../../test/agents/agent.test.ts#example-agent-guide-rails} */ readonly guideRails?: GuideRailAgent[]; /** * Name of the agent, used for identification and logging * * Defaults to the class constructor name if not specified in options */ readonly name: string; /** * Alias for the agent, can be used to refer to the agent by multiple names, especially in AIGNE CLI */ readonly alias?: string[]; /** * Default topic this agent subscribes to * * Each agent has a default topic in the format "$agent_[agent name]" * The agent automatically subscribes to this topic to receive messages * * @returns The default topic string */ get topic(): string; /** * Description of the agent's purpose and capabilities * * Useful for documentation and when agents need to understand * each other's roles in a multi-agent system */ readonly description?: string; model?: ChatModel; imageModel?: ImageModel; taskTitle?: string | ((input: Message) => PromiseOrValue); renderTaskTitle(input: I): Promise; taskRenderMode?: TaskRenderMode; private readonly _inputSchema?; defaultInput?: GetterSchema; private readonly _outputSchema?; /** * Get the input data schema for this agent * * Used to validate that input messages conform to required format * If no input schema is set, returns an empty object schema by default * * @returns The Zod type definition for input data */ get inputSchema(): ZodType; get inputKeys(): string[]; /** * Get the output data schema for this agent * * Used to validate that output messages conform to required format * If no output schema is set, returns an empty object schema by default * * @returns The Zod type definition for output data */ get outputSchema(): ZodType; get outputKeys(): string[]; /** * Whether to include the original input in the output * * When true, the agent will merge input fields into the output object */ readonly includeInputInOutput?: boolean; /** * Topics the agent subscribes to for receiving messages * * Can be a single topic string or an array of topic strings */ readonly subscribeTopic?: SubscribeTopic; /** * Topics the agent publishes to for sending messages * * Can be a string, array of strings, or a function that determines * topics based on the output */ readonly publishTopic?: PublishTopic; /** * Collection of skills (other agents) this agent can use * * Skills can be accessed by name or by array index, allowing * the agent to delegate tasks to specialized sub-agents */ readonly skills: Agent[] & { [key: string]: Agent; }; /** * Whether to disable emitting events for agent actions * * When true, the agent won't emit events like agentStarted, * agentSucceed, or agentFailed */ private disableEvents?; private subscriptions; /** * Attach agent to context: * - Subscribe to topics and invoke process method when messages are received * - Subscribe to memory topics if memory is enabled * * Agents can receive messages and respond through the topic subscription system, * enabling inter-agent communication. * * @param context Context to attach to */ attach(context: Pick): void; protected subscribeToTopics(context: Pick): void; onMessage({ message, context }: MessagePayload): Promise; /** * Add skills (other agents or functions) to this agent * * Skills allow agents to reuse functionality from other agents, * building more complex behaviors. * * @param skills List of skills to add, can be Agent instances or functions */ addSkill(...skills: (Agent | FunctionAgentFn)[]): void; /** * Check if the agent is invokable * * An agent is invokable if it has implemented the process method */ get isInvokable(): boolean; /** * Check context status to ensure it hasn't timed out * * @param options Invocation options containing context * @throws Error if the context has timed out */ private checkContextStatus; private newDefaultContext; retrieveMemories(input: Pick & { search?: Message | string; }, options: Pick): Promise[]>; recordMemories(input: MemoryRecorderInput, options: Pick): Promise; /** * Invoke the agent with regular (non-streaming) response * * Regular mode waits for the agent to complete processing and return the final result, * suitable for scenarios where a complete result is needed at once. * * @param input Input message to the agent * @param options Invocation options, must set streaming to false or leave unset * @returns Final JSON response * * @example * Here's an example of invoking an agent with regular mode: * {@includeCode ../../test/agents/agent.test.ts#example-invoke} */ invoke(input: I & Message, options?: Partial & { streaming?: false; }): Promise; /** * Invoke the agent with streaming response * * Streaming responses allow the agent to return results incrementally, * suitable for scenarios requiring real-time progress updates, such as * chat bot typing effects. * * @param input Input message to the agent * @param options Invocation options, must set streaming to true for this overload * @returns Streaming response object * * @example * Here's an example of invoking an agent with streaming response: * {@includeCode ../../test/agents/agent.test.ts#example-invoke-streaming} */ invoke(input: I & Message, options: Partial & { streaming: true; }): Promise>; /** * General signature for invoking the agent * * Returns either streaming or regular response based on the streaming parameter in options * * @param input Input message to the agent * @param options Invocation options * @returns Agent response (streaming or regular) */ invoke(input: I & Message, options?: Partial): Promise>; private processStreamingAndRetry; private callHooks; private mergeDefaultInput; protected invokeSkill(skill: Agent, input: I & Message, options: AgentInvokeOptions): Promise; protected invokeChildAgent: Context["invoke"]; /** * Process agent output * * Validates output format, applies post-processing operations, and triggers success events * * @param input Original input message * @param output Raw output produced by the agent * @param options Invocation options * @returns Final processed output */ protected processAgentOutput(input: I, output: Exclude, AgentResponseStream>, { messages, ...options }: AgentInvokeOptions & { messages?: ChatModelInputMessage[]; }): Promise; /** * Process errors that occur during agent execution * * Logs error information, triggers failure events, and re-throws the error * * @param error Caught error * @param options Invocation options */ private processAgentError; /** * Check agent invocation usage to prevent exceeding limits * * If the context has a maximum invocation limit set, checks if the limit * has been exceeded and increments the invocation counter * * @param options Invocation options containing context and limits * @throws Error if maximum invocation limit is exceeded */ protected checkAgentInvokesUsage(options: AgentInvokeOptions): void; /** * Pre-processing operations before handling input * * Preparatory work done before executing the agent's main processing logic, including: * - Checking context status * - Verifying invocation limits * * @param _ Input message (unused) * @param options Options for agent invocation */ protected preprocess(_: I, options: AgentInvokeOptions): Promise; private checkResponseByGuideRails; private runGuideRails; /** * Handle errors detected by GuideRail agents * * This method is called when a GuideRail agent aborts the process, providing * a way for agents to customize error handling behavior. By default, it simply * returns the original error, but subclasses can override this method to: * - Transform the error into a more specific response * - Apply recovery strategies * - Log or report the error in a custom format * - Return a fallback output instead of an error * * @param error The GuideRail agent output containing abort=true and a reason * @returns Either the original/modified error or a substitute output object * which will be tagged with $status: "GuideRailError" */ protected onGuideRailError(error: GuideRailAgentOutput): Promise; /** * Post-processing operations after handling output * * Operations performed after the agent produces output, including: * - Checking context status * - Adding interaction records to memory * * @param input Input message * @param output Output message * @param options Options for agent invocation */ protected postprocess(input: I, output: O, options: AgentInvokeOptions): Promise; protected publishToTopics(output: Message, options: AgentInvokeOptions): Promise; formatOutput(output: O): PromiseOrValue; /** * Core processing method of the agent, must be implemented in subclasses * * This is the main functionality implementation of the agent, processing input and * generating output. Can return various types of results: * - Regular object response * - Streaming response * - Async generator * - Another agent instance (transfer agent) * * @param input Input message * @param options Options for agent invocation * @returns Processing result * * @example * Example of returning a direct object: * {@includeCode ../../test/agents/agent.test.ts#example-process-direct-response} * * @example * Example of returning a streaming response: * {@includeCode ../../test/agents/agent.test.ts#example-process-streaming-response} * * @example * Example of using an async generator: * {@includeCode ../../test/agents/agent.test.ts#example-process-async-generator} * * @example * Example of transfer to another agent: * {@includeCode ../../test/agents/agent.test.ts#example-process-transfer} */ abstract process(input: I, options: AgentInvokeOptions): PromiseOrValue>; /** * Shut down the agent and clean up resources * * Primarily used to clean up memory and other resources to prevent memory leaks * * @example * Here's an example of shutting down an agent: * {@includeCode ../../test/agents/agent.test.ts#example-agent-shutdown} * * @example * Here's an example of shutting down an agent by using statement: * {@includeCode ../../test/agents/agent.test.ts#example-agent-shutdown-by-using} */ shutdown(): Promise; /** * Async dispose method for shutdown the agent * * @example * Here's an example of shutting down an agent by using statement: * {@includeCode ../../test/agents/agent.test.ts#example-agent-shutdown-by-using} */ [Symbol.asyncDispose](): Promise; /** For AFSModule interface **/ private agentToAFSEntry; private findAgentByAFSPath; list(_path: string, _options?: AFSListOptions): Promise; read(path: string): Promise; search(path: string, _query: string, options?: AFSSearchOptions): Promise; exec(path: string, args: Record, options: AFSExecOptions): Promise; } export type AgentInput = T extends Agent ? I : never; export type AgentOutput = T extends Agent ? O : never; /** * Lifecycle hooks for agent execution * * Hooks provide a way to intercept and extend agent behavior at key points during * the agent's lifecycle, enabling custom functionality like logging, monitoring, * tracing, error handling, and more. */ export interface AgentHooks { priority?: "low" | "medium" | "high"; /** * Called when agent processing begins * * This hook runs before the agent processes input, allowing for * setup operations, logging, or input transformations. * * @param event Object containing the input message */ onStart?: ((event: { context: Context; agent: Agent; input: I; }) => PromiseOrValue) | Agent<{ input: I; }, { input?: I; options?: any; }>; /** * Called when agent processing completes or fails * * This hook runs after processing finishes, receiving either the output * or an error if processing failed. Useful for cleanup operations, * logging results, or error handling. * * @param event Object containing the input message and either output or error */ onEnd?: ((event: XOr<{ context: Context; agent: Agent; input: I; output: O; error: Error; }, "output", "error">) => PromiseOrValue) | Agent, { output?: O; retry?: boolean; }>; onSuccess?: ((event: { context: Context; agent: Agent; input: I; output: O; }) => PromiseOrValue) | Agent<{ input: I; output: O; }, { output?: O; }>; onError?: ((event: { context: Context; agent: Agent; input: I; error: Error; }) => PromiseOrValue) | Agent<{ input: I; error: Error; }, { retry?: boolean; }>; /** * Called before a skill (sub-agent) is invoked * * This hook runs when the agent delegates work to a skill, * allowing for tracking skill usage or transforming input to the skill. * * @param event Object containing the skill being used and input message */ onSkillStart?: ((event: { context: Context; agent: Agent; skill: Agent; input: Message; }) => PromiseOrValue) | Agent<{ skill: Agent; input: Message; }>; /** * Called after a skill (sub-agent) completes or fails * * This hook runs when a skill finishes execution, receiving either the output * or an error if the skill failed. Useful for monitoring skill performance * or handling skill-specific errors. * * @param event Object containing the skill used, input message, and either output or error */ onSkillEnd?: ((event: XOr<{ context: Context; agent: Agent; skill: Agent; input: Message; output: Message; error: Error; }, "output", "error">) => PromiseOrValue) | Agent>; /** * Called when an agent hands off processing to another agent * * This hook runs when a source agent transfers control to a target agent, * allowing for tracking of handoffs between agents and monitoring the flow * of processing in multi-agent systems. * * @param event Object containing the source agent, target agent, and input message */ onHandoff?: ((event: { context: Context; source: Agent; target: Agent; input: I; }) => PromiseOrValue) | Agent<{ source: Agent; target: Agent; input: I; }>; } export type AgentHookInput = Hook extends (input: infer I) => any ? Omit : never; export type AgentHookOutput = Hook extends (...args: any[]) => any ? Exclude>, void> | undefined : never; /** * Response type for an agent, can be: * - Direct response object * - Output transferred to another agent * - Streaming response * * @template T Response data type */ export type AgentResponse = T | AgentResponseStream | TransferAgentOutput | GuideRailAgentOutput; /** * Streaming response type for an agent * * @template T Response data type */ export type AgentResponseStream = ReadableStream>; /** * Data chunk type for streaming responses * * @template T Response data type */ export type AgentResponseChunk = AgentResponseDelta | AgentResponseProgress; /** * Check if a response chunk is empty * * @template T Response data type * @param chunk The response chunk to check * @returns True if the chunk is empty */ export declare function isEmptyChunk(chunk: AgentResponseChunk): boolean; /** * Incremental data structure for agent responses * * Used to represent a single incremental update in a streaming response * * @template T Response data type * @property delta.text - Text format incremental update * @property delta.json - JSON format incremental update */ export interface AgentResponseDelta { delta: { text?: Partial<{ [key in keyof T as Extract extends string ? key : never]: string; }> | Partial<{ [key: string]: string; }>; json?: Partial | TransferAgentOutput; }; } export declare function isAgentResponseDelta(chunk: AgentResponseChunk): chunk is AgentResponseDelta; export interface AgentResponseProgress { progress: ({ event: "agentStarted"; input: Message; taskTitle?: string; } | { event: "agentSucceed"; output: Message; } | { event: "agentFailed"; error: Error; } | { event: "message"; message: ChatModelInputMessage; }) & Omit & { agent: { name: string; }; }; } export type AgentResponseProgressMessageItem = { type: "text"; content: string; } | { type: "thinking"; thoughts: string; } | { type: "tool_use"; toolUseId: string; name: string; input: unknown; } | { type: "tool_result"; toolUseId: string; content: unknown; }; export declare function isAgentResponseProgress(chunk: AgentResponseChunk): chunk is AgentResponseProgress; /** * Creates a text delta for streaming responses * * This utility function creates an AgentResponseDelta object with only the text part, * useful for incrementally building streaming text responses in agents. * * @template T Agent message type extending Message * @param textDelta The text content to include in the delta update * @returns An AgentResponseDelta with the text delta wrapped in the expected structure */ export declare function textDelta(textDelta: NonNullable["delta"]["text"]>): AgentResponseDelta; /** * Creates a JSON delta for streaming responses * * This utility function creates an AgentResponseDelta object with only the JSON part, * useful for incrementally building structured data responses in streaming mode. * * @template T Agent message type extending Message * @param jsonDelta The JSON data to include in the delta update * @returns An AgentResponseDelta with the JSON delta wrapped in the expected structure */ export declare function jsonDelta(jsonDelta: NonNullable["delta"]["json"]>): AgentResponseDelta; /** * Async generator type for agent processing * * Used to generate streaming response data * * @template O Agent output message type */ export type AgentProcessAsyncGenerator = AsyncGenerator, Partial | TransferAgentOutput | undefined | void>; /** * Result type for agent processing method, can be: * - Direct or streaming response * - Async generator * - Another agent instance (for task forwarding) * * @template O Agent output message type */ export type AgentProcessResult = AgentResponse | AgentProcessAsyncGenerator | Agent; export declare function agentProcessResultToObject(response: AgentProcessResult): Promise; /** * Schema definition type for agent input/output * * Can be a Zod type definition or a function that returns a Zod type * * @template I Agent input/output message type */ export type AgentInputOutputSchema = ZodType | ((agent: Agent) => ZodType); /** * Configuration options for a function agent * * Extends the base agent options and adds function implementation * * @template I Agent input message type * @template O Agent output message type */ export interface FunctionAgentOptions extends AgentOptions { /** * Function implementing the agent's processing logic * * This function is called by the process method to handle input * and generate output */ process: FunctionAgentFn; } /** * Function agent class, implements agent logic through a function * * Provides a convenient way to create agents using functions without * needing to extend the Agent class * * @template I Agent input message type * @template O Agent output message type * * @example * Here's an example of creating a function agent: * {@includeCode ../../test/agents/agent.test.ts#example-function-agent} */ export declare class FunctionAgent extends Agent { tag: string; static schema(): ZodObject<{ process: ZodType; }, "strip", z.ZodTypeAny, { process: FunctionAgentFn>; }, { process: FunctionAgentFn>; }>; static load(options: { filepath: string; parsed: object; }): Promise>; /** * Create a function agent from a function or options * * Provides a convenient factory method to create an agent directly from a function * * @param options Function agent options or function * @returns New function agent instance * * @example * Here's an example of creating a function agent from a function: * {@includeCode ../../test/agents/agent.test.ts#example-function-agent-from-function} * * @example * Here's an example of creating a function agent without basic agent options: * {@includeCode ../../test/agents/agent.test.ts#example-function-agent} * * @example * Here's an example of creating a function agent from a function returning a stream: * {@includeCode ../../test/agents/agent.test.ts#example-function-agent-stream} * * @example * Here's an example of creating a function agent from a function returning an async generator: * {@includeCode ../../test/agents/agent.test.ts#example-function-agent-async-generator} */ static from(options: FunctionAgentOptions | FunctionAgentFn): FunctionAgent; /** * Create a function agent instance * * @param options Function agent configuration options */ constructor(options: FunctionAgentOptions); /** * Stores the function used to process agent input and generate output * * @private */ _process: FunctionAgentFn; /** * Process input implementation, calls the configured processing function * * @param input Input message * @param options Invocation options * @returns Processing result */ process(input: I, options: AgentInvokeOptions): PromiseOrValue>; } /** * Function type for function agents * * Defines the function signature for processing messages in a function agent * * @template I Agent input message type * @template O Agent output message type * @param input Input message * @param context Execution context * @returns Processing result, can be synchronous or asynchronous */ export type FunctionAgentFn = FunctionAgent> = (this: A, input: I, options: AgentInvokeOptions) => PromiseOrValue>;