Codemation Docs
How-To Guides

Create Custom Agent Tool

Add a tool that an AIAgent node can call during workflow execution.

… stars

This guide shows how to build a standalone custom tool that an AIAgent can call when the model needs external capability or fresh data.

If you already have a runnable node and just want to expose it to the agent, use Use a Node as an Agent Tool instead. That path usually avoids writing a second adapter class.

For small app-local helpers without a separate @tool() class, use callableTool(...) from @codemation/core (Zod inputSchema / outputSchema, execute, optional credentialRequirements). The legacy CallableToolFactory.callableTool(...) entry point remains equivalent. See AI Agent.

Use this guide when

Reach for a custom agent tool when:

  • the model needs deterministic computation
  • the model needs fresh or external data
  • you want the model to call an internal API instead of guessing
  • the capability does not naturally belong in a reusable workflow node

Example scenario

Imagine you want an agent that can search your internal documentation before it answers.

The pattern is:

  1. define a tool config
  2. implement the tool with input and output schemas
  3. attach the tool config to an AIAgent

Step 1: define the tool config

import type { ToolConfig, TypeToken } from "@codemation/core";

export class SearchDocsToolConfig implements ToolConfig {
  readonly type: TypeToken<unknown> = SearchDocsTool;

  constructor(
    public readonly name: string = "search_docs",
    public readonly description: string = "Search product documentation for the current task.",
  ) {}
}

Step 2: implement the tool

import type { Tool, ToolExecuteArgs } from "@codemation/core";
import { tool } from "@codemation/core";
import { z } from "zod";

const searchToolInputSchema = z.object({
  query: z.string(),
});

const searchToolOutputSchema = z.object({
  results: z.array(
    z.object({
      title: z.string(),
      url: z.string(),
    }),
  ),
});

@tool()
export class SearchDocsTool implements Tool<
  SearchDocsToolConfig,
  typeof searchToolInputSchema,
  typeof searchToolOutputSchema
> {
  readonly defaultDescription = "Search documentation and return the best matching pages.";
  readonly inputSchema = searchToolInputSchema;
  readonly outputSchema = searchToolOutputSchema;

  async execute(
    args: ToolExecuteArgs<SearchDocsToolConfig, z.input<typeof searchToolInputSchema>>,
  ): Promise<z.output<typeof searchToolOutputSchema>> {
    const query = args.input.query.trim();

    return {
      results: [
        {
          title: `Result for ${query}`,
          url: "https://example.test/docs",
        },
      ],
    };
  }
}

Step 3: attach the tool to an AIAgent

new AIAgent({
  name: "Answer product questions",
  messages: [
    {
      role: "system",
      content: "Use the search_docs tool when you need product documentation context, then answer clearly.",
    },
    { role: "user", content: ({ item }) => JSON.stringify(item.json) },
  ],
  chatModel: new OpenAIChatModelConfig("OpenAI", "gpt-4o-mini"),
  tools: [new SearchDocsToolConfig()],
});

Why tools are useful

Tools let the model stay focused on reasoning while deterministic code handles:

  • lookups
  • calculations
  • external API access
  • capability boundaries that should not live inside a prompt
  1. AI Agent node
  2. Use a node as an agent tool
  3. Create a custom credential

On this page