tool2agent interface for AI SDK.
pnpm install @tool2agent/ai
import { tool2agent, toolBuilder } from '@tool2agent/ai';
tool2agent is a protocol that enables LLM agents to navigate complex business constraints through trial and error by communicating rich and structured feedback data from tools.
This package implements tool2agent bindings for AI SDK in two forms:
toolBuilder() - a type-safe mini-framework for creating interactive LLM tools with rich feedback.tool2agent() - a tool2agent-enabled replacement for AI SDK tool() that gives full manual control over validation logic and generates a protocol output schema.toolBuilder() is the main value proposition of tool2agent so far. It allows you to semi-declaratively define tool feedback flows.
toolBuilder() accepts a tool input schema with some of its fields marked as dynamic parameters.
At runtime, dynamic parameters are made optional, and the LLM can fill them as it "sees" fit.
Every dynamic parameter has a validation function attached that is called regardless of whether the parameter has been passed. This allows the tool to provide feedback at any time. For example, feedback can include a list of value suggestions that may depend on other parameter values.
These parameter inter-dependencies are what make toolBuilder() a neat instrument for building conversational LLM workflows, because they allow you to specify the ordering of parameters to be filled, which guides the assistant towards asking the user the right questions.
Check out a complete usage example
tool2agent() functionThis interface wires together tool2agent types and AI SDK by translating tool2agent tool parameters to AI SDK tool() parameters.
import type { Tool } from 'ai';
import type { ToolCallResult } from '@tool2agent/types';
// This definition is simplified for illustrative purposes
type Tool2Agent<InputType, OutputType> = Tool<
InputType,
// output is always a `ToolCallResult` that can be either accepted (with output value),
// or rejected
ToolCallResult<InputType, OutputType>
>;
The tool2agent() function allows you to define AI SDK LLM tools using an execute() method that handles both validation and execution, returning structured feedback via ToolCallResult.
tool2agent()execute() accepts a tool payload and returns a ToolCallResult that can either succeed (ok: true) with the output value, or fail (ok: false) with structured feedback info.// Parameters of tool2agent() function:
import type { ToolExecutionOptions } from '@ai-sdk/provider-utils';
function tool2agent<
InputSchema extends z.ZodType<any>,
OutputSchema extends z.ZodType<any>,
>(params: {
inputSchema: InputSchema;
outputSchema: OutputSchema;
execute: (
input: z.infer<InputSchema>,
options: ToolExecutionOptions<unknown>,
) => Promise<ToolCallResult<z.infer<InputSchema>, z.infer<OutputSchema>>>;
// other parameters omitted
}): Tool2Agent<z.infer<InputSchema>, z.infer<OutputSchema>>;
// ^ `Tool2Agent` is compatible with AI SDK `Tool`
tool() and tool2agent()tool() does nothing and exists only for type checking, while tool2agent() builds the tool's execute() methodtool() passes exceptions through, while tool2agent() catches exceptions and returns them formatted nicely to the LLM as tool2agent problemstool2agent() mandates input and output schemas. Use never / z.never() for output schema if it is not needed.tool2agent() supports custom toModelOutput to control how results are sent to the model.createMiddleware() allows you to compose transformations around tools, enabling reusable logic for validation, logging, or input/output transformation. Middleware can be piped together using the .pipe() method.
export type Middleware<
InputType,
OutputType,
NewInputType = InputType,
NewOutputType = OutputType,
> = {
applyTo: (tool: Tool2Agent<InputType, OutputType>) => Tool2Agent<NewInputType, NewOutputType>;
pipe<FinalInputType, FinalOutputType>(
next: Middleware<NewInputType, NewOutputType, FinalInputType, FinalOutputType>,
): Middleware<InputType, OutputType, FinalInputType, FinalOutputType>;
};
toolBuilder() for building conversational agents with logical dependencies between parameters and complex validation logic