跳到正文
Hacker News· nicchia·· 6 天前AI 评分58

Trama 发布:在写代码前把智能体的改动画成状态机

Trama – See your agent's changes as state machines before any code

AI 导读

Trama 是一个 VS Code 与 Cursor 扩展,让智能体先把应用写成状态机地图,再据此生成代码。地图以纯 Markdown 存放在仓库的 .trama/ 目录,由模型、需求、提案、任务和漂移组成,图表自动生成且只读。

正文 · AI 翻译

Tasks · Requirements · Analysis · Map · Agents

你的 AI agent 写代码很快。Trama 确保它写的是你想要的那份代码。

The Diagram of the shop's Order Machine, then the Payment Machine

当大部分代码都由 agent 编写时,很容易搞不清你的软件到底在做什么。每一次提示都会加入没人看过的行为。

Trama 为你和你的 agent 提供一份共享的应用地图:它能处于的每一种状态,以及是什么把它从一种状态推进到下一种。agent 用纯文本编写这份地图,Trama 据此自动绘制出图表,且始终是最新的。你永远不用拖拽方框或画箭头。agent 在写下一行代码之前会先读这份地图。

看看实际效果

让我们给一个小型网店加上退货功能:就是 Trama 自带的那个 商店示例。

1. 说出你想要什么

像跟同事说话那样写下来。一行就够了,也可以写满一整页。从标签页的菜单里发送;关闭标签页也会发送。

Writing a design request in Trama

你的 agent 会立刻在你已经在用的聊天或终端里接手,并开始阅读地图。

2. 回答几个问题

agent 只问它自己无法决定的事。对于退货,它问了九个问题,第一个是如何对一次配送建模,因为 14 天是从配送开始算的。每个问题都预先选好了 agent 的建议,所以大多数时候你只需确认。跳过你不在乎的那些:agent 会采用它的建议,并把它列为一条假设供你核对。

The agent's questions, with its recommended answer already selected

3. 在任何代码存在之前就看到改动

当 agent 完成后,在地图上选中它的 Proposal:新增部分为蓝色,删除部分为红色。在这里,退货引入了一个新的 Actor——时间,它负责关闭退货窗口。侧边面板汇总了每一项决策和每一条假设。

The returns Proposal drawn on the map, with its decisions beside it

在看板上,Proposal 列出了它触及的每一个文件。批准它,或者附上备注拒绝它。

The Proposal on the Board, with Approve and Reject

4. 看着它被构建出来

批准后,agent 会对照代码检查改动了什么,每个 Machine 一个子 agent,并行进行。

The scan of the approved Proposal, with one sub-agent per Machine

随着 agent 准备任务,任务会出现在看板上。

Tasks appearing on the Board while the agent prepares them

退货设计变成了九个 Task,归在它下面。

Nine Tasks grouped under the returns design

点击 Run this design,agent 会逐一处理它们,而你可以全程跟进。

5. 知道代码和地图何时不一致

当代码做了地图没有说明的事,或违反了你的一条规则时,Trama 称之为 Drift。

Drift 不是 bug 报告。它只是说代码和地图不再讲述同一个故事,而且它不判定哪一个是对的:

  • 代码可能是错的。 agent 误读了一个 Task,或者一次快速的手动修复漏掉了一种情况:这是个 bug。
  • 地图可能过时了。 你在写代码时改了主意,或者代码处理了一种没人想到要画出来的情况:代码是对的,地图应该跟上。
  • 两者可能都合理。 对地图从未提出的一个问题,有两种都成立的答案:这是只有你能做的决定。

那些既不改变图表也不改变你任何规则的细枝末节不算 Drift:只有当行为本身不同时,Trama 才会提出一个。

每个 Drift 都会显示发生了什么、应该发生什么,以及两到五种修复代码的方式,agent 的建议排在最前面。你选一个。或者你保持代码原样,地图随之更新以匹配。在你决定之前,agent 不会启动任何涉及应用那部分的 Task,所以不会有新东西建立在摇摇欲坠的地基上。

6. 一次性设定规则

技术栈、设计、数据、业务规则:写一次,放在地图旁边,agent 会在每个任务中遵循它们。

规则随地图一起生长。退货设计也加了自己的规则:窗口在交付后第 14 天的 23:59 结束,退货覆盖整个订单,退款为全额。每条规则都绑定到地图上它所适用的确切部分,就像 order/Delivered。

Requirements next to the map: data, business rules and interface

是的,它比原始的 vibe coding 慢

Trama 仍然是 vibe coding:你描述你想要什么,agent 来写代码。改变的是中间发生的事。

