or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

agents.mdchat-models.mdhub.mdindex.mdmiddleware.mdstorage.mdtools.md
tile.json

tools.mddocs/

Tools

Type-safe tool creation with Zod schema validation (re-exported from @langchain/core/tools).

tool Function

function tool<T extends InteropZodType = InteropZodType>(
  func: (input: InferInteropZodInput<T>, config?: RunnableConfig) => any,
  config: {
    name: string;
    description: string;
    schema: T;
  }
): DynamicStructuredTool<T>;

Examples:

import { tool } from "langchain";
import { z } from "zod";

// Simple tool
const searchTool = tool(
  ({ query }) => `Results for: ${query}`,
  {
    name: "search",
    description: "Search for information",
    schema: z.object({
      query: z.string().describe("The search query"),
    }),
  }
);

// Multiple parameters
const calculatorTool = tool(
  ({ operation, x, y }) => {
    switch (operation) {
      case "add": return x + y;
      case "subtract": return x - y;
      case "multiply": return x * y;
      case "divide": return x / y;
      default: throw new Error(`Unknown: ${operation}`);
    }
  },
  {
    name: "calculator",
    description: "Perform arithmetic",
    schema: z.object({
      operation: z.enum(["add", "subtract", "multiply", "divide"]),
      x: z.number(),
      y: z.number(),
    }),
  }
);

// Async tool
const weatherTool = tool(
  async ({ location }) => {
    const response = await fetch(`https://api.weather.com/${location}`);
    return await response.json();
  },
  {
    name: "get_weather",
    description: "Get weather for a location",
    schema: z.object({
      location: z.string().describe("City or ZIP"),
    }),
  }
);

// With RunnableConfig
const databaseTool = tool(
  async ({ query }, config) => {
    const signal = config?.signal;
    const result = await executeQuery(query, { signal });
    return result;
  },
  {
    name: "query_database",
    description: "Execute database query",
    schema: z.object({
      query: z.string().describe("SQL query"),
    }),
  }
);

DynamicStructuredTool

class DynamicStructuredTool<T extends InteropZodType = InteropZodType> extends StructuredTool<T> {
  name: string;
  description: string;
  schema: T;

  invoke(input: InferInteropZodInput<T>, config?: RunnableConfig): Promise<any>;
  stream(input: InferInteropZodInput<T>, config?: RunnableConfig): Promise<IterableReadableStream<any>>;
}

StructuredTool

abstract class StructuredTool<T extends InteropZodType = InteropZodType> extends Tool {
  schema: T;

  abstract _call(
    arg: InferInteropZodInput<T>,
    runManager?: CallbackManagerForToolRun
  ): Promise<string>;

  invoke(input: InferInteropZodInput<T>, config?: RunnableConfig): Promise<string>;
}

Custom Tool Example:

import { StructuredTool } from "langchain";
import { z } from "zod";

class CustomSearchTool extends StructuredTool {
  name = "custom_search";
  description = "Custom search implementation";
  schema = z.object({
    query: z.string(),
    maxResults: z.number().default(10),
  });

  async _call({ query, maxResults }) {
    const results = await this.performSearch(query, maxResults);
    return JSON.stringify(results);
  }

  private async performSearch(query: string, max: number) {
    // Implementation
    return [];
  }
}

const customTool = new CustomSearchTool();

Tool

abstract class Tool {
  name: string;
  description: string;
  returnDirect?: boolean;

  abstract _call(arg: string, runManager?: CallbackManagerForToolRun): Promise<string>;

  invoke(input: string, config?: RunnableConfig): Promise<string>;
  call(arg: string, callbacks?: Callbacks): Promise<string>;
}

DynamicTool

class DynamicTool extends Tool {
  name: string;
  description: string;

  constructor(config: {
    name: string;
    description: string;
    func: (input: string, runManager?: CallbackManagerForToolRun) => Promise<string>;
    returnDirect?: boolean;
  });

  _call(input: string, runManager?: CallbackManagerForToolRun): Promise<string>;
}

Example:

import { DynamicTool } from "langchain";

const simpleTool = new DynamicTool({
  name: "echo",
  description: "Echo input",
  func: async (input) => `You said: ${input}`,
});

Configuration Types

interface RunnableConfig {
  signal?: AbortSignal;
  callbacks?: Callbacks;
  tags?: string[];
  metadata?: Record<string, any>;
  runName?: string;
}

interface CallbackManagerForToolRun {
  handleToolStart?(tool: Tool, input: string): void;
  handleToolEnd?(output: string): void;
  handleToolError?(error: Error): void;
}

type ServerTool = StructuredTool | DynamicStructuredTool | Tool | DynamicTool;

interface ClientTool {
  name: string;
  description: string;
  schema: InteropZodType;
}

Common Patterns

Error Handling:

const safeTool = tool(
  async ({ url }) => {
    try {
      const response = await fetch(url, { timeout: 5000 });
      if (!response.ok) return `Error: HTTP ${response.status}`;
      return await response.text();
    } catch (error) {
      return `Error: ${error.message}`;
    }
  },
  {
    name: "fetch_url",
    description: "Fetch URL content",
    schema: z.object({ url: z.string().url() }),
  }
);

Validation:

const validatedTool = tool(
  async ({ email, age }) => {
    if (age < 18) return "Error: Must be 18 or older";
    return `Registered: ${email}`;
  },
  {
    name: "register_user",
    description: "Register user",
    schema: z.object({
      email: z.string().email(),
      age: z.number().min(0).max(150),
      name: z.string().min(1),
    }),
  }
);

Stateful Tool:

class CounterTool {
  private count = 0;

  getTool() {
    return tool(
      ({ increment }) => {
        this.count += increment;
        return `Count: ${this.count}`;
      },
      {
        name: "counter",
        description: "Increment counter",
        schema: z.object({ increment: z.number() }),
      }
    );
  }
}

const counter = new CounterTool();
const counterTool = counter.getTool();

Return Direct:

class DirectAnswerTool extends StructuredTool {
  name = "direct_answer";
  description = "Get answer without further processing";
  returnDirect = true;
  schema = z.object({ query: z.string() });

  async _call({ query }) {
    return await getDefinitiveAnswer(query);
  }
}

Tool Composition:

const fetchAndParseTool = tool(
  async ({ url }) => {
    const content = await fetchTool.invoke({ url });
    const parsed = await parseTool.invoke({ content });
    return parsed;
  },
  {
    name: "fetch_and_parse",
    description: "Fetch and parse URL",
    schema: z.object({ url: z.string().url() }),
  }
);