跳到正文
OpenRouter Blog·· 2026-04-24精选AI 评分62

OpenRouter 发布 Agent SDK,用 callModel 构建多轮智能体工作流

Agent SDK: Building Multi-turn Agent Workflows on OpenRouter

AI 导读

OpenRouter 发布 @openrouter/agent,一个模型无关的 TypeScript SDK,用单个 callModel 函数在 OpenRouter 上 400+ 模型间执行智能体循环。

推荐理由

官方给出 callModel 的循环、停止条件与成本追踪写法,可据此判断多轮智能体工程化的落地方式。

正文 · AI 翻译

构建一个 agent 需要的是一套分层的行为,远不止聊天补全:它需要调用模型、检查输出中的工具请求、执行这些工具、将结果反馈回去,并重复这一过程直到任务完成。构建这个循环的持久版本意味着要处理输入验证、流式传输、成本追踪,以及知道何时停止。

@openrouter/agent 是一个与模型无关的 TypeScript SDK,它将所有这些打包成一个函数,可以在 OpenRouter 上的 400 多个模型中的任何一个上执行这个 agentic 循环。为了展示这个 agentic 循环有多强大,我们发布了一篇教程,介绍在 Agent SDK 之上构建一个 skill 如何让你构建自己的个人 agent harness。

从聊天补全到 agentic 行为

标准的聊天补全是无状态的:你发送消息,你得到响应。要将其转变为 agent,需要附加若干行为:

工具执行。 模型会生成一个结构化的工具调用。你的代码必须解析它、验证参数、运行函数,并为下一次请求格式化结果。使用 callModel,你可以用 tool() 和 Zod schema 定义工具。工具与模型调用分开运行,边界清晰,逻辑不纠缠。SDK 会在运行时验证来自模型的输入和来自你的函数的输出。如果模型发送了错误的参数,你会得到一个清晰的错误,而不是下游的静默失败。

多轮循环。 一个 agent 很少能一步完成。它可能会搜索、读取结果、再次搜索,然后写一份摘要。这意味着循环:调用模型、执行工具、再次调用模型、重复。callModel 在内部处理这个循环。你通过停止条件来控制它:接收完整步骤历史并决定是否继续的自定义函数。

停止条件。 没有护栏的话,agent 循环可能会永远运行下去(或者至少直到你的账单变得令人不安)。callModel 接受可组合的停止条件:stepCountIs(10) 将循环限制在 10 轮,maxCost(1.00) 设置美元上限,hasToolCall('done') 在调用特定工具时停止。将它们组合起来,或者编写一个自定义函数。

import { stepCountIs, maxCost, hasToolCall } from '@openrouter/agent/stop-conditions';

const result = client.callModel({
  model: 'openai/gpt-5',
  input: 'Research this topic and compile a report',
  tools: [searchTool, writeTool, doneTool],
  stopWhen: [
    stepCountIs(15),
    maxCost(2.00),
    hasToolCall('done'),
  ],
});

流式传输。 需要多步执行的 agent 需要展示进度。callModel 为你提供 getTextStream()、getToolCallsStream() 和 getReasoningStream()。并发地流式传输、提取和处理同一个响应,无需事先做出选择。

成本追踪。 每个响应都通过 result.getResponse() 包含 token 计数和成本数据,因此你可以确切知道每次 agent 运行的成本。

工具审批。 对于会执行现实世界操作的 agent,你可以将工具标记为需要审批。当模型调用其中一个时,SDK 会暂停执行,将控制权交还给你的代码,并等待你收集决定后再继续。

callModel 处理了所有这些,因此你可以专注于你的应用程序特有的工具和逻辑。而且由于该 SDK 与模型无关,你可以在 OpenRouter 上的任何模型之间切换,而无需更改你的 agent 代码。

开始使用

npm install @openrouter/agent
import { OpenRouter } from '@openrouter/agent';
import { tool } from '@openrouter/agent/tool';
import { stepCountIs } from '@openrouter/agent/stop-conditions';
import { z } from 'zod';

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

const result = client.callModel({
  model: 'anthropic/claude-sonnet-4',
  input: 'What time is it in Tokyo?',
  tools: [
    tool({
      name: 'get_time',
      description: 'Get current time in a timezone',
      inputSchema: z.object({ timezone: z.string() }),
      execute: async ({ timezone }) => {
        try {
          return { time: new Date().toLocaleString('en-US', { timeZone: timezone }) };
        } catch {
          return { error: `Invalid timezone: ${timezone}. Use IANA format like 'Asia/Tokyo'.` };
        }
      },
    }),
  ],
  stopWhen: [stepCountIs(5)],
});

const text = await result.getText();

SDK 调用模型,看到它想要使用 get_time,根据你的 Zod schema 验证输入,执行函数,将结果反馈回去,并返回最终文本。你编写的循环逻辑为零。

获取你的 API 密钥,并将你的 agent 指向 callModel 文档。

在 Discord 上告诉我们你正在构建什么。

来源:OpenRouter Blog · openrouter.ai