我最近越来越不相信”一个 AI 工作台解决所有问题”这种说法。

听起来当然舒服:一个聊天框,一个上下文入口,一个任务列表,一个文件入口,最好还能自动读笔记、查日历、改代码、定时推送。真正用起来以后,麻烦通常不是模型不够聪明,而是状态不知道归谁管。模型带着一版上下文,本地配置留着一版,某个定时任务还在跑旧逻辑,Obsidian 里又写着我真正想执行的计划。

所以我现在不太把这套东西当成一个产品看。我更愿意把它当成一个很小的分布式系统。核心问题不是”哪个 agent 最强”,而是:“这份状态是谁的?谁可以写?写完之后怎么验证?”

目前我的答案大概是这样:

  • Codex 管交互式工程事务。
  • Hermes 管后台定时执行。
  • Obsidian 管人能读懂的计划。
  • CC Switch 管共享工具和 provider 这些底层管道。

先定 ownership contract

我现在先给每一层定一个很窄的接口。

主要读取主要写入不该接管什么
Codex当前仓库、本地配置、PDF、工作区实时状态patch、验证结果、草稿内容无人值守的周期任务
Hermescron registry、job prompt、Hermes workspace、受限 toolset定时报告、维护结果、job 状态睡觉时自动改高风险仓库
ObsidianAGENTS.md、route map、Home、Now、Board、daily note、项目笔记人能读懂的计划、source record、日志、reviewagent 的隐藏状态
CC Switchskill registry、provider 配置、客户端运行状态共享工具可见性、provider routing项目意义和个人计划

这个表比具体工具更重要。因为一旦出问题,我需要知道该查哪一层。否则所有问题都会变成一句没用的话:“AI 系统又乱了。“

Codex 是一个 transaction boundary

Codex 负责我在场时的高信任工作。一个 Codex 任务最好是一条完整的事务:先读当前状态,再做有边界的修改,然后验证,最后汇报具体变化。

所以我会让它改仓库、查配置、跑构建、审文档、看 PDF、修失败的测试。它适合做这些事,是因为它离现场近:能读文件,能看真实配置,能跑命令,能在不确定的时候停下来问我。

但我不把 Codex 当默认 scheduler。它可以做自动化,但长期无人值守任务需要另一套约束:固定范围、固定输出、可观察的 last run 状态、保守的写入权限。

这就是 Hermes 的边界。

Hermes cron 负责周期性状态维护

Hermes 的 cron registry 里,每个 job 都有 schedule、prompt、skill、toolset、last run、next run、last status 这些字段。这里最关键的是 last status。一个没有状态记录的 AI 定时任务,本质上只是”到点再许一次愿”。

我现在会按维护的状态类型来理解这些 job:

状态类型例子维护什么
agent 运行状态daily-evolution, weekly-review, daily-git-commitHermes workspace、运行经验、版本化本地状态
vault 状态obsidian-morning, obsidian-nightly, obsidian-weekly, obsidian-healthdaily note、Board、route-map health、项目/课程/研究页面
信息流daily-ai-news, arxiv-daily-digest去重后的 AI 新闻和论文 intake
桌面和 runtime 卫生desktop-screenshot-cleanup, hermes-auto-update-and-health-check截图归档、更新检查、运行时健康

目前日常节奏是错开的:daily-evolution 在 00

跑,daily-git-commit 在 01
,Hermes health check 在 03
,AI news 在 08
,Obsidian morning pass 在 08
,ArXiv digest 在 09
,Obsidian nightly pass 在 22
,screenshot cleanup 在 22

慢一点的整理放到周任务里:weekly-review 是周一 00

obsidian-weekly 是周五 18
obsidian-health 是周日 21

这些时间点本身不是重点。重点是 owner 明确。AI 新闻重复了,就看 news job 的去重上下文。vault 过期了,就看 Obsidian job 有没有按 route map 读写。运行时行为漂了,就查客户端和 provider plumbing,而不是怪 Codex 那个聊天界面。

状态流是这样跑的

大多数周期任务其实都走同一条路径。

flowchart TD
  A["Cron tick"] --> B["Hermes job registry"]
  B --> C["Prompt + skill + toolset"]
  C --> D{"State class"}
  D --> E["Vault: route map -> daily note / Board / logs"]
  D --> G["Feeds: sources -> dedupe -> briefing"]
  D --> H["Runtime: update check -> health report"]
  E --> I["Bounded write surface"]
  G --> I
  H --> I
  I --> J["Short report or quiet no-op"]

这里真正有用的是 bounded write surface。vault job 应该从 route map 和允许的顶层页面开始,不应该在仓库里乱逛。截图清理应该移动明确的截图文件,不应该碰桌面上别的东西。新闻 job 应该和最近输出去重,不应该每天重新发现同一个 release note。

所以 cron 对我来说不是”定时跑 prompt”。它更像一组状态 reconciliation loop。

Obsidian 是可见的 second brain

Obsidian 是人能读懂的那层。我的计划要落在 Now、Board、daily note、reading queue、research map、course note、project synthesis 这些页面上,而不是只留在某个 agent 的隐藏上下文里。

