Skip to content
Effect 4.0 is here. One ecosystem. Zero dependencies.

Tool

The Tool module provides functionality for defining and managing tools that language models can call to augment their capabilities.

This module enables creation of both user-defined and provider-defined tools, with full schema validation, type safety, and handler support. Tools allow AI models to perform actions like searching databases, calling APIs, or executing code within your application context.

Example

import { Tool } from "@effect/ai"
import { Schema } from "effect"
// Define a simple calculator tool
const Calculator = Tool.make("Calculator", {
description: "Performs basic arithmetic operations",
parameters: {
operation: Schema.Literal("add", "subtract", "multiply", "divide"),
a: Schema.Number,
b: Schema.Number
},
success: Schema.Number
})
48 exports Since v1.0.0 Source

Annotations

Annotation indicating whether a tool performs destructive operations.

Signature

declare class Destructive extends any {
constructor();
}

Example

import { Tool } from "@effect/ai"
const safeTool = Tool.make("search_database")
.annotate(Tool.Destructive, false)

Annotation indicating whether a tool can be called multiple times safely.

Signature

declare class Idempotent extends any {
constructor();
}

Example

import { Tool } from "@effect/ai"
const idempotentTool = Tool.make("get_current_time")
.annotate(Tool.Idempotent, true)

Annotation indicating whether a tool can handle arbitrary external data.

Signature

declare class OpenWorld extends any {
constructor();
}

Example

import { Tool } from "@effect/ai"
const restrictedTool = Tool.make("internal_operation")
.annotate(Tool.OpenWorld, false)
Since v1.0.0

Annotation indicating whether a tool only reads data without making changes.

Signature

declare class Readonly extends any {
constructor();
}

Example

import { Tool } from "@effect/ai"
const readOnlyTool = Tool.make("get_user_info")
.annotate(Tool.Readonly, true)
Since v1.0.0

Annotation for providing a human-readable title for tools.

Signature

declare class Title extends any {
constructor();
}

Example

import { Tool } from "@effect/ai"
const myTool = Tool.make("calculate_tip")
.annotate(Tool.Title, "Tip Calculator")

Constructors

Creates a Tool from a Schema.TaggedRequest.

This utility function converts Effect's TaggedRequest schemas into Tool definitions, automatically mapping the request parameters, success, and failure schemas.

Signature

declare function fromTaggedRequest<S extends AnyTaggedRequestSchema>(schema: S): FromTaggedRequest<S>

Example

import { Tool } from "@effect/ai"
import { Schema } from "effect"
// Define a tagged request for user operations
class GetUser extends Schema.TaggedRequest<GetUser>()("GetUser", {
success: Schema.Struct({
id: Schema.Number,
name: Schema.String,
email: Schema.String
}),
failure: Schema.Struct({
error: Schema.Literal("UserNotFound", "DatabaseError"),
message: Schema.String
}),
payload: {
userId: Schema.Number
}
}) {}
// Convert to a Tool
const getUserTool = Tool.fromTaggedRequest(GetUser)
Since v1.0.0

Creates a user-defined tool with the specified name and configuration.

This is the primary constructor for creating custom tools that AI models can call. The tool definition includes parameter validation, success/failure schemas, and optional service dependencies.

If a tool accepts no parameters but still needs an explicit empty object schema, use EmptyParams.

Signature

declare function make<Name extends string, Parameters extends Fields | EmptyParams = EmptyParams, Success extends Any = Void, Failure extends All = Never, Mode extends FailureMode | undefined = undefined, Dependencies extends Array<Tag<any, any>> = []>(name: Name, options?: {
readonly dependencies?: Dependencies;
readonly description?: string;
readonly failure?: Failure;
readonly failureMode?: Mode;
readonly parameters?: Parameters;
readonly success?: Success;
}): Tool<Name, {
readonly failure: Failure;
readonly failureMode: Mode extends undefined ? "error" : Mode;
readonly parameters: Parameters extends EmptyParams ? EmptyParams : Parameters extends Fields ? Struct<Parameters> : never;
readonly success: Success;
}, Identifier<Dependencies[number]>>

Example

import { Tool } from "@effect/ai"
import { Schema } from "effect"
// Simple tool with no parameters
const GetCurrentTime = Tool.make("GetCurrentTime", {
description: "Returns the current timestamp",
success: Schema.Number
})

