【免费下载链接】routa
Workspace-first multi-agent coordination platform for AI development, with shared Specs, Kanban orchestration, and MCP/ACP/ A2A support across web and desktop.
Routa 是一个 Workspace-first 的 AI 多智能体开发平台,它同时提供Web 端(Next.js)和桌面端(Tauri + Rust)两种运行形态。两种形态、两套后端,却必须对用户呈现完全一致的行为——靠什么保证?答案就在仓库根目录的那份 api-contract.yaml:一份 OpenAPI 3.1 契约文件,定义了 158 个 API 端点,是 Web 与桌面端 API 的单一事实来源(Single Source of Truth)。
这篇文章带你走一遍 Routa API 契约的实战流程:契约长什么样、如何自动验证双端一致性、以及新增接口时的标准动作。
为什么"双后端 API 一致性"这么难
想象一下:同一个看板界面,在浏览器里由 Next.js 服务(端口 3000)驱动,在桌面客户端里由 Rust/Axum 服务(端口 3210)驱动。
如果没有契约约束,时间一长两边必然"漂移":
- Web 端加了
PATCH /api/workspaces/{id},桌面端忘了同步,桌面用户更新工作区标题就 404 - 两端返回的字段名不一致(一个叫
taskId,一个叫task_id),前端组件时好时坏 - 错误码一个返回 400、一个返回 500,用户看到的报错信息对不上
Routa 的解法写在架构决策记录 ADR-0001 双后端语义对等 中:Web 与桌面是一个产品的两个运行时形态,必须共享同一套领域词汇(workspace、session、task、kanban board),并暴露由api-contract.yaml统一治理的 API 形状。
api-contract.yaml 长什么样:契约的核心结构
打开 api-contract.yaml,头部声明就说明了它的地位:
Single source of truth for the Routa.js dual-backend API. Both the Next.js backend (src/app/api/) and the Rust backend (crates/routa-server/) MUST implement all endpoints defined here.
契约声明了两个服务地址(api-contract.yaml):
servers: - url: http://localhost:3000 description: Next.js backend (dev) - url: http://localhost:3210 description: Rust backend (desktop)共享的领域枚举:两端"说同一种语言"
契约的components.schemas部分定义了共享数据模型。比如任务状态(api-contract.yaml):
TaskStatus: type: string enum: [PENDING, IN_PROGRESS, REVIEW_REQUIRED, COMPLETED, NEEDS_FIX, BLOCKED, CANCELLED]无论 Next.js 还是 Rust,返回的任务状态都必须是这 7 个值之一。前端只需实现一次状态渲染,两端通用。
端点定义:路径、参数、响应一个不落
以健康检查为例(api-contract.yaml):
/api/health: get: operationId: getHealth responses: "200": schema: type: object required: [status, timestamp]再看创建智能体(api-contract.yaml)——请求体明确要求name和role,role必须引用共享的AgentRole枚举(ROUTA / CRAFTER / GATE / DEVELOPER),成功返回201并包含agentId与agent对象。契约把"入参要求什么、成功返回什么、失败返回什么"全部写死,两个后端照着实现即可。
整个契约共覆盖 158 个端点,横跨 agents、tasks、kanban、notes、workspaces、sessions、shared-sessions、ACP、MCP、A2A、git、github、codebases 等模块,你可以直接通读 api-contract.yaml 的paths部分。
契约如何"自动守门":3 层验证命令
写契约只是第一步,Routa 的关键设计是:契约不是摆设,它被自动化验证反复执行。
第 1 层:静态 Schema 校验(不需要启动服务)
npm run api:schema:validate对应脚本 validate-openapi-schema.ts 会做 7 项静态检查:所有$ref能否解析、operationId是否唯一、响应 Schema 能否被 AJV 编译、枚举是否非空等等。契约文件本身写得对不对,这一步就能拦住。
第 2 层:三端路由对账(Parity Check)
npm run api:check这是最有意思的一步。check-api-parity.ts 会从三个来源提取路由清单并逐一比对:
- api-contract.yaml中声明的端点
- Next.js 文件系统路由:扫描
src/app/api/下的route.ts(src/app/api/ 共 245 个文件) - Rust 路由:扫描
crates/routa-server/src/api/(crates/routa-server/src/api/)下的.rs文件
任何一端缺失契约里定义的端点,或私自带了一个契约里没有的端点,都会被精确报出——"契约里有、Rust 里没有"和"Next.js 多写了一个"是两种不同的漂移,都会失败。
第 3 层:行为测试(同一套测试打两个后端)
前两层是静态的,第三层是真枪实弹。tests/api-contract/run.ts 实现了一套与后端无关的测试套件,覆盖 workspaces、agents、tasks、notes、sessions、skills、schema-validation 七大场景:
npm run api:test:nextjs # 打到 http://localhost:3000 npm run api:test:rust # 打到 http://localhost:3210同一套断言、两个 BASE_URL。如果 Rust 端的行为和 Next.js 端出现任何偏差(响应结构、状态码、负向路径的报错),测试就会在其中一个后端上失败。其中 test-schema-validation.ts 更进一步:对真实响应用契约里声明的 JSON Schema 做逐字段校验,覆盖 create → read → delete 全链路。
| 验证命令 | 验证什么 | 需要启动服务 |
|---|---|---|
npm run api:schema:validate | 契约文件自身合法性 | ❌ |
npm run api:check | 契约 vs Next.js vs Rust 路由一致性 | ❌ |
npm run api:test:nextjs/api:test:rust | 双端真实行为对等 | ✅ |
新增一个 API 端点:4 步标准流程
Routa 遵循**契约优先(Contract First)**原则:先改契约,再写代码。docs/fitness/api-contract.md 中规定的新端点流程:
- 📝 在 api-contract.yaml 中定义端点(路径、方法、参数、请求/响应 Schema)
- 🟦 在 Next.js 中实现:
src/app/api/下新建路由 - 🦀 在 Rust 中实现:
crates/routa-server/src/api/下新增对应 handler - ✅ 运行
npm run api:check验证一致性,并在 rust-api-test.md 端点矩阵中登记测试条目
修改现有端点更严格:必须先评估是否为breaking change,若是,则需要版本化或废弃旧端点、提供迁移文档、并在 PR 中明确标注——契约原则里写着"Breaking Changes 禁止:除非有迁移计划"(docs/fitness/api-contract.md)。
契约被破坏时会发生什么:Fitness 门禁自动拦截
Routa 把 API 契约检查纳入了 fitness(工程适应度)体系,作为硬门禁(hard gate):
- docs/fitness/api-contract.md:
openapi_schema_valid与api_parity_check两个指标均为hard_gate: true,通过阈值 100 分——也就是说,Schema 校验或路由对账任何一处不过,整个检查直接失败 - docs/fitness/rust-api-test.md:
api_contract维度权重 10,除npm run api:check外还挂了 Rust 侧的端到端测试cargo test -p routa-server --test rust_api_end_to_end,并按"端点 × 方法 × 成功/负向/回归路径"三层逐条登记 VERIFIED 证据
换句话说:没有契约覆盖的 API 进不了主干。CI 里api:schema:validate+api:check两道闸门跑不过,代码就无法合并。
动手看看:克隆仓库跑一遍
git clone https://gitcode.com/gh_mirrors/ro/routa cd routa npm install npm run api:schema:validate # 静态校验契约 npm run api:check # 三端路由对账前两条命令无需启动任何服务,几秒钟就能看到契约与两个后端的对账结果。想体验行为层测试,再分别启动 Next.js(npm run dev)或 Rust(cargo run -p routa-server),执行对应的npm run api:test:*即可。
小结:3 个值得借鉴的设计
- 单一事实来源:158 个端点全部声明在 api-contract.yaml 中,两个后端是"契约的实现者",不是"契约的作者"
- 分层验证:静态 Schema → 路由对账 → 行为测试,成本递增、可信度递增,且前两层零依赖即可运行
- 门禁化:契约检查不是"建议",而是 fitness 体系里的硬门槛,破坏契约的代码过不了 CI
对多形态产品(Web / 桌面 / CLI)来说,API 契约文件 + 自动化对账,是把"永远保持一致"从一句口号变成一条npm run api:check命令的最实际路径。
【免费下载链接】routa
Workspace-first multi-agent coordination platform for AI development, with shared Specs, Kanban orchestration, and MCP/ACP/ A2A support across web and desktop.
相关推荐
5分钟快速上手:Windows系统完美安装苹果苹方字体终极指南
5分钟快速上手:Windows系统完美安装苹果苹方字体终极指南 还在为Windows系统缺乏优雅中文显示效果而烦恼吗?PingFangSC苹方字体作为苹果公司精
前端插上 U 盘就能开播:my-tv 免费电视直播软件,装上就用、零门槛换台
插上 U 盘就能开播:my tv 免费电视直播软件,装上就用、零门槛换台 你想让老电视看直播,可大多点播软件要么要注册账号、要么有会员墙,而你要的只是一台开机就
音视频直播TREK 的 @trek/shared:用 Zod 契约包统一前后端 API 类型的单一事实源实战
TREK 的 @trek/shared:用 Zod 契约包统一前后端 API 类型的单一事实源实战 @trek/shared 是 TREK(自托管旅行规划应用)
后端前端MCP 服务AI 应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考