胶囊系统是一个运行在 Agent 基座上的 SE(Shell Engineering)项目。它没有传统的页面和 HTTP 接口,用户通过 Agent 输入自然语言。因此,这个项目不能理解成“Python 程序接收输入,然后从头执行到尾”。Agent 基座才是运行时主控,Skill 记录工作方法,CLI 和 Python 提供可以反复调用的确定性工具。本教材主要使用 Hermes 举例,但这套结构本身不依赖某个特定基座。
3.1 Agent 基座是运行时主控
传统应用通常有一个清楚的入口。网页应用从页面和接口接收请求,命令行工具从参数接收请求。比如,用户在网页上点击一个“设置”按钮,这是一个确定性的功能。
但是同学们,这一节我们要讨论一个极其重要的变化:到了 Agent 时代,入口本身变得不确定了。大部分时候,Agent 接收到的是自然语言,用户并没有把功能名称、参数和执行步骤逐项写出来。
以胶囊系统为例,它的入口是一段自然语言。用户可能输入“把这张图放进知识库”,也可能输入“看看刚才那份资料处理到哪里了”。系统首先要理解这句话对应什么意图,才能决定后面调用哪项功能。
这个入口由 Agent 基座承担。它负责理解用户语言,并根据当前上下文决定下一步是继续分析、询问用户、调用 Python 工具,还是发起人工审核。Hermes 可以承担这个角色,Codex 也可以。只要一个 Agent 基座能够读取 Skill、调用工具并处理结构化结果,就可以驱动胶囊系统。
Skill 可以视为 Agent 使用胶囊系统时的操作手册。它记录遇到什么意图应该调用哪个 Python CLI、信息不足时怎样继续询问,以及工具返回结果以后应该怎样处理。
所以,胶囊系统不是一个传统的 Python 程序,而是一个由 Agent 基座驱动的 SE 项目。Hermes 是本教材选用的兼容性测试环境,不是 SE 产品必须绑定的组成部分。
它采用的是 Agent 主导的工具调用方式:当前 Agent 始终留在最外层,根据 Skill 一步一步推进任务;需要执行确定性操作时,再调用 CLI 和 Python。
用户
↓
Agent 读取 Skill,理解意图
↓
Agent 判断下一步
├─ 直接进行语义理解
├─ 询问用户
├─ 调用 Python 工具
└─ 发起人工审核
↓
Python 执行一次确定性操作
↓
返回结果、状态和允许的后续动作
↓
Agent 继续判断下一步
其实并不复杂:不确定的、模糊的工作交给 Agent;确定的传统操作,比如 CRUD,交给 Python。Agent 决定下一步做什么,Python 保证这一步被正确执行。
3.2 Skill、CLI 与 Python 模块
Agent 虽然负责主控,却不适合处理确定性的操作,比如删除证据、修改知识页;Skill 也不适合保存工作状态(比如,我们无法在 Skill 里保存当前审核的处理进度)。
真正会改变数据的操作,仍然要交给传统的 Python 程序。这些程序需要能够测试和校验,失败以后也要有明确的恢复方式。
但如果让 Skill 直接指导 Agent 操作零散的 Python 函数,我认为是不靠谱的。这是一个工程稳定性的问题。
看过《程序员的 AI 编程绿皮书》的同学可以思考下,为什么 Skill 不适合直接操作零散的 Python 函数。
因此,这个项目不是只有一个 Skill,也不是一堆零散的 Python 函数。我采用的结构是在两者之间增加一层稳定的 CLI。还记得我们在教材前面使用过的网易云音乐 CLI 吗?这里采用的是同一种思路:
capsule-system/
├── skills/capsule-system/
│ ├── SKILL.md 记录意图识别与调用规则
│ └── references/ 命令、工作流和审核格式
│
├── src/capsule_system/
│ ├── cli/ 向 Agent 暴露稳定命令
│ ├── workflows/ 校验并记录流程状态
│ ├── extractors/ 提取 PDF、网页和音视频文字
│ ├── knowledge/ 处理知识页演化
│ ├── review/ 处理人工审核
│ └── persistence/ 访问飞书和本地状态
│
└── tests/ 验证工具、流程和最终结果
Agent 根据 Skill 调用少量稳定的 CLI 命令,CLI 再把命令分派给内部 Python 模块。至于某项功能在 Python 内部拆成几个函数,属于实现细节,不需要暴露给 Skill。以后即使重构 Python 代码,只要 CLI 契约没有改变,Skill 就不需要跟着修改。
从用户使用的角度看:
- Agent 基座是主控
- Skill 是它推进任务时遵循的工作方法
- CLI 提供稳定的调用入口
- Python 模块和函数负责执行具体操作、保存状态和保护数据边界。这几部分合在一起,才是胶囊系统第一版需要交付的完整产品。Hermes 或 Codex 这样的具体基座,可以根据开发和使用环境替换。
这是我根据工程经验总结出的一种成熟 SE 项目结构。如果你有更合适的方案,当然可以采用自己的;如果暂时没有,这套结构更符合当前 SE 项目的开发方式。
3.3 确定性处理与语义理解
接下来还需要决定,大模型究竟在哪些地方参与。最容易想到的分法是:确定性的工作交给 Python,不确定的工作交给 Agent。这个方向基本正确,但“确定”和“不确定”还不够准确,比如音频转写文字同样使用模型,却不一定要让 Agent 自由判断。
音频转写文字同样会用到模型,但这个模型并不是大语言模型。你可以把音频转换模型理解成一个函数,它和大语言模型的语义理解有很大的差异。
更合适的做法是把处理过程分成四层:
| 层次 | 负责的工作 | 胶囊系统中的例子 |
|---|---|---|
| Python 确定性处理 | 可以明确校验、重复执行和自动测试的操作 | 文件校验、PDF 文字提取、计算哈希、状态迁移、写入飞书 |
| 专用模型工具 | 目标单一,输入输出边界已经固定的模型任务 | 使用 faster-whisper 把音频转成带时间戳的文字 |
| Agent 语义理解 | 需要结合上下文理解含义、比较关系或组织内容的任务 | 理解用户意图、判断图片表达的知识、分析新旧观点、改写知识页 |
| 用户审核 | 系统无法可靠处理,而且继续执行会影响重要结果的判断 | 知识冲突、图片信息不完整、永久删除证据 |
这个划分意味着,第一版中的通用语言理解和视觉理解都由当前 Agent 基座完成。本教材在具体流程中使用 Hermes,但开发时也可以由 Codex 承担同样的语义任务。Python 没有必要绕过当前 Agent,再单独接入另一套通用大模型 API。否则,同一次运行中会出现两套模型配置、两套上下文和两套错误处理方式,主控边界也会变得模糊。
但 Python 仍然可以调用目标明确的专用模型。faster-whisper 虽然也是模型,但它承担的是“把语音转换成文字”这项边界清楚的工作。Python 可以检查音频格式、保存分段时间和识别质量,再把转写文字交给当前 Agent 理解主题。这和让通用大模型自由判断资料应该怎样进入知识库,不是同一类任务。
独立图片更能说明两者的区别。Python 可以检查图片格式、尺寸。但图片表达了什么,里面的流程是否完整,脱离外部说明以后能不能形成证据,这些都需要具备视觉能力的 Agent 基座理解。Agent 给出结构化判断以后,Python 还要检查字段、状态和处理条件;无法确认的重要内容则进入人工审核。
3.4 Agent 基座与 Python 的往返调用
确定职责以后,整个系统就不能设计成“Skill 调一次 Python,然后 Python 从头做到尾”。这种线性流程基本不可能处理复杂的 SE 项目。
一份资料从进入系统到改写知识页,中间通常需要多次语义理解,也需要多次调用 Python。
那么这里会出现一个问题,谁是主控方?我的建议是不同的项目应该选择不同的主控方。对于以自然语言为入口的 SE 项目,把 Agent 基座放在最外层通常更简单,但也会增加不确定性。
如果把 Agent 基座作为主控,它就始终留在最外层。每次调用 Python,只完成当前一次明确的操作,然后把结果交还给 Agent。Agent 读完结果,再结合 Skill 决定下一步。
还是拿 PDF 来举例。下面继续用 Hermes 表示当前运行的 Agent。用户输入“把这份 PDF 放进知识库”以后,实际过程更接近下面这样:
- Hermes 理解用户要处理一份 PDF,于是调用 Python 提取文字。
- Python 提取文字,把临时结果返回给 Hermes,此时不保存证据。
- Hermes 阅读文字,判断资料的主题和知识价值。
- Hermes 调用 Python 查询可能相关的知识页。
- Python 返回候选知识页及其版本信息。
- Hermes 比较新旧知识,判断它们是补充、重复还是冲突。
- Hermes 决定更新知识页、结束处理,或者请求人工审核。
- Hermes 再调用 Python 执行相应操作,全部完成以后才保存最终结果。
整个过程可以压缩成一个不断往返的循环:
Hermes 思考
↓
调用 CLI 和 Python
↓
Python 返回结果
↓
Hermes 继续思考
↓
再次调用 CLI 和 Python / 询问用户 / 发起人工审核
使用 Agent 基座主控的好处在于,不存在 Python 调用当前 Agent 会话这种情况。Python 只需要返回机器可以读取的结果。例如,PDF 文字提取完成以后,它可以返回临时文字、结果状态和允许的后续动作。Hermes 在这个例子中读取这些字段,然后根据 Skill 继续处理。
{
"status": "extracted",
"text": "PDF 提取出的文字……",
"allowed_actions": [
"analyze_evidence",
"discard_evidence"
]
}
你也可以把它理解成一个由 Agent 基座主控的动态工作流。工作流里有些节点需要 Agent 理解语义,有些节点需要 Python 执行确定性操作。究竟进入哪个节点,由当前 Agent 根据 Skill、上下文和工具返回结果继续判断。
3.5 主控权与写入边界
Agent 基座是主控,但主控不等于它可以绕过规则直接修改数据。这种方案最大的问题还是大模型的天生缺陷:不确定性。
大模型可能误解用户意图,也可能在长对话中漏掉前面的限制。如果所有写入都由 Agent 自由决定,一次错误判断就可能跳过审核,把尚未确认的内容直接写入知识库。
因此,Python 还要建立“门”,检查必要的写入限制。Agent 决定要做什么,Python 则根据现有数据和项目规则检查这项操作能不能执行。例如,Hermes 请求把一条尚未审核的冲突证据写入知识库,Python 应该拒绝这次操作,并返回拒绝原因和当前允许的处理方式:
{
"status": "rejected",
"reason": "evidence_requires_review",
"allowed_actions": [
"request_review",
"discard_evidence"
]
}
Hermes 读取这个结果以后,可以按照 Skill 发起人工审核,也可以询问用户是否放弃这条证据,但不能强迫 Python 越过写入限制。换成 Codex 或其他 Agent 基座时,这条约束仍然成立:Agent 负责理解、判断和编排,Python 负责校验、执行和保存。
这里也可以分享一个原则:约束必须由确定的 Python 代码来看守,而不应该依靠大模型。
3.6 这些技术边界需要进入 Planning Brief
Agent 基座、Skill、CLI 和 Python 模块的关系,以及 Python、Agent、专用模型和用户之间的职责划分,都不是功能需求。它们不会改变用户希望系统完成什么,却会直接决定项目怎样开发、怎样测试,最后又要交付哪些文件和运行环境。
这些都是技术边界,而不是需求,它们应该成为 Plan 的技术输入,而不是写入 SPEC。后面的 Planning Brief 需要记录两项已经确定的方向:胶囊系统由 Agent 基座主控,当前 Agent 根据 Skill 通过稳定的 CLI 调用 Python;确定性操作由 Python 执行,通用语义理解由 Agent 完成,重要的不确定问题最终交给用户。Codex 是开发环境,Hermes 是兼容性测试环境,但业务核心不能依赖某个基座的内部实现。