Creates a provider-defined tool which leverages functionality built into a large language model provider (e.g. web search, code execution).

These tools are executed by the large language model provider rather than by your application. However, they can optionally require custom handlers implemented in your application to process provider generated results.

Signature

declare function providerDefined<Name extends string, Args extends Fields = {}, Parameters extends Fields | EmptyParams = EmptyParams, Success extends Any = Void, Failure extends All = Never, RequiresHandler extends boolean = false>(options: {
readonly args: Args;
readonly failure?: Failure;
readonly id: `${string}.${string}`;
readonly parameters?: Parameters;
readonly providerName: string;
readonly requiresHandler?: RequiresHandler;
readonly success?: Success;
readonly toolkitName: Name;
}): <Mode extends FailureMode | undefined = undefined>(args: RequiresHandler extends true ? Simplify<View<Args, "Encoded", EncodedOptionalKeys<Args>, EncodedMutableKeys<Args>> & {
readonly failureMode?: Mode;
}> : Simplify<View<Args, "Encoded", EncodedOptionalKeys<Args>, EncodedMutableKeys<Args>>>) => ProviderDefined<Name, {
readonly args: Struct<Args>;
readonly failure: Failure;
readonly failureMode: Mode extends undefined ? "error" : Mode;
readonly parameters: Parameters extends EmptyParams ? EmptyParams : Parameters extends Fields ? Struct<Parameters> : never;
readonly success: Success;
}, RequiresHandler>

Example

import { Tool } from "@effect/ai"
import { Schema } from "effect"
// Web search tool provided by OpenAI
const WebSearch = Tool.providerDefined({
id: "openai.web_search",
toolkitName: "WebSearch",
providerName: "web_search",
args: {
query: Schema.String
},
success: Schema.Struct({
results: Schema.Array(Schema.Struct({
title: Schema.String,
url: Schema.String,
content: Schema.String
}))
})
})

Guards

Type guard to check if a value is a provider-defined tool.

Signature

declare function isProviderDefined(u: unknown): u is ProviderDefined<string, any, false>

Example

import { Tool } from "@effect/ai"
import { Schema } from "effect"
const UserDefinedTool = Tool.make("Calculator", {
description: "Performs basic arithmetic operations",
parameters: {
operation: Schema.Literal("add", "subtract", "multiply", "divide"),
a: Schema.Number,
b: Schema.Number
},
success: Schema.Number
})
const ProviderDefinedTool = Tool.providerDefined({
id: "openai.web_search",
toolkitName: "WebSearch",
providerName: "web_search",
args: {
query: Schema.String
},
success: Schema.Struct({
results: Schema.Array(Schema.Struct({
title: Schema.String,
url: Schema.String,
snippet: Schema.String
}))
})
})
console.log(Tool.isUserDefined(UserDefinedTool)) // false
console.log(Tool.isUserDefined(ProviderDefinedTool)) // true

Type guard to check if a value is a user-defined tool.

Signature

declare function isUserDefined(u: unknown): u is Tool<string, any, any>

Example

import { Tool } from "@effect/ai"
import { Schema } from "effect"
const UserDefinedTool = Tool.make("Calculator", {
description: "Performs basic arithmetic operations",
parameters: {
operation: Schema.Literal("add", "subtract", "multiply", "divide"),
a: Schema.Number,
b: Schema.Number
},
success: Schema.Number
})
const ProviderDefinedTool = Tool.providerDefined({
id: "openai.web_search",
toolkitName: "WebSearch",
providerName: "web_search",
args: {
query: Schema.String
},
success: Schema.Struct({
results: Schema.Array(Schema.Struct({
title: Schema.String,
url: Schema.String,
snippet: Schema.String
}))
})
})
console.log(Tool.isUserDefined(UserDefinedTool)) // true
console.log(Tool.isUserDefined(ProviderDefinedTool)) // false

Models

Since v1.0.0

The strategy used for handling errors returned from tool call handler execution.

If set to "error" (the default), errors that occur during tool call handler execution will be returned in the error channel of the calling effect.

If set to "return", errors that occur during tool call handler execution will be captured and returned as part of the tool call result.

Signature

type FailureMode = "error" | "return"

Handler

interface
Since v1.0.0

Represents an Tool that has been implemented within the application.

Signature

