agent-native 解读:写一次功能,Agent、界面、命令行同时可用

开源AgentAI

一个典型的 Web 应用有三层:前端界面、后端 API、数据库。如果想给这个应用加一个 AI 助手,让它也能查询订单、修改数据,开发者通常要再写一遍集成——把已有的 API 包装成 Agent 可调用的工具,两套代码做同一件事,从此各自维护。Builder.io 在 3 月创建、本周冲上 GitHub Trending 的开源框架 agent-native(5,339 星,日增约 98 星,核心包 MIT 许可证)要消灭的就是这层重复:功能只写一次,界面、Agent、HTTP、MCP、A2A、命令行六个出口同时可用。

BuilderIO/agent-native 仓库卡片:5k Stars / 484 Forks / 73 Contributors

一个文件夹取代 API 层

框架的核心抽象只有一个:action。在 actions/ 目录下放一个文件,导出一个 defineAction() 调用,框架在启动时扫描这个文件夹并自动挂载每个文件,没有注册步骤,也没有需要维护的索引文件。

ts
// actions/hello.ts
import { defineAction } from "@agent-native/core/action";
import { z } from "zod";

export default defineAction({
  description: "Return a friendly greeting.",
  schema: z.object({
    name: z.string().default("world").describe("Name to greet"),
  }),
  http: { method: "GET" },
  readOnly: true,
  run: async ({ name }) => {
    return { message: `Hello, ${name}!` };
  },
});

这一个文件定义了四个东西:description 告诉 Agent 什么时候该用它;schema 用 zod 校验输入并生成类型化工具定义;http 把这个只读操作暴露为 GET 接口;run 是界面和 Agent 共享的业务逻辑。

写完之后,六个出口同时生效,全部走同一套 schema 校验、权限检查和审计记录:

出口调用方式场景
Agent 工具Agent 读描述和 schema,聊天中直接调用「帮我回复这张工单」
React HooksuseActionQuery / useActionMutation / callAction界面按钮点击
HTTP自动挂载在 /_agent-native/actions/<name>外部脚本、集成
MCP 工具任何 MCP 宿主(Claude、Cursor、Codex)发现并调用其他 AI 客户端驱动你的应用
A2A 工具其他 agent-native 应用通过 A2A 协议发现调用工作区内应用互相委托
CLIpnpm action hello '{"name":"Steve"}'定时任务、手工测试

官方文档对传统架构的批评是:多数应用在前端和数据库之间建一个只有浏览器能调用的 API 层,Agent 想用同样的能力就得另写一份集成。agent-native 里没有这个分层,app/ 和 Agent 解析到同一批 action 和同一个 SQL 数据库。改一处逻辑,六个出口同时更新——示例文档专门演示了这一点:改 hello 的返回值,刷新界面和让 Agent 重新调用,两边返回的都是新文案。

这里有一条明确的设计边界:Agent 不通过点击界面来操作应用,它和应用走同一个 action 层。界面是 action 的另一种渲染,不在 Agent 的操纵路径上。

上手成本与栈

bash
npx --yes @agent-native/core@latest create my-app --standalone --template chat
cd my-app && corepack enable && pnpm install
pnpm dev

运行要求 Node.js 22.22 以上、pnpm(可用 corepack 启用),Agent 的 LLM 连接支持 Builder.io 免费额度、Anthropic 或 OpenAI 的 API key,也支持本地 Ollama 模型。聊天模板自带浏览器界面、认证、持久化会话、实时同步和一个示例 action。数据库用 PostgreSQL(生产)和 PGlite(本地开发),部署目标不限定,任何 Nitro 兼容的主机都可以,LLM、SQL 数据库、工具和基础设施全部自带——官方原话是「你构建的一切都留在你手里」。

run() 的函数体是普通服务端代码,没有沙箱或 DSL。框架只约定一件事:actions/ 之外的代码不许直接 import 某个 action 的 run 函数,一切调用必须经过六个出口之一,这样校验和审计才不会被绕过。

Agent Teams:主聊天是编排者,不是干活的人

多 Agent 部分是这套框架最有想法的设计。主聊天被定位为编排者(orchestrator):读请求、委派,很少自己干重活。遇到「用我的语气写这封邮件」「跑一个 BigQuery 分析」「复审这个 PR」这类任务,主 Agent 生成一个子代理(sub-agent),后者拥有自己的线程、系统提示词和工具集。

