Context
Programmatic interface to inspect and mutate an Agent at runtime.
Overview
AgentContext is the programmable surface you use to observe and safely modify a running Agent. It exposes:
- The (
state,options) of the agent's current lifecycle & configuration. - Direct store access (default local store + namespaced stores) for shared memory.
- Instruction (system prompt) management with scoped variants.
- Tool list mutation at runtime.
- Low-level message mutation helpers (
raw) for advanced workflows (batched edits, rewrites). - Safe runtime option updates (only while idle).
- Controlled stop signals (async and sync) to abort streaming or tool execution.
Use agent.context inside events, hooks, tools, orchestration code, or external supervisors.
Some operations (e.g. setOptions) require the agent to be idle. Attempting them during generating or waiting throws.
state
Current snapshot of the agent state: messages, step count, and lifecycle status.
Examples
// 1) Read last assistant message
const last = [...agent.context.state.messages].reverse().find(m => m.role === 'assistant');
// 2) Branch logic based on status
if (agent.context.state.status === 'waiting') {
console.log('Agent awaiting tool results');
}
// 3) Count user messages so far
const userCount = agent.context.state.messages.filter(m => m.role === 'user').length;options
Resolved configuration (model settings overrides, tools, step options, instructions, etc.). Mutate with setOptions()—not by editing this object directly.
Examples
// 1) Inspect temperature
console.log('Temperature:', agent.context.options.modelSettings?.temperature);
// 2) List currently registered tools
(agent.context.options.tools ?? []).forEach(t => console.log(t.name));
// 3) Check step constraints
const maxStep = agent.context.options.stepOptions?.maxStep;raw
Low-level async helpers to mutate messages directly. Avoid unless you need precise control; prefer high-level APIs.
appendMessages(messages, replaceLast, reason)updateMessages(callback, reason)reasoninfluences after-events (after:messagesUpdate). Valid add reasons:userMessage | toolCall | partialAiMessage | AiMessage(removal reasons prefixed byremove:).
Examples
// 1) Append a synthetic assistant summary
await agent.context.raw.appendMessages([
{ role: 'assistant', content: 'Summary: conversation compressed.' }
], false, 'AiMessage');
// 2) Replace last assistant partial with a finalized version
await agent.context.raw.appendMessages([
{ role: 'assistant', content: 'Final answer.' }
], true, 'AiMessage');
// 3) Bulk redact messages
await agent.context.raw.updateMessages(prev => prev.map(m => (
m.role === 'user' ? { ...m, content: '[REDACTED]' } : m
)), 'partialAiMessage');store
Returns the agent's default local Store (if configured).
Examples
// 1) Read ephemeral memory
console.log(agent.context.store.value);
// 2) Increment a counter
agent.context.store.update(v => ({ ...v, turns: (v.turns ?? 0) + 1 }));
// 3) React to changes
agent.context.store.onChange(v => console.log('Store changed', v));addStore
Attach an additional namespaced store for modular shared state. Namespace must be unique.
Examples
import { createStore } from '@src/store';
// 1) Add analytics store
agent.context.addStore(createStore({ events: [] }, 'analytics'));
// 2) Add task routing map
agent.context.addStore(createStore({ tasks: {} }, 'router'));updateTools
Replace or mutate the agent's tool list at runtime. Automatically syncs to model settings.
Examples
// 1) Add a new tool
agent.context.updateTools(prev => [...prev, {
name: 'ping', description: 'Ping tool', handler: () => 'pong'
}]);
// 2) Remove deprecated tool
agent.context.updateTools(prev => prev.filter(t => t.name !== 'oldTool'));
// 3) Replace all tools with a minimal subset
agent.context.updateTools(() => [{ name: 'echo', description: 'Echo', handler: (p: any) => p }]);removeStore
Detach a previously added namespaced store. No-op if namespace missing.
Examples
// 1) Remove analytics store
agent.context.removeStore('analytics');
// 2) Clean up router store after orchestration phase
agent.context.removeStore('router');instance
Fragola root instance that created the agent. Access global options or global store.
Examples
// 1) Read default model
console.log(agent.context.instance.options.model);
// 2) Access global store value
console.log(agent.context.instance.store?.value);getStore
Fetch default (no namespace) or a namespaced store added via addStore. Returns undefined if absent.
Examples
// 1) Get default store
const base = agent.context.getStore();
// 2) Get analytics store
const analytics = agent.context.getStore<'events' extends never ? any : any>('analytics');
// 3) Safely mutate if exists
const router = agent.context.getStore('router');
router?.update(v => ({ ...v, lastAccess: Date.now() }));setInstructions
Set (or scope) system instructions. Without scope, overwrites default instructions. With scope, stores a scoped variant merged deterministically.
Examples
// 1) Replace base instructions
agent.context.setInstructions('You are a concise assistant.');
// 2) Add a scoped persona
agent.context.setInstructions('Focus on data sanitation.', 'sanitizer');
// 3) Add evaluation scope
agent.context.setInstructions('Critically evaluate previous answer.', 'critic');getInstructions
Retrieve default or scoped instructions.
Examples
// 1) Read base
console.log(agent.context.getInstructions());
// 2) Read scoped
console.log(agent.context.getInstructions('critic'));removeInstructions
Delete a scoped instructions entry. Returns boolean indicating success. Recomputes merged cache if removed.
Examples
// 1) Remove critic scope
const removed = agent.context.removeInstructions('critic');
if (removed) console.log('Critic instructions removed');
// 2) Attempt removal (fails silently)
agent.context.removeInstructions('nonexistent');setOptions
Update mutable agent options (except name, messages, fork). Only allowed when status is idle; otherwise throws.
Examples
// 1) Lower temperature
agent.context.setOptions({ modelSettings: { temperature: 0 } });
// 2) Add stepOptions limit
agent.context.setOptions({ stepOptions: { maxStep: 8 } });
// 3) Swap instructions + temperature together
agent.context.setOptions({
instructions: 'Be terse.',
modelSettings: { temperature: 0.2 }
});stop
Asynchronously request termination of current execution (aborts streaming/tool loop). Returns { [STOP]: true } when processed.
Examples
// 1) Cancel a long streaming response
await agent.context.stop();
// 2) Cancel during tool wait
await agent.context.stop();stopSync
Synchronous variant of stop() for scenarios where awaiting is unnecessary (still aborts active controller if present).
Examples
// 1) Immediate stop inside event
agent.onAiMessage((msg, partial, ctx) => {
if (!partial && msg.content.includes('unsafe')) ctx.stopSync();
return msg;
});
// 2) Force abort in orchestration timeout handler
agent.context.stopSync();Notes & Best Practices
- Prefer high-level APIs (
userMessage, events) before usingraw. - Use scoped instructions for temporary personas; remove them when done to avoid prompt drift.
- Validate namespace uniqueness when designing dynamic store registries.
- Use
stopSynconly in synchronous paths; otherwisestopis safer for consistency.