interface Handler<Name extends string> {
readonly _: typeof _;
readonly context: Context<never>;
readonly handler: (params: any) => Effect<any, any>;
readonly name: Name;
}

HandlerResult

interface
Since v1.0.0

Represents the result of calling the handler for a particular Tool.

Signature

interface HandlerResult<Tool extends Any> {
readonly encodedResult: unknown;
readonly isFailure: boolean;
readonly result: Result<Tool>;
}
Since v1.0.0

A provider-defined tool is a tool which is built into a large language model provider (e.g. web search, code execution).

These tools are executed by the large language model provider rather than by your application. However, they can optionally require custom handlers implemented in your application to process provider generated results.

Signature

interface ProviderDefined<Name extends string, Config extends {
readonly args: AnyStructSchema;
readonly failure: Schema.Schema.All;
readonly failureMode: FailureMode;
readonly parameters: AnyParametersSchema;
readonly success: Schema.Schema.Any;
} = {
readonly args: Schema.Struct<{}>;
readonly failure: typeof Schema.Never;
readonly failureMode: "error";
readonly parameters: EmptyParams;
readonly success: typeof Schema.Void;
}, RequiresHandler extends boolean = false> extends Tool<Name, {
readonly failure: Config["failure"];
readonly failureMode: Config["failureMode"];
readonly parameters: Config["parameters"];
readonly success: Config["success"];
}>, ProviderDefinedProto {
readonly args: Config["args"]["Encoded"];
readonly argsSchema: Config["args"];
readonly providerName: string;
readonly requiresHandler: RequiresHandler;
}

Example

import { Tool } from "@effect/ai"
import { Schema } from "effect"
// Define a web search tool provided by OpenAI
const WebSearch = Tool.providerDefined({
id: "openai.web_search",
toolkitName: "WebSearch",
providerName: "web_search",
args: {
query: Schema.String
},
success: Schema.Struct({
results: Schema.Array(Schema.Struct({
title: Schema.String,
url: Schema.String,
snippet: Schema.String
}))
})
})

Tool

interface
Since v1.0.0

A user-defined tool that language models can call to perform actions.

Tools represent actionable capabilities that large language models can invoke to extend their functionality beyond text generation. Each tool has a defined schema for parameters, results, and failures.

Signature

interface Tool<Name extends string, Config extends {
readonly failure: Schema.Schema.All;
readonly failureMode: FailureMode;
readonly parameters: AnyParametersSchema;
readonly success: Schema.Schema.Any;
}, Requirements = never> extends Variance<Requirements> {
readonly annotations: Context<never>;
readonly description?: string;
readonly failureMode: FailureMode;
readonly failureSchema: Config["failure"];
readonly id: string;
readonly name: Name;
readonly parametersSchema: Config["parameters"];
readonly successSchema: Config["success"];
addDependency<Identifier, Service>(tag: Tag<Identifier, Service>): Tool<Name, Config, Requirements | Identifier>;
annotate<I, S>(tag: Tag<I, S>, value: S): Tool<Name, Config, Requirements>;
annotateContext<I>(context: Context<I>): Tool<Name, Config, Requirements>;
setFailure<FailureSchema extends Any>(schema: FailureSchema): Tool<Name, {
readonly failure: FailureSchema;
readonly failureMode: Config["failureMode"];
readonly parameters: Config["parameters"];
readonly success: Config["success"];
}, Requirements>;
setParameters<ParametersSchema extends Fields | AnyParametersSchema>(schema: ParametersSchema): Tool<Name, {
readonly failure: Config["failure"];
readonly failureMode: Config["failureMode"];
readonly parameters: ParametersSchema extends Fields ? Struct<ParametersSchema> : ParametersSchema;
readonly success: Config["success"];
}, Requirements>;
setSuccess<SuccessSchema extends Any>(schema: SuccessSchema): Tool<Name, {
readonly failure: Config["failure"];
readonly failureMode: Config["failureMode"];
readonly parameters: Config["parameters"];
readonly success: SuccessSchema;
}, Requirements>;
}

Example

import { Tool } from "@effect/ai"
import { Schema } from "effect"
// Create a weather lookup tool
const GetWeather = Tool.make("GetWeather", {
description: "Get current weather for a location",
parameters: {
location: Schema.String,
units: Schema.Literal("celsius", "fahrenheit")
},
success: Schema.Struct({
temperature: Schema.Number,
condition: Schema.String,
humidity: Schema.Number
})
})

