My App

Generic Parameters Reference

Fragola is built from the ground up for strict TypeScript environments. Most core classes in Fragola (Agent, AgentContext) accept up to three generic type parameters to enforce strict type checking across your entire agent configuration.

Agent Generics

The Agent signature looks like this:

class Agent<TMetaData, TGlobalStore, TStore>

TMetaData

Defines the strict shape of custom metadata attached to messages. See Message Metadata Typing for an in-depth guide on how to configure this using DefineMetaData.

TGlobalStore

Defines the expected shape of the global store shared across the Fragola instance. By specifying this, calls to context.instance.store will be strongly typed.

TStore

Defines the expected shape of the agent's local store.

type MyGlobalData = { dbUrl: string };
type MyLocalData = { queryCount: number };

// The agent requires a store matching { queryCount: number } and 
// will expect the global store to have { dbUrl: string }
const agent = fragola.agent<{}, MyGlobalData, MyLocalData>({
    name: "TypedAgent",
    store: createStore({ queryCount: 0 })
});

Tool Parameter & Return Types

Fragola provides deep type integration for Tools, specifically bridging the gap between Zod schemas and function handlers.

Type Inference with Infer<TSchema>

When you define a tool using the tool() helper and provide a Zod schema, Fragola uses a utility type called Infer<TSchema> to automatically derive the TypeScript interface for your handler's arguments.

You never have to define an interface manually if you already wrote a Zod schema.

import { tool } from "@fragola-ai/agent";
import { z } from "zod";

const mySchema = z.object({
    id: z.string(),
    tags: z.array(z.string())
});

const myTool = tool({
    name: "process",
    description: "...",
    schema: mySchema,
    handler: (params) => {
        // params is strictly typed as:
        // { id: string, tags: string[] }
        return params.id;
    }
});

ToolHandlerReturnType

Fragola is highly permissive regarding what a tool handler can return. The internal ToolHandlerReturnType allows you to return:

  • Strings
  • Numbers
  • Booleans
  • Arrays
  • Objects (JSON serializable)
  • Promises resolving to any of the above

If a handler returns a non-string object, Fragola automatically serializes it to a JSON string using JSON.stringify before sending it to the LLM. This prevents OpenAI endpoint crashes.

Typing Hooks & Contexts

When writing reusable Hooks for Fragola, you must decide how strictly to type the agent that the hook receives.

Using AgentAny for Generalized Hooks

If your hook performs general-purpose logic (like logging events, measuring execution time, or interacting with generic tools), you should type the incoming agent as AgentAny.

AgentAny is an exported utility type that strips away the specific generics (TMetaData, TGlobalStore, TStore) so your hook can be applied to any agent.

import { type FragolaHook, type AgentAny } from "@fragola-ai/agent";

const loggerHook: FragolaHook = (agent: AgentAny) => {
    agent.onUserMessage(({ message }) => {
        console.log("Message received!");
        return message;
    });
};

Strictly Typed Hooks

If your hook relies on specific shapes of data—for instance, it needs the agent to have a local store with a cache property—you must explicitly define the generics in the hook's signature.

import type { Agent } from "@fragola-ai/agent";

// We require an agent that has a specific local store shape
type CachingAgent = Agent<any, any, { cache: Map<string, string> }>;

const cacheHook = (agent: CachingAgent) => {
    agent.onBeforeModelInvocation(({ context, config }) => {
        // Typescript knows `context.store.value.cache` is a Map!
        console.log("Cache size:", context.store.value.cache.size);
        return config;
    });
};

// This hook can ONLY be passed to agent.use() if the agent matches the type.

On this page