Build AI Agents Your Way

An event-driven SDK for building AI-first software. Lightweight, extensible, production-ready.

$npm install @fragola-ai/agentic-sdk-core
quickstart.ts
import { Fragola } from "@fragola-ai/agentic-sdk-core";

const fragola = new Fragola({
  apiKey: process.env.OPENAI_API_KEY,
  model: "gpt-4o-mini"
});

const agent = fragola.agent({
  name: "Assistant",
  instructions: "You are a helpful assistant."
});

const state = await agent.userMessage({
  content: "Hello!"
});

Core Primitives

A small set of powerful building blocks for any AI architecture. Scroll to explore each primitive in detail.

agents.ts
const fragola = new Fragola({
  apiKey: process.env.OPENAI_API_KEY,
  model: "gpt-4o-mini"
});

const agent = fragola.agent({
  name: "CustomerSupport",
  description: "Handles customer inquiries",
  instructions: "You are a helpful customer support agent.",
  modelSettings: {
    temperature: 0.7,
    max_tokens: 1000
  },
  stepOptions: {
    maxStep: 10,
    resetStepCountAfterUserMessage: true
  }
});

// Send a message and get the response
const state = await agent.userMessage({
  content: "Hello! What can you help me with?",
  meta: { userId: "user-123" }
});

console.log(state.messages);  // Full conversation history
console.log(state.status);    // "idle" | "generating" | "waiting"
Core Primitive

Agents

Stateful LLM instances that manage conversation history, tool execution, and state updates through a predictable lifecycle.

  • Native OpenAI message types
  • Configurable model settings
  • Step-based execution control
Learn more about Agents
tools.ts
const weatherTool = tool({
  name: "get_weather",
  description: "Get current weather for a location",
  schema: z.object({
    location: z.string().describe("City name"),
    unit: z.enum(["celsius", "fahrenheit"]).optional()
  }),
  handler: async (params, context) => {
    const weather = await fetchWeather(params.location);
    return {
      temperature: weather.temp,
      conditions: weather.conditions,
      location: params.location
    };
  }
});

// Add tools to agent
const agent = fragola.agent({
  name: "Assistant",
  instructions: "Help users with weather info.",
  description: "Weather assistant",
  tools: [weatherTool, dynamicTool]
});
Core Primitive

Tools

Strongly-typed functions with Zod or JSON Schema validation. Give your agents the ability to take actions and fetch data.

  • Zod & JSON Schema support
  • Dynamic tool handlers
  • Context-aware execution
Learn more about Tools
hooks.ts
// Create a custom analytics hook
const analyticsHook = Hook((agent) => {
  let userMessages = 0;
  let aiMessages = 0;

  agent.onUserMessage((message, context) => {
    userMessages++;
    return message;
  });

  agent.onAiMessage((message, isPartial, context) => {
    if (!isPartial) aiMessages++;
    return message;
  });

  agent.onAfterStateUpdate((context) => {
    if (context.state.status === "idle") {
      console.log(`Stats: ${userMessages} user, ${aiMessages} AI`);
    }
  });
});

// Use hook presets along with custom hooks
const agent = fragola.agent({ name: "Assistant", ... })
  .use(fileSystemSave("./conversations"))
  .use(mcpClient({ name: "tools", url: "http://localhost:3001" }))
  .use(guardrail([myGuardrail]))
  .use(analyticsHook); // your custom hook
Core Primitive

Hooks

Reusable, composable behaviors that extend agent capabilities. Package complex logic for sharing across agents and projects.

  • MCP client integration
  • Multi-agent orchestration
  • Guardrails & persistence
Learn more about Hooks
events.ts
// Intercept and transform user messages
agent.onUserMessage((message, context) => {
  const content = typeof message.content === 'string'
    ? message.content.trim()
    : message.content;
  return { ...message, content };
});

