/** * Tool types — Agent's tool-call contract. * * Pattern: Strategy (GoF) — each Tool is a strategy for "how to execute * this named operation given these args". * Role: Consumer-facing shape. Agent.tool(...) accepts these. * Emits: N/A (types only). */ import type { LLMToolSchema } from '../adapters/types.js'; import type { Credential, CredentialNeed, CredentialProvider } from '../identity/types.js'; import type { CheckInDemand } from './checkin.js'; /** * One executable tool the Agent can call. * * - `schema` is what the LLM sees (name, description, JSON schema). * - `execute` runs when the LLM requests this tool with the given args. * Returns anything JSON-serializable; the framework forwards it back * to the LLM as the tool result. */ export interface Tool, TResult = unknown> { readonly schema: LLMToolSchema; /** Declare-and-push: a credential this tool needs. The framework resolves it * BEFORE invoking and injects `ctx.credential`; it is NOT in `schema`, so the * LLM never sees or fills it. */ readonly needs?: CredentialNeed; /** * Declarative demand for a human check-in BEFORE this tool runs — consent * for a consequential action, with an evidence pack riding the ask. * `'always'` trips on every call; a `(args, ctx) => boolean` predicate trips * selectively (e.g. only refunds over $1000). When it trips the tool-dispatch * loop pauses BEFORE execute and surfaces a `CheckInRequest`; the human * answers with `checkInApproved` / `checkInDeclined`. Omitted → byte-identical * behavior (no gate, no events, no pause). See `.checkIn()` on the Agent * builder to configure the evidence pack. Ordered AFTER the permission gate * and arg-validation, BEFORE credential resolution. * * Non-generic here (a `Tool` widens into `Tool[]` registries); `defineTool` * exposes a predicate typed to the tool's args at the CALL site. */ readonly checkIn?: CheckInDemand; execute(args: TArgs, ctx: ToolExecutionContext): Promise | TResult; } /** Runtime context passed to tool.execute(). */ export interface ToolExecutionContext { /** Unique id of THIS tool invocation (matches stream.tool_start.toolCallId). */ readonly toolCallId: string; /** Current iteration number of the ReAct loop. */ readonly iteration: number; /** Abort signal propagated from run({ env: { signal } }). */ readonly signal?: AbortSignal; /** * The bound credential provider — the PULL escape hatch for dynamic needs. * Always present: when none is attached it's a fail-closed provider that * THROWS, so it never silently no-ops via optional chaining. Prefer the * declarative `needs` + `ctx.credential` for the common case. */ readonly credentials: CredentialProvider; /** True when a real provider is attached. Branch on this for intentional * degraded (no-credential) mode instead of relying on `undefined`. */ readonly hasCredentials: boolean; /** The credential resolved for this tool's declared `needs` (declare-and-push). * Present only when the tool declared a need and it resolved successfully. */ readonly credential?: Credential; } /** * Internal: registry entry keyed by tool name. * Consumer never sees this shape. */ export interface ToolRegistryEntry { readonly name: string; readonly tool: Tool; } /** * Convenience input for `defineTool` — flatter than `Tool` itself. * Consumers describe the tool inline; the helper assembles `schema`. * * `inputSchema` is a JSON Schema object (the same one the LLM will * see). For tools that take no arguments, pass `{ type: 'object', * properties: {} }` or omit and we'll default to that. */ export interface DefineToolOptions { readonly name: string; readonly description: string; readonly inputSchema?: Readonly>; /** Declare a credential this tool needs (declare-and-push). Resolved by the * framework before `execute` and injected as `ctx.credential`. */ readonly needs?: CredentialNeed; /** Demand a human check-in before this tool runs (see {@link Tool.checkIn}). * `'always'` or a `(args, ctx) => boolean` predicate. */ readonly checkIn?: CheckInDemand; execute(args: TArgs, ctx: ToolExecutionContext): Promise | TResult; } /** * STRICT validation — throws a clear, actionable error if a tool name can't be * sent to an LLM. Exposed for consumers who want to fail hard (e.g. in a build * step or a test). The library itself only WARNS (see `warnIfInvalidToolName`), * because a name is provider-specific: a mock or a name-sanitizing custom provider * may accept dotted/namespaced names that OpenAI/Anthropic reject. */ export declare function assertValidToolName(name: unknown): asserts name is string; /** * DEV-MODE heads-up (never throws): warns once-per-call if a tool name will be * rejected by OpenAI/Anthropic. Production and non-dev runs pay nothing. This is * the library's default guard (Convention: dev diagnostics warn, they don't throw) * — keeping mock/custom-provider + namespaced-name setups working. Reach for * `assertValidToolName` when you want a hard failure. */ export declare function warnIfInvalidToolName(name: unknown): void; export declare function defineTool, TResult = unknown>(options: DefineToolOptions): Tool;