这套设计不是我从零发明的。它借了 Andrej Karpathy 的 LLM Wiki 模式,也就是现在很多人说的 AI-maintained Obsidian second brain:知识留在普通 Markdown 里,Obsidian 是可读的 frontend,LLM 负责维护 wiki 结构,而不是把所有东西藏进聊天记录。这里真正有价值的不是”AI 会写笔记”,而是 raw material、synthesis、index、log 都是我能打开检查的文件。

但我没有照搬 starter layout。常见的 LLM Wiki 结构大概是 raw/wiki/index.mdlog.md,再加一个 agent instruction file。我的 vault 要同时服务 daily planning、coursework、research、paper reading 和 automation log,所以最后变成了一个 human-first 的编号结构:

区域作用
Root filesHome.mdNow.mdInbox.mdAGENTS.mdindex.md,以及作为指针的 root log.md
00 System/templates、route map、raw/source material、operation logs、assets、runtime residue
01 Daily/按日期命名的 daily notes
02 Work/active projects、coursework、Board、dev logs、reviews、presentations、people
03 Research/research maps、paper notes、reading queue、methodology notes、synthesis
04 Knowledge/reusable concept notes 和 study explainers
99 Archive/过期计划、历史材料、legacy shells

技术上的连接点是 route map。Agent 不应该硬编码 wiki/raw/Projects/、root Logs/ 这种路径,而是通过 00 System/obsidian-second-brain/routes.json 去解析 dailyworkresearchknowledgerawlogsboardreading_queue 这些逻辑 route。

这个小文件让 vault 同时对人和 agent 都可用。我可以改 visible structure,而不用重写每个 prompt。cron job 也仍然知道 daily note 写到哪里、operation log 追加到哪里、raw source material 应该落在哪一层。

写入前还有一个 control-plane read。Vault job 在动内容前,应该先读 AGENTS.mdindex.mdHome.mdNow.md 和 route map。AGENTS.md 是操作手册,index.md 是 catalog,Home.mdNow.md 是人看的状态面,route map 负责把逻辑目标解析成具体路径。

还有一条 exclusion contract。.codex/.opencode/.gemini/.obsidian/.venv/.smart-env/.omc/copilot/ 这些 hidden/runtime folders 可以存在,但普通 vault health 不应该把它们当成知识内容来扫。

vault job 还必须写 operation log。这个要求有点土,但很必要。我不想让一个后台 agent 悄悄”整理”我的工作,然后什么痕迹都不留。夜间任务如果更新了 daily note,或者把某个项目状态浮到首页,我之后应该能查到它动过什么。

CC Switch 只做管道

CC Switch 管共享 skills、provider routing、不同客户端的运行时可见性。它不应该变成 planner,也不应该接管项目意义。它的价值在于减少环境漂移。

很多问题表面上像 agent 坏了,其实是管道问题:一个客户端看得到某个 skill,另一个看不到;provider 在两个地方配置不一致;PATH 有噪声,看起来像缺二进制,其实可用命令还在另一条路径里。这些都应该按 plumbing 问题查,而不是上升成”AI 工作流不可靠”。

我实际使用的 routing rule

这个路由规则其实很简单。要改真实文件、还要验证的,用 Codex。会周期性重复、写入边界又很窄的,放到 Hermes cron。明天还要读的计划和长期约定,写进 Obsidian 或项目级 instruction。问题如果出在 skill、provider、客户端可见性,就查 CC Switch。

先手动跑一遍这个习惯很重要。不是所有有用的动作都应该立刻变成 cron。很多事情我会先让 Codex 跑一次,看清楚输入、输出和失败模式,再决定它有没有资格交给 Hermes 长期跑。

我主要防的失败模式

这套系统还是会乱。区别是,乱的时候更容易定位。

第一类是 duplicate ownership。旧的 Codex automation 和新的 Hermes cron 如果都以为自己负责同一个晨报,我就会收到重复推送,甚至看到两个版本的总结。所以现在 recurring work 的 active owner 是 Hermes cron,旧 Codex automation 只当审计记录,除非我明确重新启用。

第二类是 stale instruction。项目 instruction、route map 或笔记都可能过期。配置、schedule、enabled tools、当前文件状态这些问题,agent 必须先查现场。

第三类是 unbounded writes。一个 prompt 如果只写”整理我的 vault”,范围太大。更合理的写法是:“读 route map,更新今天的 daily note,追加 operation log,不碰 hidden/runtime folders。”

清理任务也很容易出事。所以桌面截图 job 是移动到 archive,不是永久删除。这个方案不优雅,但可逆。

最后一类是假成功。job 跑完不代表它做对了。所以定时任务要有 last status、可见输出,以及之后能审计的日志。

现在这套东西到底是什么

这不是一个全知助手。它更像一套操作模型,用来约束几个不完美的 agent。

Codex 给我可验证的交互式修改。Hermes 负责让周期性状态不要腐烂。Obsidian 留下我自己能读懂的计划。CC Switch 让共享运行时不要漂得太远。

这比”一个统一工作台”没那么好看。但当系统撒谎、重复、丢失上下文,或者把状态写错地方时,我至少知道该从哪一层开始查。