Other

Since v1.0.0

Schemas

Schema for tools that accept no parameters.

When to use

Use when you need an explicit no-parameter parameters schema for a tool.

Details

This is Schema.Record({ key: Schema.String, value: Schema.Never }), representing an empty object parameter shape with no additional properties.

See

  • make for the tool constructor that defaults omitted parameters to this schema

Signature

declare const EmptyParams: EmptyParams

EmptyParams

interface
Since v1.0.0

Type of the EmptyParams schema used for tools with no parameters.

Details

It is a record schema with string keys and never values, so the generated parameter schema accepts an empty object shape with no properties.

Signature

interface EmptyParams extends Record$<String, Never> {}

Type Ids

Unique identifier for provider-defined tools.

Signature

declare const ProviderDefinedTypeId: "~@effect/ai/Tool/ProviderDefined"

Type-level representation of the provider-defined tool identifier.

Signature

type ProviderDefinedTypeId = typeof ProviderDefinedTypeId
Since v1.0.0

Unique identifier for user-defined tools.

Signature

declare const TypeId: "~@effect/ai/Tool"
Since v1.0.0

Type-level representation of the user-defined tool identifier.

Signature

type TypeId = typeof TypeId

Utilities

Extracts the description from a tool's metadata.

Returns the tool's description if explicitly set, otherwise attempts to extract it from the parameter schema's AST annotations.

Signature

declare function getDescription<Name extends string, Config extends {
readonly failure: All;
readonly failureMode: FailureMode;
readonly parameters: AnyParametersSchema;
readonly success: Any;
}>(tool: Tool<Name, Config>): string | undefined

Example

import { Tool } from "@effect/ai"
const myTool = Tool.make("example", {
description: "This is an example tool"
})
const description = Tool.getDescription(myTool)
console.log(description) // "This is an example tool"

Signature

declare function getDescriptionFromSchemaAst(ast: AST): string | undefined

Generates a JSON Schema for a tool.

This function creates a JSON Schema representation that can be used by large language models to indicate the structure and type of the parameters that a given tool call should receive.

Signature

declare function getJsonSchema<Name extends string, Config extends {
readonly failure: All;
readonly failureMode: FailureMode;
readonly parameters: AnyParametersSchema;
readonly success: Any;
}>(tool: Tool<Name, Config>): JsonSchema7

Example

import { Tool } from "@effect/ai"
import { Schema } from "effect"
const weatherTool = Tool.make("get_weather", {
parameters: {
location: Schema.String,
units: Schema.optional(Schema.Literal("celsius", "fahrenheit"))
}
})
const jsonSchema = Tool.getJsonSchema(weatherTool)
console.log(jsonSchema)
// {
// type: "object",
// properties: {
// location: { type: "string" },
// units: { type: "string", enum: ["celsius", "fahrenheit"] }
// },
// required: ["location"]
// }

Signature

declare function getJsonSchemaFromSchemaAst(ast: AST): JsonSchema7

Unsafe: This function will throw an error if an insecure property is found in the parsed JSON or if the provided JSON text is not parseable.

Signature

declare function unsafeSecureJsonParse(text: string): unknown

Utility Types

Any

interface
Since v1.0.0

A type which represents any Tool.

Signature

interface Any extends Pipeable {
readonly "~@effect/ai/Tool": {
readonly _Requirements: Covariant<any>;
};
readonly annotations: Context<never>;
readonly description?: string;
readonly failureMode: FailureMode;
readonly failureSchema: All;
readonly id: string;
readonly name: string;
readonly parametersSchema: AnyParametersSchema;
readonly successSchema: Any;
}

A type which represents any valid parameters schema.

Signature

type AnyParametersSchema = AnyStructSchema | EmptyParams
Since v1.0.0

A type which represents any provider-defined Tool.

Signature

interface AnyProviderDefined extends Any {
readonly args: any;
readonly argsSchema: AnyStructSchema;
readonly decodeResult: (result: unknown) => Effect<any, AiError>;
readonly providerName: string;
readonly requiresHandler: boolean;
}
Since v1.0.0

Signature

interface AnyStructSchema extends Pipeable {
[key: number]: any;
readonly annotations: any;
readonly ast: AST;
readonly Context: any;
readonly Encoded: any;
readonly fields: Fields;
readonly make: any;
readonly Type: any;
}
Since v1.0.0

