/** * AgentSession class - Manages the lifecycle of an agent session. * * This class provides a high-level interface for managing agent sessions, * including starting, stopping, and interacting with the agent. */ import type { AgoraClient } from "../AgoraPoolClient.js"; import type { AgentManagementClient } from "../api/resources/agentManagement/client/Client.js"; import type { AgentsClient } from "../api/resources/agents/client/Client.js"; import type { Agent } from "./Agent.js"; import type { AgoraArea } from "./area.js"; import { type PresetInput } from "./presets.js"; import type { AgentConfigUpdate, ConversationHistory, ConversationTurns, GetTurnsOptions, SayOptions, SessionInfo, ThinkOptions, ThinkResponse } from "./types.js"; /** * Event types that can be emitted by AgentSession. */ export type AgentSessionEvent = "started" | "stopped" | "error"; /** * Event handler type. */ export type AgentSessionEventHandler = (data: T) => void; /** * Configuration options for creating an AgentSession. */ export interface AgentSessionOptions { /** The Agora client instance */ client: AgoraClient; /** The agent configuration */ agent: Agent; /** The App ID */ appId: string; /** The App Certificate — enables automatic RTC token generation when starting sessions */ appCertificate?: string; /** Unique agent instance name (set via {@link Agent.createSession}) */ name: string; /** The channel to join */ channel: string; /** Authentication token for the channel. Omit to auto-generate (requires appCertificate). */ token?: string; /** The agent's RTC UID */ agentUid: string; /** Remote user UIDs to subscribe to */ remoteUids: string[]; /** Idle timeout in seconds (0 = no auto-exit) */ idleTimeout?: number; /** Whether to use string UIDs */ enableStringUid?: boolean; /** Preset IDs to use as the base ASR/LLM/TTS configuration for this session */ preset?: PresetInput; /** Published AI Studio pipeline ID to use as this session's base configuration. Overrides agent.pipelineId. */ pipelineId?: string; /** * Token lifetime in seconds (default: 86400 = 24 hours, Agora maximum). * Only applies when the SDK auto-generates a token (i.e. no `token` is provided). * Valid range: 1–86400. Use `ExpiresIn.hours()` / `ExpiresIn.minutes()` for clarity. */ expiresIn?: number; /** Enable debug logging of API requests */ debug?: boolean; /** * Optional logger for warnings. Defaults to console.warn. * Set to a no-op function to silence warnings. */ warn?: (message: string) => void; } /** * AgentSession class for managing agent lifecycle and interactions. * * Use {@link Agent.createSession} to create a session — this is the recommended entry point. * * @example * ```typescript * import { AgoraClient, Area, Agent, OpenAI, ElevenLabsTTS, DeepgramSTT } from 'agora-agents'; * * const client = new AgoraClient({ * area: Area.US, * appId: '...', * appCertificate: '...', * }); * * const agent = new Agent({ client, instructions: 'You are a helpful voice assistant.' }) * .withLlm(new OpenAI({ apiKey: '...', model: 'gpt-4o-mini', url: 'https://api.openai.com/v1/chat/completions' })) * .withTts(new ElevenLabsTTS({ key: '...', modelId: '...', voiceId: '...', baseUrl: 'wss://api.elevenlabs.io/v1', sampleRate: 24000 })) * .withStt(new DeepgramSTT({ apiKey: '...', language: 'en-US' })); * * const session = agent.createSession({ * name: `conversation-${Date.now()}`, * channel: `demo-channel-${Date.now()}`, * agentUid: '1', * remoteUids: ['100'], * }); * * const agentId = await session.start(); * * await session.say('Hello! How can I help you today?'); * await session.stop(); * ``` */ export declare class AgentSession { private readonly _client; private readonly _agent; private readonly _appId; private readonly _appCertificate?; private readonly _name; private readonly _channel; private readonly _token?; private readonly _agentUid; private readonly _remoteUids; private readonly _idleTimeout?; private readonly _enableStringUid?; private readonly _preset?; private readonly _pipelineId?; private readonly _expiresIn?; private readonly _debug?; private readonly _authMode; private _agentsClient; private _agentManagementClient; private _previewFeatures; private _sessionBaseUrl?; private _agentId; private _status; private _eventHandlers; private readonly _warn; constructor(options: AgentSessionOptions); private _clientCurrentUrl; /** * Builds per-request headers for app-credentials auth mode. * * Generates a fresh ConvoAI REST token on each call — no caching — to * avoid expired-token issues. Token generation is cheap. * * Returns undefined for basic and pre-built-token modes (the client handles those). */ private _convoAIHeaders; /** Auth plus the route gate, with the gate pinned last. */ private _requestHeaders; /** * Client-level default headers, for debug logging only. * * Reaches into `_options` the same way `authMode` is read in the constructor; * supplier-valued headers are skipped rather than resolved, since debug * logging must not trigger side effects. */ private _clientDefaultHeaders; /** * The current agent ID (null if not started). */ get id(): string | null; /** * The current session status. */ get status(): "idle" | "starting" | "running" | "stopping" | "stopped" | "error"; /** * The agent configuration. */ get agent(): Agent; /** * The App ID for this session. */ get appId(): string; /** * Direct access to the underlying Fern-generated AgentsClient. * * Use this to access any new endpoints that Fern generates without * waiting for agentkit method updates. New endpoints are immediately * available via this property. * * Note: You'll need to pass appid and agentId manually when using raw methods. * * @example * ```typescript * // Access new endpoints directly * await session.raw.someNewEndpoint({ * appid: session.appId, * agentId: session.id!, * // ... other params * }); * ``` */ get raw(): AgentsClient; /** * Direct access to the underlying Fern-generated AgentManagement client. */ get rawAgentManagement(): AgentManagementClient; /** * Returns true when the agent is configured for MLLM (multimodal end-to-end audio). */ private _isMllmMode; /** * Warns when agent-level `instructions` would be silently discarded. * * `instructions` is only serialized into `llm.system_messages`, which does * not exist in an MLLM pipeline — the Go and Python SDKs drop it the same * way. Without this warning the agent starts with no system prompt at all * and the only symptom is off-persona replies. */ private _warnOnDroppedMllmInstructions; /** * Validates avatar and TTS configuration before starting. * * This catches common misconfigurations like using the wrong TTS sample rate * for a specific avatar vendor (e.g., HeyGen requires 24kHz, Akool requires 16kHz), * and rejects the unsupported MLLM + avatar combination. * * @throws {Error} If configuration is invalid */ private _validateAvatarConfig; /** * Fills session-derived avatar fields and generates avatar ConvoAI tokens. * * Token management is gated to vendors that publish a separate RTC video * identity (HeyGen, LiveAvatar, Generic, SenseTime). Other vendors (Akool, Anam) do * not run a separate publisher and never receive an auto-generated token. */ private _enrichAvatarParams; private _validateEnrichedAvatarConfig; private _vendorValidationCategories; /** * Start the agent session. * * All connection details were provided when creating the session. * * @returns A promise that resolves to the agent ID * @throws {Error} If avatar/TTS configuration is invalid */ start(): Promise; /** * Stop the agent session. * * If the agent has already stopped (e.g., crashed or timed out), * this method will succeed silently rather than throwing an error. */ stop(): Promise; /** * Send a message to be spoken by the agent. * * @param text - The text to speak * @param options - Optional speak options */ say(text: string, options?: SayOptions): Promise; /** * Interrupt the agent while speaking or thinking. */ interrupt(): Promise; /** * Inject a text instruction into the current session pipeline. */ think(text: string, options?: ThinkOptions): Promise; /** * Update the agent configuration at runtime. * * @param config - Partial configuration to update */ update(config: AgentConfigUpdate): Promise; /** * Get the conversation history. * * @returns The conversation history */ getHistory(): Promise; /** * Get turn-by-turn analytics and timing details for this session. * * @returns The session's conversation turns */ getTurns(options?: GetTurnsOptions): Promise; /** * Get all turn analytics pages for this session. * * For very long sessions, prefer processing pages with `getTurns()` to avoid * holding all turn data in memory at once. */ getAllTurns(options?: Omit): Promise; /** * Get the current session info. * * @returns The session info */ getInfo(): Promise; /** * Register an event handler. * * @param event - The event type * @param handler - The event handler */ on(event: AgentSessionEvent, handler: AgentSessionEventHandler): void; /** * Unregister an event handler. * * @param event - The event type * @param handler - The event handler */ off(event: AgentSessionEvent, handler: AgentSessionEventHandler): void; /** * Emit an event to all registered handlers. */ private _emit; }