Agent Library
Agent Library 回答一个问题:这个 Agent 实际可以使用哪些能力?它由实例内的 Skill 和 Agent Plugin 目录,以及每个 Agent 的启用状态组成。本页以 Ankole.AIAgent.Library 的实际代码为准说明这套模型。
Skill 和 Plugin 本身是文件系统中的 Bundle,不是数据库记录。PostgreSQL 保存启用状态、注册表语义和文件观察结果,并在实例级默认值之上记录每个 Agent 的少量覆盖。文件内容和版本留在实例的部署包中,数据库只记录哪些能力由谁启用。
两种能力
库持有两种相关但不相同的东西:
- 一个 Skill 是一个文件系统 bundle,由一份
SKILL.md标识。skill 名小写,以字母开头,只用字母、数字、_和-,最长 64 字符。一个 skill 要么是builtin(随应用镜像发布,从app/library/skills同步),要么是installed(agent 安装到 worker 可见的存储下)。agent_skills行记录启用状态、来源种类、content hash 和同步时间——它明确不是一张文件内容表。 - Agent Plugin 是标准 Codex Plugin 包,可以附带 Ankole 的
workspace-template/初始化目录。包的文件和版本留在实例的部署包中;PostgreSQL 只保存每个 Agent 的启用覆盖。Plugin 标识符与 Skill 名称使用相同的格式规则。
两者相连:一个 Agent Plugin 可以带 skill,而 skill 行记录它的 agent_plugin_id,供父级启用和目录展示使用。但 Agent Plugin 成员只是独立的元数据——它不改变 skill 的加载方式。
启用:默认,再覆盖
一个 agent 的有效能力,是带着两层走过目录解析出来的:
- 实例级默认值——每个 Skill 的
default_enabled,以及运维者设置的全局 Plugin 默认值。 - 按 agent 的覆盖——某条 skill 行上的
enabled_override,或限定到某一个 agent 的 Agent Plugin 覆盖。
解析结果就是能力端点返回的 effective_enabled 字段:取默认值,若存在覆盖则应用覆盖。没有覆盖的能力继承默认值;有覆盖的能力遵从覆盖。目录上限 256 个 plugin,所以解析保持廉价,界面保持清晰可读。
这就是 Console 的 Agent Library 能力路由所暴露的模型:先设全局默认值,再按 agent 收窄或放宽。
Agent 长期文档与 Skill overlay
除了能力,库还持有 agent 自己的可写文档和 skill 定制:
- Agent 长期文档包括
mission、soul和design,即容器表接受的三个source_kind。前两项定义职责与行为,design保存视觉内容使用的设计系统。它们存放在agent_library_container_entries中,并按内容哈希寻址。 - skill overlay 是
agent_skill_overlays里的语义行,每个(agent, skill)一条。它们让运维者为某一个 agent 定制某个 skill 的行为,而不必 fork 这个 skill bundle。一个 overlay 支持比较并交换(compare-and-swap)替换,所以并发编辑以确定的方式分出胜负。
一次 skill 视图读取该 skill 的文件,外加该 agent 对它的任何 overlay,于是 agent 看到的是一个连贯的 skill,而不是一个 bundle 外加一份单独的补丁。
同步:让注册表保持诚实
因为 skill 是文件系统 bundle,数据库注册表必须跟踪文件系统。两条同步路径做这件事:
sync_builtin_skills把app/library/skills树与 builtin skill 行对账,返回是否有变化、content hash 以及 skill 数和文件数。它从应用镜像运行,所以新镜像能在下一次同步时新增或更新 builtin skill。sync_agent_skills把某个 agent 的已安装 skill 与 worker 可见存储的实际内容对账,而replace_installed_skill_observations写下观察到的文件集。从存储里消失的 skill 会反映到注册表;新出现的 skill 会被捡起来。
同步是“读取并对账”,不是“推送后祈祷”。content_hash 让同步幂等:同一棵树产出同一个 hash,只有真正的变化才写一行。
运维界面
Console 页里已经覆盖的路由驱动这套模型。尤其是能力路由:
| 方法 | 路径 | 用途 |
|---|---|---|
GET |
/agent-library/capabilities |
带默认值的全局目录 |
PUT |
/agent-library/agent-plugins/:id |
设定一个 plugin 的全局默认值 |
PUT |
/agent-library/skills/:id |
设定一个 skill 的全局默认值 |
GET |
/agents/:agent_uid/library-capabilities |
某个 agent 的有效能力 |
PUT |
/agents/:agent_uid/library-capabilities/agent-plugins/:id |
为某一个 agent 覆盖一个 plugin |
PUT |
/agents/:agent_uid/library-capabilities/skills/:id |
为某一个 agent 覆盖一个 skill |
GET |
/agents/:agent_uid/library-documents |
列出该 agent 的 mission/soul/design |
PUT |
/agents/:agent_uid/library-documents/:document_kind |
设定一份文档 |
GET |
/agents/:agent_uid/library-skill-overlays |
列出 skill overlay |
PUT |
/agents/:agent_uid/library-skill-overlays/:skill_name |
设定一个 skill overlay |
DELETE |
/agents/:agent_uid/library-skill-overlays/:skill_name |
移除一个 skill overlay |
读取 /agents/:agent_uid/library-capabilities 会触发一次 agent skill 同步,所以运维者看到的是注册表与当前存储对账后的结果——不是过期的快照。
Agent Library 不是什么
它不是 marketplace,也不是热加载系统。skill 和 plugin 是受信任的第一方 bundle,随部署发布,或安装到 worker 可见的存储里;没有第三方发现,没有 worker 之外的额外隔离机制。数据库不是 skill 字节的来源——字节在文件系统上,注册表只跟踪它所见到的。库也不是定义模型工具的地方;它是运维者决定一个 agent 能把哪些能力带进一个回合的地方。从“已启用”跨到“真正被调用”,是 Agent Computer Worker 在回合时刻的事。
下一步
- 配置库的路由,读 Console。
- 在一个回合中跑起一个已启用 skill 的 worker,读 Actor Runtime。
- 能力库所属的 Agent 主体,见主体与 AuthZ。