My App

Understanding AgentContext

The AgentContext object (agent.context) is the connective tissue of Fragola. It is passed into every event listener and every tool handler, giving you safe, consistent access to the agent's internal state.

What is in the Context?

The AgentContext exposes several key properties:

  • context.state: Read-only access to the agent's current state (messages, stepCount, status).
  • context.options: Read-only access to the agent's configured options (e.g., its name, description, and available tools).
  • context.store: The agent's default local store.
  • context.instance: A reference back to the parent Fragola SDK instance that created the agent.

Access in Event Listeners

Every lifecycle event (onUserMessage, onBeforeToolCall, etc.) receives the context as part of its payload. This allows you to write listeners that react conditionally based on the agent's state or options.

agent.onBeforeModelInvocation(({ config, context }) => {
    // Check the agent's current state via context
    if (context.state.stepCount > 3) {
        console.log(`Agent ${context.options.name} is taking a long time...`);
    }
    return config;
});

Access in Tool Handlers

The true power of the context shines in tool handlers. Tools are often isolated functions, but with Fragola, they can reach back into the agent to read history or modify state.

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

const myTool = tool({
    name: "inspectHistory",
    description: "Looks at what the user said previously.",
    schema: z.object({}),
    handler: (params, context) => {
        // A tool has full access to the agent's conversation history!
        const userMessages = context.state.messages.filter(m => m.role === "user");
        return `You have spoken ${userMessages.length} times.`;
    }
});

Dynamic & Scoped Instructions

Agent instructions (system prompts) do not have to be static. Fragola uses a scoped instructions system, allowing you to inject, update, and remove rules dynamically without losing the core persona.

Scoped Instructions

When you set instructions during agent creation, Fragola assigns them to the default scope.

You can add instructions to new scopes using context.instructions.add(scope, text) (or via the underlying Map/Set API depending on the exact implementation, usually manipulated via setInstructions(text, scope)).

Setting and Removing Instructions

agent.onBeforeModelInvocation(({ context, config }) => {
    // Inject a temporary instruction into a specific scope
    context.setInstructions("Always reply in French.", "language-rule");

    return config;
});

To remove a scoped instruction once it's no longer needed:

context.removeInstructions("language-rule");

The Final System Prompt

When the LLM is invoked, Fragola merges all scoped instructions together. You can preview exactly what the LLM will see using the systemPrompt getter.

console.log(context.systemPrompt); 
// Returns the merged string of the default instructions + any custom scopes

Message History Manipulation

While you can read the agent's history via context.state.messages, modifying it directly requires using the provided manipulation utilities to ensure the state remains stable.

context.messagesParser

Fragola provides context.messagesParser, a set of utilities securely bound to the current agent's message history. It allows you to search, filter, and extract specific interactions safely.

agent.onAfterStep(({ context }) => {
    // Use the parser to find specific messages easily
    const allToolCalls = context.messagesParser.getTools();
    const lastUserMessage = context.messagesParser.getLastUserMessage();
});

Advanced Mutations with context.raw

If you are building complex orchestrators or recovery mechanisms, you may need to fundamentally rewrite the history (e.g., pruning old messages to save tokens).

You can access context.raw.updateMessages() to safely override the history array.

agent.onBeforeModelInvocation(({ context, config }) => {
    const messages = context.state.messages;
    
    // Naive token management: If history is too long, keep only the system prompt and the last 10 messages
    if (messages.length > 50) {
        const recentMessages = messages.slice(-10);
        context.raw.updateMessages(recentMessages);
    }
    
    return config;
});

Runtime Agent Mutation

The AgentContext provides methods to mutate the agent's fundamental configuration on the fly.

Updating Options

You can update basic agent options like description or model settings using context.setOptions(). Note that some properties like name or messages cannot be updated through this method.

context.setOptions({
    description: "Updated description based on new context",
    modelSettings: {
        temperature: 0.8
    }
});

Updating Tools

As covered in Runtime Tool Management, you can dynamically swap the tools available to the model using context.updateTools().

context.updateTools((previousTools) => {
    return [...previousTools, newTool];
});

Controlled Early Exits

Sometimes, an event listener or a tool handler determines that the agent should immediately stop what it is doing.

  • context.stop(): Signals the agent to cleanly halt execution at the end of the current asynchronous boundary.
  • context.stopSync(): Instantly aborts the execution loop by throwing an internal signal.
const emergencyStopTool = tool({
    name: "halt",
    description: "Halts the agent.",
    schema: z.object({}),
    handler: (params, context) => {
        context.stopSync();
    }
});

On this page