子代理在主聊天里以一个实时预览卡片(chip)出现,折叠显示当前步骤和流式输出,点开是完整对话。官方文档列了四条该派子代理的判断标准:任务需要不同的系统提示词、有会污染主上下文的长工具链、能与其他工作并行、或属于已有专属配置文件的另一个团队。琐碎的一次性任务不派,直接调 action。

子代理的任务状态持久化在 application_state SQL 表里(键为 agent-task:<taskId>),服务端冷启动后任务还在,也能跨进程工作。主 Agent 与运行中的子代理之间支持双向消息:父级可以追加指令,子代理遇到歧义点可以主动回问,消息走任务生命周期投递,当前步骤消费不了就排队等安全点应用。

委托深度有硬性上限,默认 2 层,可用环境变量 AGENT_NATIVE_MAX_SUBAGENT_DEPTH 调整。这个上限的实现方式值得抄走:每个子代理跑在一个记录自己深度的 AsyncLocalStorage 里,任何传递性触发的 spawnTask 都会读到父级深度,到顶即拒——即使把委派工具递给了一个不该再有它的子代理,越权生成也会被服务端拒绝。判断逻辑被抽成纯函数 evaluateSubagentDepth(parentDepth),可以单元测试。超过 16 层的配置值直接钳制到 16,一个手滑的部署配置不会关掉这层保护。

自定义专家 Agent 的定义方式是 agents/<slug>.md:一个带 YAML frontmatter 的 Markdown 文件。主 Agent 手上有一个 agent-teams 工具,动作集五个:spawn(生成)、status(查进度)、read-result(取结果)、send(追加消息)、list(列出任务)。

Automations:自然语言写的触发器

自动化是一条「当 X 发生时,做 Y」的规则,落在 jobs/<name>.md 文件里,frontmatter 声明触发方式,正文是自然语言指令。触发器两种:schedule(cron 表达式)和 event(框架事件总线上的事件名)。事件触发可以挂一个自然语言条件,由 Haiku 对事件负载求值后才分发——官方示例是「当与会者邮箱以 @builder.io 结尾时」。

yaml
# jobs/slack-on-builder-booking.md
schedule: ""
enabled: true
triggerType: event
event: calendar.booking.created
condition: "attendee email ends with @builder.io"
mode: agentic
domain: calendar
runAs: creator
---
Send a Slack message to #sales with the booking details.
Use the web-request tool to POST to ${keys.SLACK_WEBHOOK}.

两个细节有工程含金量。其一,${keys.SLACK_WEBHOOK} 这类密钥在服务端解析,原始值不进 Agent 的上下文,自然语言正文里只出现变量名。其二,事件总线在模块加载时注册事件类型,负载用 Standard Schema 定义校验后才派发给订阅者;内置事件覆盖 agent.turn.completedcalendar.*mail.*clip.*,业务自定义事件用 registerEvent() 声明、emit() 触发。条件不匹配时自动化静默跳过,调度器会写一条 skipped 状态。

创建方式有三种:直接对 Agent 说「当我收到 XX 邮件时,往 Slack 发通知」,它在设置界面点选,或者手写 jobs/ 文件。三种路径落盘的是同一个文件。

官方示例与适用边界

README 收录了八个可直接 Fork 的开源 Agent 应用:Clips(会议与屏幕录制理解)、Design(交互设计生成)、Slides(演示文稿)、Analytics(数据问答与仪表盘)、Calendar、Mail、Assets 等。它们既是模板,也是 action 模式的参考实现。

适用判断不难做:如果你在做一个「人用界面、AI 也用」的应用——内部工具、客服后台、运营系统——action 六出口省掉的就是整个工具集成层。反过来,纯内容网站、没有 Agent 角色的传统 CRUD 应用,引入它没有收益。框架不锁模型也不锁托管,迁移成本主要押在「把业务操作重写成 action」这一步。

它真正提出的问题比框架本身更重:当 AI 客户端(MCP)、Agent 互操作(A2A)和人类界面需要同一批能力时,API 层是否还应该是「只有浏览器调用」的私有层。agent-native 给出的答案是把六个协议当成同一个函数的六种渲染。这个模式能否成为主流还看不准,但方向上与 MCP 生态过去一年的扩张是同一条线——应用的能力面正在从「给人用的页面」扩展成「人与 Agent 共用的一组操作」。

来源:

  • GitHub:BuilderIO/agent-native(仓库 README、License)
  • 官方文档:Actions Overview / Getting Started / Agent Teams / Automations(agent-native.com/docs)