DocsCustom Tools Deep Dive

Custom Tools Deep Dive

Extend your agent's capabilities by connecting it to any API, database, or function.

The Anatomy of a Tool#

A Tool is the bridge between the LLM and the real world. It consists of a definition (Name, Description, Schema) and an execution function.

tool-interface.ts
interface Tool<T = any> {
  name: string          // Unique identifier (e.g., "search_users")
  description: string   // Instructions for the LLM on WHEN to use this
  schema: ZodSchema<T>  // Validation for the arguments
  execute: (args: T) => Promise<string> // The implementation
}

Building a Robust Tool#

Let's build a tool that searches a product database. We'll use Zod to ensure the agent provides valid search parameters.

Description Matters

The `description` is part of the prompt. Be specific about input formats (e.g., "Dates must be ISO-8601").
product-search.ts
import { Tool } from '@akios/sdk'
import { z } from 'zod'

const searchProducts = new Tool({
  name: 'search_products',
  description: 'Search for products by name, category, or price range. Use this when the user is looking for item recommendations.',
  
  // Zod Schema defines the "Contract"
  schema: z.object({
    query: z.string().optional().describe('The search term (e.g. "wireless headphones")'),
    category: z.enum(['electronics', 'clothing', 'home']).optional(),
    maxPrice: z.number().positive().optional(),
    limit: z.number().min(1).max(20).default(5)
  }),

  execute: async ({ query, category, maxPrice, limit }) => {
    try {
      // 1. Call your internal API / Database
      const results = await db.products.findMany({
        where: {
          name: { contains: query },
          category: category,
          price: { lte: maxPrice }
        },
        take: limit
      })

      // 2. Format the output for the LLM
      // JSON.stringify is usually best for structured data
      if (results.length === 0) {
        return "No products found matching those criteria."
      }
      return JSON.stringify(results)

    } catch (error) {
      // 3. Handle Errors gracefully
      // Return the error message so the Agent knows what went wrong
      return `Error searching products: ${error.message}`
    }
  }
})

Best Practices#

1. Keep Outputs Concise

LLMs have context limits. Don't return a 10MB JSON dump. Filter fields to only what's necessary (e.g., ID, Name, Price).

2. Error Recovery

If an API call fails, don't throw an exception. Return a string like "Error: API timeout". The agent might try again or apologize to the user.