Signature

interface AnyTaggedRequestSchema extends AnyStructSchema {
[key: number]: any;
readonly _tag: string;
readonly failure: All;
readonly success: Any;
}
Since v1.0.0

A utility type to extract the type of the tool call result when it fails.

Signature

type Failure<T> = T extends Tool<infer _Name, infer _Config, infer _Requirements> ? Schema.Schema.Type<_Config["failure"]> : never
Since v1.0.0

A utility type to extract the encoded type of the tool call result when it fails.

Signature

type FailureEncoded<T> = T extends Tool<infer _Name, infer _Config, infer _Requirements> ? Schema.Schema.Encoded<_Config["failure"]> : never
Since v1.0.0

A utility type to convert a Schema.TaggedRequest into an Tool.

Signature

interface FromTaggedRequest<S extends AnyTaggedRequestSchema> extends Tool<S["_tag"], {
readonly failure: S["failure"];
readonly failureMode: "error";
readonly parameters: S;
readonly success: S["success"];
}> {}
Since v1.0.0

A utility type which represents the possible errors that can be raised by a tool call's handler.

Signature

type HandlerError<T> = T extends Tool<infer _Name, infer _Config, infer _Requirements> ? _Config["failureMode"] extends "error" ? _Config["failure"]["Type"] : never : never
Since v1.0.0

A utility type to create a union of Handler types for all tools in a record.

Signature

type HandlersFor<Tools extends Record<string, Any>> = { [Name in keyof Tools]: RequiresHandler<Tools[Name]> extends true ? Handler<Tools[Name]["name"]> : never }[keyof Tools]

Name

type
Since v1.0.0

A utility type to extract the Name type from an Tool.

Signature

type Name<T> = T extends Tool<infer _Name, infer _Config, infer _Requirements> ? _Name : never
Since v1.0.0

A utility type to extract the type of the tool call parameters.

Signature

type Parameters<T> = T extends Tool<infer _Name, infer _Config, infer _Requirements> ? Schema.Schema.Type<_Config["parameters"]> : never

A utility type to extract the encoded type of the tool call parameters.

Signature

type ParametersEncoded<T> = T extends Tool<infer _Name, infer _Config, infer _Requirements> ? Schema.Schema.Encoded<_Config["parameters"]> : never

A utility type to extract the schema for the parameters which an Tool must be called with.

Signature

type ParametersSchema<T> = T extends Tool<infer _Name, infer _Config, infer _Requirements> ? _Config["parameters"] : never
Since v1.0.0

A utility type to extract the requirements of an Tool.

Signature

type Requirements<T> = T extends Tool<infer _Name, infer _Config, infer _Requirements> ? _Config["parameters"]["Context"] | _Config["success"]["Context"] | _Config["failure"]["Context"] | _Requirements : never
Since v1.0.0

A utility type to determine if the specified tool requires a user-defined handler to be implemented.

Signature

type RequiresHandler<Tool extends Any> = Tool extends ProviderDefined<infer _Name, infer _Config, infer _RequiresHandler> ? _RequiresHandler : true
Since v1.0.0

A utility type to extract the type of the tool call result whether it succeeds or fails.

Signature

type Result<T> = T extends Tool<infer _Name, infer _Config, infer _Requirements> ? Success<T> | Failure<T> : never
Since v1.0.0

A utility type to extract the encoded type of the tool call result whether it succeeds or fails.

Signature

type ResultEncoded<T> = T extends Tool<infer _Name, infer _Config, infer _Requirements> ? SuccessEncoded<T> | FailureEncoded<T> : never
Since v1.0.0

A utility type to extract the type of the tool call result when it succeeds.

Signature

type Success<T> = T extends Tool<infer _Name, infer _Config, infer _Requirements> ? Schema.Schema.Type<_Config["success"]> : never
Since v1.0.0

A utility type to extract the encoded type of the tool call result when it succeeds.

Signature

type SuccessEncoded<T> = T extends Tool<infer _Name, infer _Config, infer _Requirements> ? Schema.Schema.Encoded<_Config["success"]> : never
Since v1.0.0

A utility type to extract the schema for the return type of a tool call when the tool call succeeds.

Signature

type SuccessSchema<T> = T extends Tool<infer _Name, infer _Config, infer _Requirements> ? _Config["success"] : never