/** * @license * Copyright 2025 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import { Content } from '@google/genai'; import { Event } from '../events/event.js'; import { BaseNode, BaseNodeConfig } from '../workflow/base_node.js'; import type { NodeContext } from '../workflow/node_context.js'; import { Context } from './context.js'; import { InvocationContext } from './invocation_context.js'; /** * A single callback function for an agent. */ export type SingleAgentCallback = (context: Context) => Promise | (Content | undefined); /** * Type for before agent callbacks, which can be a single callback or * an array of callbacks. */ export type BeforeAgentCallback = SingleAgentCallback | SingleAgentCallback[]; /** * Type for after agent callbacks, which can be a single callback or * an array of callbacks. */ export type AfterAgentCallback = SingleAgentCallback | SingleAgentCallback[]; /** * The config of a base agent. * * Extends {@link BaseNodeConfig}, so every agent also accepts the node-level * options — `retryConfig`, `timeout`, `inputSchema`, `outputSchema`, * `stateSchema`, `rerunOnResume`, `waitForOutput` — which apply when the agent * runs inside a workflow. */ export interface BaseAgentConfig extends BaseNodeConfig { name: string; description?: string; parentAgent?: BaseAgent; subAgents?: BaseAgent[]; beforeAgentCallback?: BeforeAgentCallback; afterAgentCallback?: AfterAgentCallback; } /** * A unique symbol to identify ADK agent classes. * Defined once and shared by all BaseAgent instances. */ declare const BASE_AGENT_SIGNATURE_SYMBOL: unique symbol; /** * Type guard to check if an object is an instance of BaseAgent. * @param obj The object to check. * @returns True if the object is an instance of BaseAgent, false otherwise. */ export declare function isBaseAgent(obj: unknown): obj is BaseAgent; /** * Base class for all agents in Agent Development Kit. * * The class is generic over its config type so that {@link clone} can be typed * per subclass (e.g. `LlmAgent.clone({instruction})`). The default keeps bare * `BaseAgent` references valid as `BaseAgent`. * * An agent **is** a {@link BaseNode}, so any agent can be dropped straight into * a workflow graph without a wrapper — mirroring adk-python, where * `BaseAgent(BaseNode)`. {@link runImpl} bridges the two contracts: the node * runner calls it, and it delegates to the agent's own {@link runAsync}. */ export declare abstract class BaseAgent extends BaseNode { /** * A unique symbol to identify ADK agent classes. */ readonly [BASE_AGENT_SIGNATURE_SYMBOL] = true; /** * The config this agent was constructed from. * * Stored so {@link clone} can rebuild the agent by re-running the concrete * constructor with overrides applied, which re-derives all state correctly * instead of copying an already-mutated instance. Shallow-copied so later * external mutation of the caller's object does not leak into clones. */ protected readonly config: TConfig; /** * The agent's name. * Agent name must be a JS identifier and unique within the agent tree. * Agent name cannot be "user", since it's reserved for end-user's input. */ readonly name: string; /** * Root agent of this agent. * Computed dynamically by traversing up the parent chain. */ get rootAgent(): BaseAgent; /** * The parent agent of this agent. * * Note that an agent can ONLY be added as sub-agent once. * * If you want to add one agent twice as sub-agent, consider to create two * agent instances with identical config, but with different name and add them * to the agent tree. * * The parent agent is the agent that created this agent. */ parentAgent?: BaseAgent; /** * The sub-agents of this agent. */ readonly subAgents: BaseAgent[]; /** * Callback or list of callbacks to be invoked before the agent run. * * When a list of callbacks is provided, the callbacks will be called in the * order they are listed until a callback does not return undefined. * * @param callbackContext: MUST be named 'callbackContext' (enforced). * * @return Content: The content to return to the user. When the content is * present, the agent run will be skipped and the provided content will be * returned to user. */ readonly beforeAgentCallback: SingleAgentCallback[]; /** * Callback or list of callbacks to be invoked after the agent run. * * When a list of callbacks is provided, the callbacks will be called in the * order they are listed until a callback does not return undefined. * * @param callbackContext: MUST be named 'callbackContext' (enforced). * * @return Content: The content to return to the user. When the content is * present, the provided content will be used as agent response and * appended to event history as agent response. */ readonly afterAgentCallback: SingleAgentCallback[]; constructor(config: BaseAgentConfig); /** * Creates a copy of this agent with the given config fields overridden. * * Mirrors adk-python's `BaseAgent.clone(update=...)`. The clone is a detached * root: its `parentAgent` is always `undefined`. Sub-agents are recursively * cloned (and re-parented to the clone) unless `subAgents` is overridden. * Rebuilding via the concrete constructor re-derives all state, so a cloned * `LlmAgent` gets a fresh `requestProcessors` array rather than sharing the * original's. See google/adk-js#534. * * @param overrides Config fields to override on the clone. Overriding * `parentAgent` is rejected, matching adk-python. * @returns A new detached agent instance of the same concrete class. */ clone(overrides?: Partial): this; /** * Entry method to run an agent via text-based conversation. * * @param parentContext The invocation context of the parent agent. * @yields The events generated by the agent. * @returns An AsyncGenerator that yields the events generated by the agent. */ runAsync(parentContext: InvocationContext): AsyncGenerator; /** * Runs this agent as a workflow node. * * The node runner calls this; it delegates to {@link runAsync}, so an agent * behaves identically whether it is run directly or as a node. Mirrors * adk-python `BaseAgent._run_impl`. * * The invocation context comes from {@link NodeContext.getInvocationContext} * rather than the raw field, so the agent runs against whatever view of the * session the workflow wants it to see. * * Unlike adk-python's `_run_impl`, nothing is stamped onto the events here. * Python has to fix up the author and the node path because it authors * in-workflow events as the workflow itself; the TypeScript node runner * already owns both (`enrichEvent` keeps an author the node set, and always * stamps the true node path), so repeating it would be dead code. * * `nodeInput` is intentionally unused: an agent's input is its conversation, * which the workflow supplies through the session. A node that needs to read * its input — an `LlmAgent` injecting it into the prompt, say — does so in * its own wrapper. */ protected runImpl(ctx: NodeContext, _nodeInput: unknown): AsyncGenerator; /** * Entry method to run an agent via video/audio-based conversation. * * @param parentContext The invocation context of the parent agent. * @yields The events generated by the agent. * @returns An AsyncGenerator that yields the events generated by the agent. */ runLive(parentContext: InvocationContext): AsyncGenerator; /** * Core logic to run this agent via text-based conversation. * * @param context The invocation context of the agent. * @yields The events generated by the agent. * @returns An AsyncGenerator that yields the events generated by the agent. */ protected abstract runAsyncImpl(context: InvocationContext): AsyncGenerator; /** * Core logic to run this agent via video/audio-based conversation. * * @param context The invocation context of the agent. * @yields The events generated by the agent. * @returns An AsyncGenerator that yields the events generated by the agent. */ protected abstract runLiveImpl(context: InvocationContext): AsyncGenerator; /** * Finds the agent with the given name in this agent and its descendants. * * @param name The name of the agent to find. * @return The agent with the given name, or undefined if not found. */ findAgent(name: string): BaseAgent | undefined; /** * Finds the agent with the given name in this agent's descendants. * * @param name The name of the agent to find. * @return The agent with the given name, or undefined if not found. */ findSubAgent(name: string): BaseAgent | undefined; /** * Creates an invocation context for this agent. * * @param parentContext The invocation context of the parent agent. * @return The invocation context for this agent. */ protected createInvocationContext(parentContext: InvocationContext): InvocationContext; /** * Runs the before agent callback if it exists. * * @param invocationContext The invocation context of the agent. * @return The event to return to the user, or undefined if no event is * generated. */ protected handleBeforeAgentCallback(invocationContext: InvocationContext): Promise; /** * Runs the after agent callback if it exists. * * @param invocationContext The invocation context of the agent. * @return The event to return to the user, or undefined if no event is * generated. */ protected handleAfterAgentCallback(invocationContext: InvocationContext): Promise; private setParentAgentForSubAgents; } /** * Gets the canonical callback from the given callback. * * @param callbacks The callback or list of callbacks to get the canonical * callback from. * @return The canonical callback. */ export declare function getCannonicalCallback(callbacks?: T | T[]): T[]; export {};