Skip to main content

Why callModel?

  • Items-Based Model: Built on OpenRouter’s Responses API with structured items (messages, tool calls, reasoning) instead of raw message chunks
  • Multiple Consumption Patterns: Get text, stream responses, or access structured data - all from a single call
  • Automatic Tool Execution: Define tools with Zod schemas and let the SDK handle execution loops
  • Type Safety: Full TypeScript inference for tool inputs, outputs, and events
  • Format Compatibility: Convert to/from OpenAI chat and Anthropic Claude message formats
  • Streaming First: Built on a reusable stream architecture that supports concurrent consumers

Quick Start

import { OpenRouter } from '@openrouter/agent';

const openrouter = new OpenRouter({
  apiKey: process.env.OPENROUTER_API_KEY,
});

const result = openrouter.callModel({
  model: 'openai/gpt-5-nano',
  input: 'What is the capital of France?',
});

// Get text (simplest pattern)
const text = await result.getText();
console.log(text); // "The capital of France is Paris."

Consumption Patterns

callModel returns a ModelResult object that provides multiple ways to consume the response:

Text Methods

// Get just the text content
const text = await result.getText();

// Get the full response with usage data
const response = await result.getResponse();
console.log(response.usage); // { inputTokens, outputTokens, cachedTokens }

Streaming Methods

// Stream text deltas
for await (const delta of result.getTextStream()) {
  process.stdout.write(delta);
}

// Stream reasoning (for reasoning models)
for await (const delta of result.getReasoningStream()) {
  console.log('Reasoning:', delta);
}

// Stream complete items by ID (recommended)
for await (const item of result.getItemsStream()) {
  console.log('Item update:', item.type, item.id);
}

// Stream all events (including tool preliminary results)
for await (const event of result.getFullResponsesStream()) {
  console.log('Event:', event.type);
}

Tool Methods

// Get all tool calls from the response
const toolCalls = await result.getToolCalls();

// Stream tool calls as they complete
for await (const toolCall of result.getToolCallsStream()) {
  console.log(`Tool: ${toolCall.name}`, toolCall.arguments);
}

// Stream tool deltas and preliminary results
for await (const event of result.getToolStream()) {
  if (event.type === 'delta') {
    process.stdout.write(event.content);
  } else if (event.type === 'preliminary_result') {
    console.log('Progress:', event.result);
  }
}

Input Formats

callModel accepts multiple input formats:
// Simple string
const result1 = openrouter.callModel({
  model: 'openai/gpt-5-nano',
  input: 'Hello!',
});

// Message array (OpenResponses format)
const result2 = openrouter.callModel({
  model: 'openai/gpt-5-nano',
  input: [
    { role: 'user', content: 'Hello!' },
  ],
});

// With system instructions
const result3 = openrouter.callModel({
  model: 'openai/gpt-5-nano',
  instructions: 'You are a helpful assistant.',
  input: 'Hello!',
});

What’s Next?

Explore the guides to learn more about specific features:

Example Tools

Ready-to-use tool implementations: