Hydra AI

V 0.1.0 Coming Soon

These are draft docs for the upcoming 0.1.0 release. Read more about the upcoming release here. Have a question about anything in the docs? Send us a message.

Tools

Tools enable Hydra to interact with your application's data and functionality. They provide a type-safe way to extend the AI's capabilities with custom business logic. Hydra will call these tools and use their outputs to help decide how to respond to a message, what component to show, and what data to fill the component with.

interface HydraTool {
  name: string;
  description: string; // What is this tool for and when should Hydra use it?
  tool: (input: z.infer<ZodTypeAny>) => any; // The function that Hydra will call when using this tool
  inputSchema: ZodTypeAny; // The parameter type that Hydra will use when calling the tool.
}

To make use of tools, we will:

  1. Add tools by defining them and registering them with Hydra
  2. Associate tools with components, so Hydra know which tools to focus on when using a given component

Adding a Tool

//define the function's input schema
const weatherSchema = z.object({
  city: z.string().optional(),
});
 
//define the tool function. This is your own custom function and can perform any logic you want.
const getWeather = async (city?: string) => {
  try {
    const weather = await fetch(`https://api.weatherapi.com/&city=${city}`); //mock weather api
    return weather;
  } catch (error) {
    throw new Error(`Failed to fetch weather for ${city}`);
  }
};
 
//define the tool
const tool: HydraTool = {
  name: "get_weather",
  description: "Fetch current weather information for a specified city",
  tool: getWeather,
  inputSchema: weatherSchema,
};
 
//register the tool
hydraClient.registerTool(tool);

Registering a Tool using React Hooks:

const { registerTool, registerTools } = useHydra();
 
const tool1 = // tool definition
const tool2 = // tool definition
registerTool(tool1); // register a single tool
registerTools([tool1, tool2]); // register multiple tools at once

Associating Tools with Components

Once Hydra has decided on a component to use in response to a message, it will use the registered tools if it has decided that extra external data is needed to fill the component properly. To tell Hydra which tools to consider for a given component, we need to associate the tools with the component. A tool can be associated with multiple components.

During component definition:

If you already have the tool functionality defined when you register your components, you can pass the tool directly to the component definition.

const weatherTool: HydraTool = {
  name: "getForecast",
  description: "Call the weather API to get today's forecast",
  // a function, called with `await fetchForecast("Las Vegas")`
  tool: fetchForecast,
  toolSchema: z
    .function()
    .args(
      z
        .string()
        .describe(
          "The geographic location, such as a city, state, or zip code",
        ),
    ),
};
 
hydraClient.registerComponent({
  name: "WeatherComponent",
  //other component definition fields...
  associatedTools: [weatherTool],
});

Using React Hooks:

If you define your tool functionality sometime after registering your components, you can use the addToolAssociation hook to associate the tool with the component.

const { addToolAssociation } = useHydra();
 
const weatherTool: HydraTool = {
  //tool definition
};
 
addToolAssociation("WeatherComponent", weatherTool); // will fail if there is no registered component with the name 'WeatherComponent'

Tool Definition Examples

Data Operations

Database Tool Example
const dbTools = {
  queryDatabase: {
    description: "Execute a database query",
    inputSchema: z.object({
      table: z.string().describe("Target table name"), 
      fields: z.array(z.string()).describe("Fields to retrieve"), 
      where: z.record(z.unknown()).optional(), 
    }),
  },
};

File Operations

File System Tool Example
const fileTools = {
  readFile: {
    description: "Read file contents",
    inputSchema: z.object({
      path: z.string().describe("File path"), 
      encoding: z.enum(["utf8", "binary"]).default("utf8"), 
    }),
  },
};

API Integration

API Tool Example
const apiTools = {
  fetchData: {
    description: "Fetch data from external API",
    inputSchema: z.object({
      endpoint: z.string().url(), 
      method: z.enum(["GET", "POST"]), 
      body: z.unknown().optional(), 
    }),
  },
};

Best Practices

  1. Type Safety
Type-Safe Tool Definition
// Define strict input types
const inputSchema = z.object({

  id: z.string().uuid(),
  data: z.record(z.unknown()),
}); 
 
// Type-safe implementation
const implementation = async (input: z.infer<typeof inputSchema>) => {

  // TypeScript knows the shape of input
};
  1. Error Handling
Error Handling Example
const robustImplementation = async (input: z.infer<typeof schema>) => {
  try {
    // Tool logic
  } catch (error) {
    throw new Error(`Tool failed: ${error.message}`); 
  }
};
  1. Documentation
Well-Documented Tool
const documentedTool = {
  description: "Comprehensive description of what the tool does", 
  inputSchema: z.object({
    param1: z.string().describe("Detailed description of param1"), 
    param2: z.number().describe("Detailed description of param2"), 
  }),
};

On this page