import { type ZodType } from '@frontmcp/lazy-zod'; import { type ToolExecutor } from '../../agent/agent-execution-loop'; import { type ElicitOptions, type ElicitResult } from '../../elicitation'; import type { AIPlatformType, ClientInfo, McpLoggingLevel } from '../../notification'; import { type AgentInputOf, type AgentOutputOf } from '../decorators'; import type { AgentMetadata, AgentType, ToolInputType, ToolOutputType } from '../metadata'; import { ExecutionContextBase, type ExecutionContextBaseArgs } from './execution-context.interface'; import { type ProviderRegistryInterface } from './internal'; import { type AgentCompletion, type AgentCompletionChunk, type AgentCompletionOptions, type AgentLlmAdapter, type AgentPrompt, type AgentToolDefinition } from './llm-adapter.interface'; export type { AgentType }; /** * History entry for tracking input/output changes during execution. */ type HistoryEntry = { at: number; stage?: string; value: T | undefined; note?: string; }; /** * Constructor arguments for AgentContext. */ export type AgentCtorArgs = ExecutionContextBaseArgs & { metadata: AgentMetadata; input: In; llmAdapter: AgentLlmAdapter; agentScope?: ProviderRegistryInterface; /** Tool definitions available to this agent */ toolDefinitions?: AgentToolDefinition[]; /** Function to execute tools - provided by AgentInstance */ toolExecutor?: ToolExecutor; /** Progress token from the request's _meta, used for progress notifications */ progressToken?: string | number; }; /** * Abstract base class for agent execution contexts. * * Agents are autonomous units with their own LLM provider, isolated scope, * and the ability to be invoked as tools by other agents or the parent app. * * Override the protected methods to customize agent behavior: * - `completion()` - Override for custom LLM completion logic * - `streamCompletion()` - Override for custom streaming logic * - `executeTool()` - Override for custom tool execution logic * * @example * ```typescript * // Default behavior - works automatically (no execute() needed!) * @Agent({ * name: 'research-agent', * description: 'Researches topics', * systemInstructions: 'You are a research assistant. Search and summarize topics.', * llm: { adapter: 'openai', model: 'gpt-4-turbo', apiKey: { env: 'OPENAI_API_KEY' } }, * tools: [WebSearchTool], * }) * export default class ResearchAgent extends AgentContext {} * * // Custom behavior - override execute() only when needed * @Agent({ ... }) * export default class CustomAgent extends AgentContext { * async execute(input: Input): Promise { * // Custom pre-processing * const result = await super.execute(input); // Call default loop * // Custom post-processing * return result; * } * } * ``` */ export declare class AgentContext, Out = AgentOutputOf<{ outputSchema: OutSchema; }>> extends ExecutionContextBase { protected readonly agentId: string; protected readonly agentName: string; readonly metadata: AgentMetadata; /** The LLM adapter for this agent */ protected readonly llmAdapter: AgentLlmAdapter; /** Agent-scoped provider registry (if isolated scope is enabled) */ protected readonly agentScope?: ProviderRegistryInterface; /** System instructions for the agent's LLM */ protected readonly systemInstructions: string; /** Tool definitions available to this agent */ protected readonly toolDefinitions: AgentToolDefinition[]; /** Function to execute tools - provided by AgentInstance */ protected readonly toolExecutor?: ToolExecutor; private _rawInput?; private _input?; private _outputDraft?; private _output?; private readonly _inputHistory; private readonly _outputHistory; private readonly _progressToken?; constructor(args: AgentCtorArgs); /** * Execute the agent with the given input. * * **Default behavior:** Runs the agent execution loop automatically: * - Sends input + system instructions to the LLM * - Executes tool calls as needed * - Sends notifications on tool calls and output * - Returns the final response * * **Override this method** only when you need custom behavior: * - Custom pre/post processing * - Custom response formatting * - Multi-step workflows * * @example * ```typescript * // Custom behavior - call super.execute() for default loop * async execute(input: Input): Promise { * this.notify('Starting custom agent...', 'info'); * const result = await super.execute(input); * return { ...result, customField: 'added' }; * } * ``` */ execute(input: In): Promise; /** * Run the agent execution loop. * * This is the default implementation that: * 1. Builds prompt from input + system instructions * 2. Sends to LLM with available tools * 3. Executes tool calls and loops until final response * 4. Sends notifications on tool calls and output */ protected runAgentLoop(input: In): Promise; /** * Build the user message from input. * Override this to customize how input is formatted for the LLM. */ protected buildUserMessage(input: In): string; /** * Parse the LLM response into the expected output format. * Override this to customize response parsing. */ protected parseAgentResponse(content: string | null): Out; get input(): In; set input(v: In | undefined); get inputHistory(): ReadonlyArray>; get output(): Out | undefined; set output(v: Out | undefined); get outputHistory(): ReadonlyArray>; /** * Generate a completion from the LLM. * * Override this method to add custom pre/post processing: * * @example * ```typescript * protected override async completion(prompt, tools, options) { * console.log('Pre-processing...'); * const result = await super.completion(prompt, tools, options); * console.log('Post-processing...'); * return result; * } * ``` */ protected completion(prompt: AgentPrompt, tools?: AgentToolDefinition[], options?: AgentCompletionOptions): Promise; /** * Stream a completion from the LLM. * * Override this method to add custom streaming logic. */ protected streamCompletion(prompt: AgentPrompt, tools?: AgentToolDefinition[], options?: AgentCompletionOptions): AsyncGenerator; /** * Execute a tool by name with the given arguments. * * Override this method to add custom tool execution logic: * - Logging * - Caching * - Error handling * - Tool call interception */ protected executeTool(name: string, args: Record): Promise; /** * Invoke another agent by ID. * * Only available if `swarm.canSeeOtherAgents` is true or the target agent * is in `swarm.visibleAgents`. */ protected invokeAgent(agentId: string, input: unknown): Promise; /** * Send a notification message to the current session. * Uses 'notifications/message' per MCP 2025-11-25 spec. * * Use this to report progress during long-running operations. * * @param message - The notification message (string) or structured data (object) * @param level - Log level: 'debug', 'info', 'warning', or 'error' (default: 'info') * @returns true if the notification was sent, false if session unavailable * * @example * ```typescript * async execute(input: Input): Promise { * await this.notify('Starting agent processing...', 'info'); * await this.notify({ step: 1, total: 5, status: 'in_progress' }); * // ... processing * return result; * } * ``` */ protected notify(message: string | Record, level?: McpLoggingLevel): Promise; /** * Send a progress notification to the current session. * Uses 'notifications/progress' per MCP 2025-11-25 spec. * * Only works if the client requested progress updates by including a * progressToken in the request's _meta field. If no progressToken was * provided, this method logs a debug message and returns false. * * @param progress - Current progress value (should increase monotonically) * @param total - Total progress value (optional) * @param message - Progress message (optional) * @returns true if the notification was sent, false if no progressToken or session * * @example * ```typescript * async execute(input: Input): Promise { * for (let i = 0; i < 10; i++) { * await this.progress(i + 1, 10, `Step ${i + 1} of 10`); * await doWork(); * } * return result; * } * ``` */ protected progress(progress: number, total?: number, message?: string): Promise; /** * Request interactive input from the user during agent execution. * * Sends an elicitation request to the client for user input. The client * presents the message and a form (or URL) to collect user response. * * Only one elicit per session is allowed. A new elicit will cancel any pending one. * On timeout, an ElicitationTimeoutError is thrown to kill agent execution. * * For clients that don't support elicitation, the framework automatically handles * the fallback flow using the sendElicitationResult tool. * * @param message - Prompt message to display to user * @param requestedSchema - Zod schema defining expected input structure * @param options - Mode ('form'|'url'), ttl (default 5min), elicitationId (for URL mode) * @returns ElicitResult with status and typed content * @throws ElicitationNotSupportedError if client doesn't support elicitation and no fallback available * @throws ElicitationFallbackRequired (internal) triggers fallback flow for non-supporting clients * @throws ElicitationTimeoutError if request times out (kills execution) * * @example * ```typescript * async execute(input: Input): Promise { * const result = await this.elicit('Confirm action?', z.object({ * confirmed: z.boolean(), * reason: z.string().optional() * })); * * if (result.status !== 'accept') { * return { cancelled: true }; * } * // result.content is typed { confirmed: boolean, reason?: string } * return { confirmed: result.content!.confirmed }; * } * ``` */ protected elicit(message: string, requestedSchema: S, options?: ElicitOptions): Promise ? O : unknown>>; /** * Respond with the final output and end execution. * * This sets the output and throws to exit the flow immediately. */ respond(value: Out): never; /** * Get the detected AI platform type for the current session. */ get platform(): AIPlatformType; /** * Get the client info (name and version) for the current session. */ get clientInfo(): ClientInfo | undefined; } //# sourceMappingURL=agent.interface.d.ts.map