FragolaFragolaAI Agentic SDK
Core Concepts

Tools

Understanding tools and schema validation in Fragola

Overview

Tools allow your agents to perform actions, fetch data, and interact with external systems. Fragola supports multiple schema formats, dynamic tool handlers, and context access.

Creating a Tool

import { tool } from "@fragola-ai/agentic-sdk-core";
import { z } from "zod";

const weatherTool = tool({
  name: "get_weather",
  description: "Get current weather for a location",
  schema: z.object({
    location: z.string().describe("City name or coordinates"),
    unit: z.enum(["celsius", "fahrenheit"]).optional()
  }),
  handler: async (params) => {
    const weather = await fetchWeather(params.location, params.unit);
    return {
      temperature: weather.temp,
      conditions: weather.conditions,
      location: params.location
    };
  }
});

// Add to agent
const agent = fragola.agent({
  name: "Assistant",
  tools: [weatherTool]
});

Schema Formats

Fragola accepts multiple schema formats for tool parameters.

Provides automatic validation and type inference:

const createUserTool = tool({
  name: "create_user",
  description: "Create a new user account",
  schema: z.object({
    email: z.string().email(),
    name: z.string().min(1),
    age: z.number().int().positive().optional(),
    role: z.enum(["admin", "user", "guest"]).default("user")
  }),
  handler: async (params) => {
    // params is fully typed
    const user = await db.createUser(params);
    return user;
  }
});

JSON Schema String

For advanced use cases or manual validation control:

const weatherTool = tool({
  name: "get_weather",
  description: "Get weather information",
  schema: JSON.stringify({
    type: "object",
    properties: {
      location: { type: "string" }
    },
    required: ["location"]
  }),
  handler: async (params: any) => {
    // Manual validation if needed
    if (typeof params.location !== "string") {
      throw new Error("Invalid location parameter");
    }
    return await fetchWeather(params.location);
  }
});

No Schema

For tools that don't require parameters:

const getCurrentTimeTool = tool({
  name: "get_current_time",
  description: "Get the current time",
  handler: async () => {
    return new Date().toISOString();
  }
});

Dynamic Tools

A tool handler can be dynamic, for use cases where the handler depends on too much runtime variables, it allows you to avoid organization overhead by returning an output from anywhere in your codebase. For scenarios where the handler is determined at runtime:

// /src/tools/dynamicTool.ts
const dynamicTool = tool({
  name: "dynamic_action",
  description: "Performs dynamic actions",
  schema: z.object({ action: z.string() }),
  handler: "dynamic"
});

// /src/app.ts
agent.onToolCall(async (params, tool) => {
  if (tool.name === "dynamic_action") {
    const result = await performDynamicAction(params);
    return result;
  }
});

Context Access

Tools can access the agent context to interact with stores, agent state, and other agent capabilities:

If you're unfamiliar with the context concept, read the Introduction to Context.

const contextAwareTool = tool({
  name: "get_user_preference",
  description: "Get user preferences from the store",
  schema: z.object({
    key: z.string()
  }),
  handler: async (params, context) => {
    // Access stores
    const userStore = context.getStore("user");
    const preference = userStore?.get(params.key);
    
    // Access conversation history
    const messages = context.state.messages;
    
    return { preference, messageCount: messages.length };
  }
});

Runtime Tool Management

Add, remove, or update tools dynamically:

// Add tools
agent.context.updateTools((currentTools) => [
  ...currentTools,
  newTool
]);

// Remove tools by name
agent.context.updateTools((currentTools) => 
  currentTools.filter(t => t.name !== "old_tool")
);

// Replace a tool
agent.context.updateTools((currentTools) => 
  currentTools.map(t => t.name === "weather" ? updatedWeatherTool : t)
);