import type { OperationLifecycleLike } from '../types/lifecycle.js'; import { type CompiledGraph } from '../graph/graph.js'; import type { GraphCheckpointer, InterruptRequest, NodeContext } from '../types/graph.js'; import type { CompletionRequest, Message, ToolDefinition } from '../types/messages.js'; import type { NexusResponse, StreamChunk } from '../types/response.js'; import type { Principal } from '../types/principal.js'; import type { Store } from '../types/store.js'; import type { PermissionPolicyLike } from './permissions.js'; /** * An agent as a graph. * * `AgentLoop` is a `while` loop: it cannot be paused, resumed after a restart, inspected halfway, or * made to run two tool calls at once, because a loop has nowhere to keep that state. The same agent * expressed as a graph inherits all of it — checkpoints, human approval through `interrupt()`, * parallel tool tasks through `Send`, forks, events, and a Mermaid diagram — without this module * implementing any of them. `AgentLoop` stays for the simple case that wants none of that. */ /** The model call an agent makes. Injected, so this module needs no provider runtime. */ export interface AgentModelClient { /** Runs one completion. */ complete(request: CompletionRequest): Promise; /** Streams one completion. Used when the agent is created with `streamTokens`. */ stream?(request: CompletionRequest): AsyncIterable; } /** A tool call the agent is about to make. */ export interface AgentToolCall { /** The model's id for the call. */ id: string; /** The tool's name. */ name: string; /** Arguments, parsed from the model's JSON. */ args: Record; /** What the call declares it does, when the tool declares capabilities. */ capabilities?: readonly string[]; /** Why the permission policy asked for approval, when it did. */ permission?: string; } /** What an approver may answer: allow, refuse with a reason, or allow with corrected arguments. */ export type AgentApproval = boolean | { approved: true; args?: Record; } | { approved: false; reason?: string; }; /** How a call to a tool that needs approval is presented to the operator. */ export interface AgentApprovalPolicy { /** The question an operator sees. Defaults to naming the tool and its arguments. */ reason?: (call: AgentToolCall) => string; } /** What every middleware hook can read about the step it runs in. */ export interface AgentMiddlewareContext { /** The agent's state at this step: the whole transcript, tool calls and results included. */ state: AgentState; /** Long-term memory, when the agent has a store. */ store?: Store; /** The thread the run belongs to. */ threadId: string; /** The tenant the run is for, when it has one. */ tenantId?: string; /** Who the run is for, when it has a principal: the caller the server authenticated. */ principal?: Readonly; /** Aborted when the run is cancelled or the step times out. A hook that waits should stop with it. */ signal: AbortSignal; /** * Suspends the run until a person answers, as `interruptOn` does. When the run resumes, the step * runs again and this returns the answer instead of suspending. */ interrupt(request: InterruptRequest): T; } /** What `wrapModelCall` can read, and how it ends the run without calling the model. */ export interface AgentModelCallContext extends AgentMiddlewareContext { /** * Ends the run with this answer and `stopReason: 'stopped'`, without another model call. Return * what it returns: `return context.stop('The model call limit was reached.')`. */ stop(answer: string): NexusResponse; } /** Hooks around the agent's model calls and tool calls. Each hook is optional. */ export interface AgentMiddleware { /** Names the middleware in traces and errors. */ name?: string; /** Adjusts the request before it is sent: trim history, add context, swap the model. */ beforeModel?(context: AgentMiddlewareContext & { request: CompletionRequest; }): CompletionRequest | void | Promise; /** Inspects or replaces the response: redact, validate, count. */ afterModel?(context: AgentMiddlewareContext & { response: NexusResponse; }): NexusResponse | void | Promise; /** * Wraps the model call itself, after every `beforeModel` and before every `afterModel`. `next` * sends a request and may be called again, with the same request or a changed one, to retry or to * fall back to another model. The first middleware is the outermost. */ wrapModelCall?(request: CompletionRequest, next: (request: CompletionRequest) => Promise, context: AgentModelCallContext): Promise | NexusResponse; /** * Wraps a tool call, so a policy can log it, time it, retry it, or refuse it. `next` runs the * rest of the chain and may be called again; given a call, it runs that call's arguments instead, * and the permission policy decides them again first. The first middleware is the outermost. */ wrapToolCall?(call: AgentToolCall, next: (call?: AgentToolCall) => Promise, context: AgentMiddlewareContext): Promise | AgentToolResult; } /** What a tool call produced. */ export interface AgentToolResult { /** True when the tool returned a value. */ ok: boolean; /** The value returned. */ result?: unknown; /** Why the tool failed. */ error?: string; } /** Options for `createAgent()`. */ export interface CreateAgentOptions { /** Client the model is called through. */ client: AgentModelClient; /** Model to use. Defaults to the client's routing. */ model?: string; /** Tools the model may call. */ tools?: ToolDefinition[]; /** System prompt placed before the conversation. */ systemPrompt?: string; /** Model calls before the agent stops with `stopReason: 'max_iterations'`. Defaults to 8. */ maxIterations?: number; /** Tool calls run at once. Defaults to 8; `1` runs them one at a time. */ toolConcurrency?: number; /** Tools that need human approval before they run, keyed by tool name. */ interruptOn?: Record; /** Hooks around model and tool calls, applied in order. */ middleware?: AgentMiddleware[]; /** * Decides every tool call from the capabilities it declares, before it runs: allow it, deny it, * or interrupt for a person's approval, as `interruptOn` does. A denied call reaches the model as a * failed tool result naming the reason, and never runs. See `permissionPolicy()` in * `nexus-ai-pro/agent/permissions`. */ permissions?: PermissionPolicyLike; /** Long-term memory, available to tools and middleware as `store`. */ store?: Store; /** * Where checkpoints go. Defaults to the graph's in-process checkpointer; `false` disables them, * and with them approvals. */ checkpointer?: GraphCheckpointer | false; /** Names the agent in checkpoints and traces. */ name?: string; /** Sampling temperature. */ temperature?: number; /** Output token limit. */ maxTokens?: number; /** Structured output format for answers. */ responseFormat?: CompletionRequest['responseFormat']; /** Application data sent with every model request. */ metadata?: Record; /** * Runs every invocation as one operation of a client's lifecycle, labelled `agent`: pass * `ai.lifecycle`. Its model calls are operations of their own. */ lifecycle?: OperationLifecycleLike; /** * Streams the model's output token by token onto the run's `messages` events, through the client's * `stream()`. Without it, or with a client that cannot stream, each answer arrives as one message * event once the model returns. Middleware sees the assembled response either way. */ streamTokens?: boolean; /** * Tools that depend on the run, added to `tools` on every model call and run like them: an editor's * file system for one session, or the MCP servers one user connected. A tool in `tools` wins over a * source's tool of the same name. */ toolSource?: (context: ToolSourceContext) => ToolDefinition[] | Promise; } /** What a tool source is told about the run it supplies tools for. */ export interface ToolSourceContext { /** The run's thread. */ threadId: string; /** The tenant the run is for. */ tenantId?: string; /** Who the run is for. */ principal?: Readonly; /** Aborted when the run is cancelled. */ signal: AbortSignal; } /** * A tool the client runs, such as one an AG-UI frontend offers: a name, a description, and a schema, * with no implementation on the agent's side. Given in the input as `clientTools`, it is offered to * the model like any tool. When the model calls one, the agent ends its turn with `stopReason: * 'client_tools'`, and the client sends the result back in the next run's messages. */ export interface ClientToolDefinition { /** The name the model calls it by. */ name: string; /** What it does, written for the model. */ description: string; /** JSON Schema for the arguments. */ parameters: Record; } declare const agentChannels: () => { messages: import("../types/graph.js").Channel; iterations: import("../types/graph.js").Channel; answer: import("../types/graph.js").Channel; stopReason: import("../types/graph.js").Channel; clientTools: import("../types/graph.js").Channel; }; /** The agent's state channels, as a graph schema. */ export type AgentChannels = ReturnType; /** The agent's state. */ export type AgentState = { /** The conversation, tool calls and results included. */ messages: Message[]; /** Model calls made so far. */ iterations: number; /** The final answer, once the model stops calling tools. */ answer: string; /** Why the agent stopped. */ stopReason?: AgentStopReason; /** Tools the client runs, given in the input; see `ClientToolDefinition`. */ clientTools?: ClientToolDefinition[]; }; /** * `completed` when the model answered, `max_iterations` when it ran out of model calls, `stopped` * when a middleware ended the run through `context.stop()`, and `client_tools` when the model called * a tool the client runs, which waits for the client's result. */ export type AgentStopReason = 'completed' | 'max_iterations' | 'stopped' | 'client_tools'; /** An agent: a compiled graph over the agent's channels. */ export type AgentGraph = CompiledGraph; /** Wraps a question into the state an agent starts from. */ export declare function agentInput(goal: string): { messages: Message[]; }; /** * Builds an agent and returns it as a compiled graph. * * Run it like any graph: `agent.invoke(agentInput('...'), { threadId })`. The result's `answer` is * the final text, and `stopReason` says whether the agent finished or ran out of iterations. */ export declare function createAgent(options: CreateAgentOptions): AgentGraph; /** * Turns an agent into a tool another agent can call. * * The simplest multi-agent shape: a supervisor keeps control and delegates, rather than handing over * the conversation. The specialist runs as its own graph, with its own memory and approvals, and * returns its answer as the tool result. */ export declare function agentAsTool(options: { agent: AgentGraph; name: string; description: string; /** Threads the specialist's runs, so its work is resumable too. Defaults to a fresh thread. */ threadId?: (goal: string) => string; }): ToolDefinition; export type { NodeContext };