用原始的 vibe coding,你输入一个提示,代码就出现了。用 Trama,你回答问题、在地图上查看变更、批准它,然后 agent 才写代码。每个功能都需要更多步骤,你会感受到这一点。

这些时间没有浪费。它花在了最划算的地方:

  • 在构建之前做决定。现在回答一个问题,比以后重建一个功能更便宜。在地图上改一行只需一秒;拆掉走错方向的代码要花一下午。
  • 永远不用解释两次。地图和你的规则留在仓库里。每个新会话、每个 agent、每个队友都从已经决定好的内容开始,而不是从空白的聊天开始。
  • 在错误还小的时候抓住它。Drift 会在扫描时立即标记出偏离地图的代码,趁更多功能还没堆到它上面。
  • 让 agent 并行工作。因为每个 Task 都绑定到地图上清晰的部分,多个 agent 可以同时构建而不会互相干扰。

第一个功能更慢。第五十个不会,因为应用仍然是你理解的那个。

如果你在做一个周一就会扔掉的周末原型,原始的 vibe coding 就够了。Trama 是为你想长期保留的软件准备的。

已经有项目了?

把 Trama 指向你现有的代码。agent 会绘制出你的应用今天所做的事情的地图,并在此过程中标记出任何看起来不对的地方。

名字的含义

Trama 在意大利语中是 weft(纬线):织工在织机上来回穿梭的线,直到图案出现。布一旦织成,图案就固定了。你无法通过拉扯一根线来改变它:一根线被拉偏会立刻显现,而新的图案必须有意地织出来。

这就是 Trama 背后的理念。你的 agent 是一个极快的织工,而地图就是图案。对设计的每一次更改都是有意识地织入的,作为你批准的 Proposal,而代码中一根被拉偏的线会显示为 Drift。

在意大利语中,trama 也是故事的 plot(情节):发生了什么、以什么顺序、为什么。你的应用可能处于的每个状态、以及推动它前进的每个事件的地图,正是如此。

这些字母拼出了其中的内容:

  • Tasks:agent 接手的工作,在一个你可以跟踪的看板上。
  • Requirements:你的应用必须如何构建,写一次,每次都遵循。
  • Analysis:agent 将你的代码与地图进行比较,并告诉你它们在哪里不一致。
  • Map:你的应用可能处于的每种情况,为你绘制成图表。
  • Agents:与你已经在用的那个配合使用:Copilot Chat、Cursor、Claude Code 或 omp。

试试看

Trama 在 VS Code 和 Cursor 中运行,支持 Linux(x64)和 macOS(Apple silicon)。

  1. 安装扩展。从 Releases 下载适合你平台的 .vsix,然后从命令面板运行 Extensions: Install from VSIX…,或者:

    code --install-extension trama-<platform>-<version>.vsix

    trama 命令行包含在扩展中,所以无需安装其他东西。

  2. 在初始化项目之前,先在 Settings(trama.agent)中选择你的 agent:

    • chat(默认):VS Code 中的 Copilot Chat,或 Cursor 中的聊天。
    • claude:终端中的 Claude Code。同时将 trama.skillsDir 设为 .claude/skills,以便 Claude Code 找到 Trama 的技能。
    • omp:终端中的 omp。

    终端 agent 必须已安装并位于你的 PATH 中。

  3. 打开你的项目并运行 Trama: Open。

  4. 选择 Initialize Project 从头开始,或选择 Import from Code 用于现有应用。

  5. 点击 Design… 并描述你的第一个功能。

Settings

对于 Claude Code、使用意大利语写作,典型设置如下:

设置 默认值 作用
trama.agent chat Trama 将指令发送到哪里:chat、claude 或 omp。
trama.skillsDir .agents/skills Initialize Project 将 agent 技能安装到哪里。Claude Code 请使用 .claude/skills。
trama.language 空 agent 所写文本(描述、Proposals、Tasks、Drifts)的语言,例如 Italian。代码、名称、标题和 ID 保持英文。
trama.terminalLocation panel 终端 agent 在哪里打开:panel(终端区域,后台)或 editor(代码旁边的标签页)。
trama.analysis 空 用于设计请求、Drift 解决和导入的模型。
trama.scan 空 用于扫描的模型,包括比较每个 Machine 的子 agent。
trama.execution 空 用于实现 Tasks 的模型。
trama.autoScan true 在你批准 Proposal 后,扫描它更改的内容并创建 Tasks。
trama.autoExit true agent 的终端完成后立即关闭。
trama.maxParallelAgents 20 agent 可以同时运行多少个子 agent。
trama.submitWhileRunning disabled enabled 让你在另一个运行进行中时启动一个运行。
trama.driftAutoPilot disabled 让 agent 自行解决 Drifts:enabled 用于非关键项,yolo 用于所有项。