// Process AI responses
agent.onAiMessage((message, isPartial, context) => {
  if (isPartial) return message;  // Skip streaming partials
  return {
    ...message,
    content: message.content + '

_Powered by Fragola_'
  };
});

// Wrap tool execution with logging
agent.onToolCall(async (params, tool, context) => {
  console.log('Calling tool:', tool.name, params);
  const result = await tool.handler(params, context);
  console.log('Tool result:', result);
  return result;
});

// Trace model invocations with retries
agent.onModelInvocation(async (callAPI, context) => {
  const start = Date.now();
  try {
    const response = await callAPI();
    console.log('Model took', Date.now() - start, 'ms');
    return response;
  } catch (e) {
    // Implement retry logic
    return await callAPI();
  }
});
Core Primitive

Events

A rich subscription system for observability and control. Hook into every stage of the agent loop.

  • Message interception
  • Tool call wrapping
  • Model invocation tracing
Learn more about Events
stores.ts
// Global store shared across all agents
const globalStore = createStore({ 
  activeTenantId: "tenant-123" 
});

const fragola = new Fragola(
  { apiKey: process.env.OPENAI_API_KEY, model: "gpt-4o-mini" },
  globalStore
);

// Agent-level store
const agentStore = createStore({ turns: 0 });

const agent = fragola.agent({
  name: "Assistant",
  instructions: "You are helpful.",
  description: "General assistant",
  store: agentStore
});

// Access stores from tools
const counterTool = tool({
  name: "increment",
  description: "increments the counter",
  handler: async (params, context) => {
  if (!context.store)
    return { error: "failed to retrieve store" };
    context.store.update(prev => ({
    ...prev,
    turns: prev.turns + 1
  }));
    return { newCount: context.store.value.turns };
  }
});
Core Primitive

Stores

Simple reactive state management. Share data across agents, tools, and hooks with global or namespaced stores.

  • Global & per-agent scopes
  • Change subscriptions
  • Tool & event access
Learn more about Stores
context.ts
// Access agent state
const messages = agent.context.state.messages;
const status = agent.context.state.status;
const stepCount = agent.context.state.stepCount;

// Dynamically update tools at runtime
agent.context.updateTools(prev => [
  ...prev,
  newTool
]);

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

// Manage instructions with scopes
agent.context.setInstructions("You are concise.", "style");
agent.context.setInstructions("Focus on data.", "task");
agent.context.removeInstructions("style");

// Access stores from context
const mainStore = agent.context.store;
const analyticsStore = agent.context.getStore("analytics");

// Update options at runtime (only when idle)
agent.context.setOptions({
  modelSettings: { temperature: 0.5 },
  stepOptions: { maxStep: 5 }
});

// Stop agent execution
await agent.context.stop();
Core Primitive

Context

Unified access to agent state, tools, stores, and configuration. The bridge between your code and agent internals.

  • Runtime tool management
  • Store access from anywhere
  • Instruction updates
Learn more about Context

Built-in Hook Presets

Ready-to-use integrations for common patterns

mcpClient
Connect to remote or local MCP servers and expose their tools to your agent.
orchestration
Enable multiple specialized agents to communicate and work together.
guardrail
Validate user messages against unwanted content and reject them with a reason.
fileSystemSave
Simple conversation persistence on Node.js-like runtimes.

Get Started in Minutes

1

Install

npm install @fragola-ai/agentic-sdk-core
2

Initialize

import { Fragola } from "@fragola-ai/agentic-sdk-core";

const fragola = new Fragola({
  apiKey: process.env.OPENAI_API_KEY,
  model: "gpt-4o-mini"
});
3

Create an Agent

const agent = fragola.agent({
  name: "QuickstartAgent",
  description: "My first Fragola agent",
  instructions: "You are a helpful assistant."
});
4

Send a Message

const state = await agent.userMessage({
  content: "Hello! What can you do?"
});

console.log(state.messages);

Ready to Build?

Start building powerful AI agents with Fragola today.