Appearance
OpenRouter SDK 内置多种消息格式转换函数,可将 OpenAI Chat Completions 格式或 Anthropic Claude 格式的消息历史无损转换为 OpenRouter 的 OpenResponses 格式。本文详细介绍 fromChatMessages()、toChatMessage()、fromClaudeMessages()、toClaudeMessage() 四个核心工具函数的用法,涵盖 tool call 消息、图片 content blocks、base64 图片等复杂场景,以及完整的迁移示例。
OpenAI Chat 格式
fromChatMessages()
将 OpenAI Chat Completions 格式的消息数组转换为 OpenResponses 输入:
typescript
import { OpenRouter, fromChatMessages } from '@openrouter/agent';
const openrouter = new OpenRouter({
apiKey: process.env.OPENROUTER_API_KEY,
});
const chatMessages = [
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'Hello!' },
{ role: 'assistant', content: 'Hi there! How can I help you?' },
{ role: 'user', content: 'What is the weather like?' },
];
const result = openrouter.callModel({
model: 'openai/gpt-5-nano',
input: fromChatMessages(chatMessages),
});
const text = await result.getText();toChatMessage()
将 OpenResponses 响应转换回 Chat Completions 的 assistant 消息格式:
typescript
import { toChatMessage } from '@openrouter/agent';
const result = openrouter.callModel({
model: 'openai/gpt-5-nano',
input: 'Hello!',
});
const response = await result.getResponse();
const chatMessage = toChatMessage(response);
// chatMessage: { role: 'assistant', content: '...' }
console.log(chatMessage.role); // 'assistant'
console.log(chatMessage.content); // 响应文本支持的消息角色
| Chat Role | 说明 |
|---|---|
system | 系统指令 |
user | 用户消息 |
assistant | 助手响应 |
developer | 开发者指令 |
tool | 工具返回消息 |
Tool Call 消息
工具调用的 function call + tool result 格式会被正确转换:
typescript
const chatMessages = [
{ role: 'user', content: 'What is the weather?' },
{
role: 'assistant',
content: null,
tool_calls: [{
id: 'call_123',
type: 'function',
function: { name: 'get_weather', arguments: '{"location":"Paris"}' },
}],
},
{
role: 'tool',
tool_call_id: 'call_123',
content: '{"temperature": 20}',
},
];
const input = fromChatMessages(chatMessages);Anthropic Claude 格式
fromClaudeMessages()
将 Anthropic SDK 风格的消息数组转换为 OpenResponses 输入:
typescript
import { OpenRouter, fromClaudeMessages } from '@openrouter/agent';
const claudeMessages = [
{ role: 'user', content: 'Hello!' },
{ role: 'assistant', content: 'Hi there!' },
{ role: 'user', content: 'Tell me about TypeScript.' },
];
const result = openrouter.callModel({
model: 'anthropic/claude-sonnet-4.5',
input: fromClaudeMessages(claudeMessages),
});toClaudeMessage()
将响应转换为与 Anthropic SDK 兼容的 message 格式:
typescript
import { toClaudeMessage } from '@openrouter/agent';
const result = openrouter.callModel({
model: 'anthropic/claude-sonnet-4.5',
input: 'Hello!',
});
const response = await result.getResponse();
const claudeMessage = toClaudeMessage(response);
// 与 Anthropic SDK 类型兼容Content Blocks(多模态)
支持 Claude 的 content block 格式,可包含文字和图片:
typescript
const claudeMessages = [
{
role: 'user',
content: [
{ type: 'text', text: 'What is in this image?' },
{
type: 'image',
source: {
type: 'url',
url: 'https://example.com/image.jpg',
},
},
],
},
];
const input = fromClaudeMessages(claudeMessages);Tool Use Blocks
Claude 的 tool_use / tool_result 格式会被自动转换:
typescript
const claudeMessages = [
{ role: 'user', content: 'What is the weather?' },
{
role: 'assistant',
content: [
{
type: 'tool_use',
id: 'tool_123',
name: 'get_weather',
input: { location: 'Paris' },
},
],
},
{
role: 'user',
content: [
{
type: 'tool_result',
tool_use_id: 'tool_123',
content: '{"temperature": 20}',
},
],
},
];
const input = fromClaudeMessages(claudeMessages);Base64 图片
URL 和 base64 编码的图片都支持:
typescript
const claudeMessages = [
{
role: 'user',
content: [
{ type: 'text', text: 'Describe this image.' },
{
type: 'image',
source: {
type: 'base64',
media_type: 'image/png',
data: 'iVBORw0KGgo...',
},
},
],
},
];限制说明
部分 Claude 专有特性在转换中会丢失,例如 tool_result 的 is_error 标志。这些是 Claude API 独有的特性,OpenRouter 格式不支持。
迁移示例
从 OpenAI SDK 迁移
typescript
// 迁移前:OpenAI SDK
import OpenAI from 'openai';
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const completion = await openai.chat.completions.create({
model: 'gpt-4',
messages: [
{ role: 'system', content: 'You are helpful.' },
{ role: 'user', content: 'Hello!' },
],
});
// 迁移后:OpenRouter SDK
import { OpenRouter, fromChatMessages } from '@openrouter/agent';
const openrouter = new OpenRouter({ apiKey: process.env.OPENROUTER_API_KEY });
const result = openrouter.callModel({
model: 'openai/gpt-5.2',
input: fromChatMessages([
{ role: 'system', content: 'You are helpful.' },
{ role: 'user', content: 'Hello!' },
]),
});
const text = await result.getText();从 Anthropic SDK 迁移
typescript
// 迁移前:Anthropic SDK
import Anthropic from '@anthropic-ai/sdk';
const anthropic = new Anthropic();
const message = await anthropic.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 1024,
messages: [{ role: 'user', content: 'Hello!' }],
});
// 迁移后:OpenRouter SDK
import { OpenRouter, fromClaudeMessages } from '@openrouter/agent';
const openrouter = new OpenRouter({ apiKey: process.env.OPENROUTER_API_KEY });
const result = openrouter.callModel({
model: 'anthropic/claude-sonnet-4.5',
input: fromClaudeMessages([{ role: 'user', content: 'Hello!' }]),
maxOutputTokens: 1024,
});
const text = await result.getText();多轮对话构建
跨多次 API 调用累积消息历史:
typescript
import { fromChatMessages, toChatMessage } from '@openrouter/agent';
let messages = [
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'Hello!' },
];
// 第一轮
let result = openrouter.callModel({
model: 'openai/gpt-5-nano',
input: fromChatMessages(messages),
});
let response = await result.getResponse();
let assistantMessage = toChatMessage(response);
// 追加到历史
messages.push(assistantMessage);
messages.push({ role: 'user', content: 'What can you help me with?' });
// 第二轮继续对话
result = openrouter.callModel({
model: 'openai/gpt-5-nano',
input: fromChatMessages(messages),
});常见问题
Q: fromChatMessages 和直接传字符串有什么区别?
A: 传字符串是单轮无历史的简单调用;fromChatMessages 适合需要携带完整对话历史的多轮场景,或者从 OpenAI SDK 迁移时保持消息结构不变。
Q: 从 Claude SDK 迁移后,system prompt 怎么处理?
A: fromClaudeMessages 只处理 messages 数组;system prompt 应通过 callModel 的 instructions 参数传入,不要放进消息数组里。
Q: 转换后的格式能用于 streaming 吗?
A: 可以,转换函数只处理 input 格式,不影响 callModel 的其他配置,streaming 正常使用即可。