对于这三个模型设置,请按你的 agent 接受的方式填写模型名称,或留空以使用 agent 的默认值。在聊天中,它们选择新对话的模型:在 Copilot 中,是使用该名称的模型;在 Cursor 中,是对话的起始模型。除 trama.autoScan、trama.skillsDir、trama.language 和 trama.submitWhileRunning 之外的每个设置都只存在于你的用户设置中,因此无法按工作区覆盖。所有细节都在 扩展 README 中。

工作原理

flowchart LR
  subgraph repo[".trama/ in your repo"]
    M[Model]
    R[Requirements]
    W[Proposals · Tasks · Drifts]
  end
  E[Editor extension] -->|reads, renders| repo
  E -->|sends instructions| A[Your agent]
  A -->|loads| S[Skills]
  A -->|explores, writes through| C[trama CLI]
  C --> repo
  R -.->|generated into| S
  A -->|writes| Code[Your code]

Loading

一切都是你仓库中的纯 Markdown。.trama/ 与你的代码放在一起并随其进行版本控制:model/ 中的 Model、requirements/ 中的 Requirements,以及 proposals/、tasks/ 和 drifts/ 中的工作。没有数据库,没有云服务,没有账户。

Model 是一组状态机。一个 System 被拆分为 Features。每个 Feature 将 Machines 分组,每个 Machine 是一个文件,列出其 States、推动它变化的事件(Events),以及每次变化导向何处,条件以纯文本形式书写。States 可以嵌套。Machines 从不互相调用:它们对 Events 做出反应,这些 Events 由其他 Machines 或 System 外部的 Actors(用户、支付提供商、时间)发出。Diagram 由这些文件生成并自动布局。它是只读的:要更改它,你向 agent 请求一个 Proposal,这样文件始终是唯一事实来源。文件格式。

需求变成技能。 需求被分组到 Area(ui、tech、quality、data、rules 或你自己的)中,再拆分成片段。每个 Area 和片段都会说明 agent 何时需要它,而每个 section 适用于整个 System 或某个 Feature、Machine 或 State。每当 Requirement 文件发生变化,Trama 都会将它们重新生成为 agent 技能(trama-req-<area>-<fragment>),并以那个“何时”作为技能描述。agent 自己的技能加载器随后只会拉取与当前任务相关的规则。超过大小预算后,每个 Area 会改为一个索引技能,因此庞大的规则手册永远不会淹没 agent 的上下文。

Agent 通过 CLI 操作。 trama CLI 是一个随扩展一起打包的单一二进制文件。agent 用它来探索 Model(trama machine order、trama paths order Draft Shipped、trama search refund)、检查它(trama validate、trama analyze),并创建 Proposal、Task 和 Drift。它从不读取你的代码:将 Model 与代码进行比较是 agent 的工作。

技能驱动工作流。 trama init 会将五个 agent 技能安装到你的项目中,每个技能对应循环中的一步:

技能 作用
trama-design 分轮向你提问,然后编写一个 Proposal
trama-scan 将 Model 和 Requirements 与代码进行比较;提交 Task 和 Drift
trama-implement 将 Task 转化为代码;当无法遵循 Model 时提交一个 Drift
trama-resolve-drifts 询问你如何解决每个 Drift,然后将你的选择记录在一个 Proposal 中
trama-import 将现有代码描述为 Proposal

没有你,什么都不会改变。 一个 Proposal 包含它所触及的每个文件的完整新版本,并且在你看到它之前必须通过针对整个 Model 的验证。在你批准之前,什么都不会改变。批准、拒绝或解决 Drift 等决定由你做出:agent 只会在你明确要求时执行这些操作。未解决的 Drift 会阻止关于 Model 同一部分的所有 Task,直到你解决它。

为并行 agent 而构建。 一次扫描会将每个 Machine 分配给各自的子 agent。实现运行会按组分配 Task,这些组触及 Model 的不同部分。在你批准一个 Proposal 后,只会再次扫描它所更改的内容。

编辑器从不调用模型。 该扩展渲染 Diagram、Board 和 Requirements,在自己的面板中显示 agent 的问题,并将指令发送给你选择的 agent。所有推理都在你的 agent 中、使用你的订阅进行。

了解更多

许可证

Trama 是在 GNU AGPL v3 下开源的:使用它、修改它并分享它,只要你的更改也保持开源。

想在闭源产品中使用 Trama?联系我们 获取商业许可证。

Copyright © 2026 Luca Soda

来源:Hacker News · github.com