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.