import { type LLMToolDefinition, type LLMToolResult, type LLMTerminalToolOutcome, type LLMToolLoopStopReasons } from '../LLMService.typedefs'; import { type LLMPromptRegistry } from '../client/defineLLMPrompts'; import { type LLMVariableValue } from '../client/promptSnapshot.typedefs'; import { type LLMCallOverrides, type LLMClientCallContext, type LLMHistoryMessage } from '../client/llmClient.typedefs'; import { type LLMAgentSubagent } from '../client/LLMAgent'; /** * Structured progress events an agent run emits while it works. They exist for * two consumers with different needs: live UI updates (publish each event over * a subscription/WS channel) and durable run history (persist each event as it * arrives). Events are observability output, not control flow — a listener * failure never affects the run. */ export declare enum LLMAgentEventTypes { AgentStarted = "agent_started", AgentStepStarted = "agent_step_started", AgentMessage = "agent_message", AgentCompleted = "agent_completed", AgentFailed = "agent_failed", ToolCallStarted = "tool_call_started", ToolCallCompleted = "tool_call_completed", ToolCallFailed = "tool_call_failed", ToolCallDenied = "tool_call_denied", ToolCallRejected = "tool_call_rejected", SubagentStarted = "subagent_started", SubagentCompleted = "subagent_completed", SubagentFailed = "subagent_failed" } /** * `agent` names the run that emitted the event: the prompt name for the root * run, the subagent's `name` for a delegated run. `runId` identifies that run * uniquely within the root run's event stream (ids come from one sequence * spanning the whole tree), so a flat listener can rebuild the run tree even * when the same subagent runs twice or tools execute in parallel. */ interface LLMAgentEventBase { agent: string; runId: number; } /** Correlates the started/completed/failed events of one tool invocation. */ interface LLMAgentInvocationEventBase extends LLMAgentEventBase { invocationId: number; } /** * `subagentRunId` is the `runId` carried by the delegated run's own events, * linking a Subagent* event to the nested Agent* events it produced. */ interface LLMAgentSubagentEventBase extends LLMAgentInvocationEventBase { subagent: string; subagentRunId: number; } export interface LLMAgentStartedEvent extends LLMAgentEventBase { type: LLMAgentEventTypes.AgentStarted; input: string; } export interface LLMAgentStepStartedEvent extends LLMAgentEventBase { type: LLMAgentEventTypes.AgentStepStarted; } /** * Visible assistant text the model produced in a tool-calling round that will * continue the loop — narration emitted alongside tool calls, before those * tools run. The final round's answer is never sent here (it is * `LLMAgentCompletedEvent.output`); reasoning/thinking content and * empty/whitespace-only text are never sent either. `agent`/`runId` identify * the emitting run, so a subagent's narration is attributed to the subagent. */ export interface LLMAgentMessageEvent extends LLMAgentEventBase { type: LLMAgentEventTypes.AgentMessage; text: string; } export interface LLMAgentCompletedEvent extends LLMAgentEventBase { type: LLMAgentEventTypes.AgentCompleted; output: string; durationMs: number; } export interface LLMAgentFailedEvent extends LLMAgentEventBase { type: LLMAgentEventTypes.AgentFailed; error: string; durationMs: number; } export interface LLMAgentToolCallStartedEvent extends LLMAgentInvocationEventBase { type: LLMAgentEventTypes.ToolCallStarted; tool: string; input: unknown; } export interface LLMAgentToolCallCompletedEvent extends LLMAgentInvocationEventBase { type: LLMAgentEventTypes.ToolCallCompleted; tool: string; output: LLMToolResult; durationMs: number; } export interface LLMAgentToolCallFailedEvent extends LLMAgentInvocationEventBase { type: LLMAgentEventTypes.ToolCallFailed; tool: string; error: string; durationMs: number; } /** * A call the model made that never ran: the tool's `canExecute` precondition * refused it. It replaces the `tool_call_completed` of that invocation (the * `tool_call_started` before it shares the `invocationId`), and the run * continues — the `reason` goes back to the model as the call's result. A * refused delegation reports here too, with `tool` naming the subagent; the * `subagent_started` that precedes it has no nested run because the subagent * never started. */ export interface LLMAgentToolCallDeniedEvent extends LLMAgentInvocationEventBase { type: LLMAgentEventTypes.ToolCallDenied; tool: string; reason: string; } export interface LLMAgentToolCallRejectedEvent extends LLMAgentEventBase { type: LLMAgentEventTypes.ToolCallRejected; tool: string; input: unknown; error: string; } export interface LLMAgentSubagentStartedEvent extends LLMAgentSubagentEventBase { type: LLMAgentEventTypes.SubagentStarted; input: string; } export interface LLMAgentSubagentCompletedEvent extends LLMAgentSubagentEventBase { type: LLMAgentEventTypes.SubagentCompleted; output: LLMToolResult; durationMs: number; } export interface LLMAgentSubagentFailedEvent extends LLMAgentSubagentEventBase { type: LLMAgentEventTypes.SubagentFailed; error: string; durationMs: number; } export type LLMAgentEvent = LLMAgentStartedEvent | LLMAgentStepStartedEvent | LLMAgentMessageEvent | LLMAgentCompletedEvent | LLMAgentFailedEvent | LLMAgentToolCallStartedEvent | LLMAgentToolCallCompletedEvent | LLMAgentToolCallFailedEvent | LLMAgentToolCallDeniedEvent | LLMAgentToolCallRejectedEvent | LLMAgentSubagentStartedEvent | LLMAgentSubagentCompletedEvent | LLMAgentSubagentFailedEvent; /** * May be async: a returned promise's rejection is caught and logged, so a * failing listener (WS publish, DB persist) never affects the agent run. */ export type LLMAgentEventListener = (event: LLMAgentEvent) => void | Promise; /** * A turn that produced a model answer: either the model finished on its own * (`Completed`) or the loop hit `maxToolIterations` (`MaxIterations`). `output` * is the bound schema's type, or the final assistant text when no schema is * bound — exactly what `generate` returns. */ export interface LLMAgentAnsweredRunResult { stopReason: Exclude; output: Output; /** Visible assistant text of the final round. */ text: string; terminalTool?: undefined; } /** * A turn ended by a tool declaring `terminal` (for example an `ask_user` tool). * The model produced no final answer — the round ran in full, its results were * not fed back, and no further model round started — so the turn's outcome is * `terminalTool`, which the application handles before resuming the agent. */ export interface LLMAgentTerminalToolRunResult { stopReason: LLMToolLoopStopReasons.TerminalTool; terminalTool: LLMTerminalToolOutcome; /** Visible assistant text of the terminating round; often empty. */ text: string; output?: undefined; } /** * What one agent run produced. Discriminate on `stopReason` (or on the presence * of `terminalTool`) to tell an answered turn from one handed back to the * application by a terminal tool. */ export type LLMAgentRunResult = LLMAgentAnsweredRunResult | LLMAgentTerminalToolRunResult; /** * Optional safeguards for agents that persist work outside their returned * prose. Omit this policy to preserve the gateway's historical retry and * delegation behaviour. */ export interface LLMAgentFailurePolicy { /** Add a corrective machine hint after this many identical failures. */ identicalToolCallNudgeAfter: number; /** Stop only the affected delegation after this many identical failures. */ identicalToolCallAbortAfter: number; } /** * How much prose one specialist may hand back. Declared per subagent because * the ceiling belongs to that delegation's contract: a specialist asked to * name every entity it touched legitimately reports more than one asked for a * short summary of a document it persisted elsewhere. The note travels with * the length so a cap can never be configured without one. */ export interface LLMAgentSubagentReportCap { maxLength: number; truncationNote: string; } export declare enum LLMAgentSubagentReportStatus { Truncated = "REPORT_TRUNCATED" } export declare enum LLMAgentToolFailureStatus { Systemic = "SYSTEMIC_TOOL_FAILURE" } /** * What the parent model reads in place of a delegation that was stopped for * repeating one failing call. It is JSON so the parent can act on the fields * rather than on prose. */ export interface SystemicToolFailureReport { status: LLMAgentToolFailureStatus; tool: string; consecutiveFailures: number; lastError: string; message: string; } export interface ToolFailureStreak { inputKey: string; count: number; lastError: string; } export interface ToolFailureContext { toolName: string; input: Record; error: unknown; } export interface ToolFailedResultContext { toolName: string; input: Record; error: string; text: string; } /** * Per-run inputs shared by both `runAgent` forms. When running an `LLMAgent` * instance these are the only options — the agent already carries its tools, * subagents, and iteration bound. */ export interface LLMAgentRunOptions> { /** Variables compiled into the agent's instructions prompt. */ variables: Variables; /** The user request the agent works on this run. */ input: string; /** * Prior conversation restored from persisted session state — plain turns, * past tool calls with their results, and mid-conversation context, each * replayed as the provider's own representation of it. */ history?: LLMHistoryMessage[]; context?: LLMClientCallContext; /** * Groups the traces of one conversation, review, or agent run into a single * Langfuse session, subagent runs included. It is a typed Langfuse trace * field, not metadata, so it never reaches the reporter's payload. Top level * rather than nested under a trace object because a session is understandable * without knowing what a trace is. Keep the anchor stable — changing it * splits a session's history in two. */ sessionId?: string; /** * Langfuse trace tags. Typed Langfuse trace fields, not metadata. The `trace` * prefix is deliberate: a bare `tags` says nothing about which system reads * them. */ traceTags?: string[]; abortSignal?: AbortSignal; overrides?: LLMCallOverrides; onEvent?: LLMAgentEventListener; failurePolicy?: LLMAgentFailurePolicy; } /** * Options for the prompt-key form of `runAgent`, where the agent shape is * declared inline instead of via an `LLMAgent` instance. */ export interface LLMAgentInlineRunOptions, Registry extends LLMPromptRegistry, VariableMap extends Record> extends LLMAgentRunOptions { /** Executable tools available to the agent. */ tools?: LLMToolDefinition[]; subagents?: LLMAgentSubagent[]; maxToolIterations?: number; } export {};