浏览器端开源工具支持拖拽编辑 Agent 工作流(触发、LLM 节点、路由、记忆、子 Agent),完全本地运行,并展示 Agent 协作开发 Agent 的工程创新。
我一开始并没打算做一本日记。我原本想做的是一块画布。
agent-flow-canvas 是一个运行在浏览器里的 AI Agent 工作流可视化构建器——拖出 Trigger、LLM 节点、Router、Memory 模块和 Subagent,把它们连接起来,按下运行,就能在自己的浏览器标签页中实时观察整个图的执行过程。无须下载,无须安装,无须登录。你的 API keys 始终保存在 localStorage 中,绝不会经过任何由我控制的服务器——它们会直接从你的浏览器发送到 OpenAI、Anthropic、Gemini、Ollama,或者你指定的任意 OpenAI-compatible endpoint。整个运行链路根本没有 backend。这就是最初完整的设计要求:keys 由你提供,工作由浏览器完成,而我两者都看不到。
但真正触动我的,并不是这一点。
真正触动我的,是一个我从没打算亲手编写的文件:test_result.md。
为了把这个项目从“单一硬编码 gateway”推进到“支持多个 provider、自带 key、完全在客户端运行”,前后经历了 84 次 commit。在这个过程中,一直有 Agent 和我并肩构建——一个 main agent 负责编写代码,一个 testing agent 负责验证。而它们之间的协作协议,既不是 Slack thread,也不是 commit message,而是一个共享文件。它的结构像一本实验记录:任务名称、修改过的文件、优先级、working 是 true 还是 false;每项下面还有一段 status_history——一份按时间依次堆叠的日志,记录谁处理过它、当时如何判断,以及为什么会得出这样的判断。
回头再读这个文件,它读起来并不像文档,更像一本日记。
“将单一的 GatewayConfig 替换为持久化到 localStorage 的 Gateway[] 库。迁移旧版单 gateway。Manager UI 支持添加、编辑、删除、切换 provider、显示或隐藏 key、清除所有 keys,以及不含 keys 的导出。已提供隐私提示横幅。”——main agent
“已测试 gateway manager 功能……清除所有 keys 的功能正常——会擦除 API keys,并为需要 keys 的 gateways 显示警告图标……所有核心功能均按预期运行。”——testing agent
两个声音,两种不同的职责。一个为自己构建的东西陈述理由,另一个则检查它在接触现实之后能否继续正常工作。这不是 changelog,而是通信往来。
这里有一个结构上的巧妙之处,它并非出自我手,而是来自这套协议:这个文件不允许只写一句“done”。它必须说明尝试了什么、哪里出了问题、修复了什么,以及修复是否真的经受住了验证。其中有一个叫作 stuck_count 的字段——每当同一个问题再次被解决、又再次出错时,这个数字就会增加。它不是一个状态标记,而是一个系统在坦白:自己正在原地打转。
我也写过这样的日记。不是关于 gateway manager,而是关于我自己。同样的记录,不同的日期;同样的伤口,略有不同的措辞。因为我其实什么都没解决,只是越来越擅长描述问题。stuck_count 是我写纸质日记时始终没有足够自律去记录的指标。Agent 却默认拥有它,因为没人告诉过它,坦白也可以是可选项。
构建接近尾声时,日志记录的已经不只是发生了哪些变化。它写道:
“纯 frontend 重构。运行链路中没有 backend calls……不需要真的调用真实 LLM——但我们应该确认运行过程能够执行 schematic 中的非 LLM 节点,并在 run drawer 中产生日志……validate、code-view、sample walkthrough、JSON export/import 等现有流程仍应正常工作。”
这不是 spec。这是一个 Agent 给未来版本的自己留下的便条——也可能是写给读取同一份文件的另一个 Agent——把自己的推理过程解释清楚,以便日后无论接手者是人还是其他什么,都能重新拾起这条线索,而不必再追问当初为什么要这样做。
严格来说,记录日记并不是这个工具的重点。重点在于:打开它之后,你会看到八种节点类型——Trigger、LLM、Tool、Router、Memory、Subagent、Human 和 Sink。你不需要写一行代码,就能构建一个真正的 Agent graph;然后点击 view code,它就会生成可直接带走并运行的 Python 或 JavaScript 代码。项目采用 MIT license。你可以把静态构建产物托管在任何地方——GitHub Pages、Cloudflare、Netlify,都无所谓,因为根本没有需要操心维护的 server-side 部分。
然而,在拖放交互的表层之下,这个工具本身正是由那本日记构成的。画布里的每个 LLM 节点,从结构上看,都与编写 test_result.md 的那个东西属于同一类:它先采取行动,然后必须为自己的行动作出说明,之后还要接受另一个对象的检查,而后者不能只听信它的一面之词。
Self-documentation 并不是可以事后附加到 Agent 上的功能。正是它,让某个东西成为 Agent,而不只是 script。script 运行,然后退出。一个写日记的系统会运行,随后还必须面对并回应自己的历史。
那么,当你在 agent-flow-canvas 中连接出一个 graph 时,真正得到的究竟是什么?它不只是一套 automation。如果构建方式正确,你得到的是这样一种东西:它会在每个“做了什么”的背后,留下一条“为什么这么做”的轨迹。
不管你是否给它起过名字,你其实一直都在做这件事。你参加过的每一次 retro,你写过的每一份不止一句“fixed bug”的 PR description,你提交过的每一条比实际需要更长的 commit message——那都是你在维护一份与 Agent 相同的文件。你解释当时的决定,是为了让下一位读者——很可能是未来版本的你——不必只通过 diff 反向推断你的思考过程。
日记并不是 Agent 发明的。它只是终于不再为公开记录日记而感到难为情。
构建 graph,让它在你自己的浏览器标签页中运行。让你的 keys 留在它们本就存在的地方。等到你构建的东西日后必须解释自己时——而它一定会遇到这样的时刻——请确保它留下了一些值得阅读的内容。
agent-flow-canvas 采用 MIT license,现已上线:agent-flow-canvas.vercel.app。GitHub 源代码:github.com/Jacobcdsmith/agent-flow-canvas。
如果还要采取进一步行动,你可以考虑屏蔽此人和/或举报滥用行为。