WASM Agent

Run AI agents with tool calling in WebAssembly

Overview

The runAgent function executes an agentic tool-calling loop entirely within the WASM module. The model decides which tools to call, the WASM runtime invokes your JavaScript handler functions, feeds the results back, and repeats until the model finishes or maxIterations is reached.

Basic agent

import init, { CompletionModel, ChatMessage, runAgent } from '@blazen/sdk';

await init();

const model = CompletionModel.openai('your-key');

const tools = [
  {
    name: 'getWeather',
    description: 'Get the current weather for a city',
    parameters: {
      type: 'object',
      properties: { city: { type: 'string' } },
      required: ['city'],
    },
  },
];

const result = await runAgent(
  model,
  [ChatMessage.user('What is the weather in Tokyo?')],
  tools,
  async (toolName, args) => {
    if (toolName === 'getWeather') {
      return { temp: 22, condition: 'cloudy', city: args.city };
    }
    throw new Error(`Unknown tool: ${toolName}`);
  }
);

console.log(result.response.content);
console.log(`Iterations: ${result.iterations}`);

Tool handlers

The fourth argument to runAgent is a JavaScript async function. It receives:

  • toolName — the name of the tool the model wants to call.
  • args — parsed JSON arguments matching the tool’s parameter schema.

Return any JSON-serializable value. The WASM runtime serializes it back into the conversation as a tool result message.

async function toolHandler(toolName: string, args: Record<string, unknown>) {
  switch (toolName) {
    case 'search':
      return await fetch(`/api/search?q=${args.query}`).then(r => r.json());
    case 'calculate':
      return { result: eval(args.expression as string) };
    default:
      throw new Error(`Unknown tool: ${toolName}`);
  }
}

Agent options

Pass an options object as the fifth argument:

const result = await runAgent(model, messages, tools, handler, {
  maxIterations: 5,
  systemPrompt: 'You are a helpful research assistant.',
  temperature: 0.3,
  maxTokens: 1000,
  addFinishTool: true,
});
OptionTypeDefaultDescription
maxIterationsnumber10Maximum tool-calling rounds
systemPromptstringSystem prompt prepended to the conversation
temperaturenumberSampling temperature
maxTokensnumberMax tokens per completion call
addFinishToolbooleanfalseAdd a built-in “finish” tool the model can call to signal completion

Structured output

Combine tool calling with a single-purpose tool to extract structured data:

const extractTools = [
  {
    name: 'extractContact',
    description: 'Extract contact information from text',
    parameters: {
      type: 'object',
      properties: {
        name: { type: 'string' },
        email: { type: 'string' },
        phone: { type: 'string' },
      },
      required: ['name'],
    },
  },
];

let extracted = null;

const result = await runAgent(
  model,
  [ChatMessage.user('Extract: John Doe, john@example.com, 555-1234')],
  extractTools,
  async (toolName, args) => {
    extracted = args;
    return 'Extracted successfully.';
  },
  { maxIterations: 1 }
);

console.log(extracted);
// { name: "John Doe", email: "john@example.com", phone: "555-1234" }

Agent result

runAgent resolves with an AgentResult:

interface AgentResult {
  response: CompletionResponse; // Final completion response
  messages: object[];           // Full message history
  iterations: number;           // Number of tool-calling iterations
  totalCost?: number;           // Aggregated cost in USD
}

Next steps