mcpField
K
kcp-agent — KCP navigation planner

kcp-agent — KCP navigation planner

本地服务
cantara.github.io记忆与知识07 周前更新

关于 kcp-agent — KCP navigation planner

kcp-agent 是 Knowledge Context Protocol 的参考 Agent,根据任务和 knowledge.yaml 生成可检查的知识加载计划,并可据此回答。其规划过程无需 LLM,采用确定性规则并对访问限制 fail-closed。

主要功能

  1. 01按任务相关性规划知识单元
  2. 02按信任、时间和预算筛选
  3. 03生成可审计的加载计划
  4. 04可选调用 Claude 合成回答
  5. 05支持回答依据核验

适用场景

  1. 01在读取知识前检查加载计划
  2. 02按上下文窗口预算选择内容
  3. 03依据指定知识单元回答问题
  4. 04核验回答主张是否有依据

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"no-cantara-kcp-agent": {
"command": "npx",
"args": [
"-y",
"kcp-agent"
]
}
}
}
启动命令npx -y kcp-agent

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npmkcp-agent0.12.0

工具

5

收录的工具列表 · 更新于 2 周前

参数类型必填说明
envstring否用于联邦上下文选择的运行时环境(dev/test/staging/prod)
rolestring否用于受众定位的 Agent 角色(默认:agent)
taskstring是要为其规划知识加载的任务
as_ofstring否用于时间评估的 ISO 日期(默认:今天,UTC)
atteststring否Agent 可提供的证明提供方,与清单的 trusted_providers 匹配
budgetnumber否按请求付费单元的支出上限
followboolean否跟随符合条件的联邦引用(默认 false)
strictboolean否失败时关闭:丢弃不符合条件的单元,而不是将其列出
methodsarray否Agent 可结算的支付方式,例如 ["free","x402"](默认仅 free)
currencystring否预算货币(默认:USDC)
manifeststring是knowledge.yaml 的路径、目录或 HTTPS URL
max_depthnumber否follow=true 时要跟进的联邦跳数(默认:1)
max_nodesnumber否遍历期间获取的清单总数上限(默认:64)
max_unitsnumber否选中单元的数量上限(默认:5)
credentialsarray否Agent 持有的凭据类型,例如 ["mtls","api_key"] — 用于开放受访问控制的单元
context_budgetnumber否计划加载到调用方上下文窗口的 Token 上限;超出预算的单元将跳过,并附带计算过程
allow_private_hostsboolean否允许获取 loopback、private、link-local 主机以及 http://;默认 false — 失败时拒绝

详细介绍

kcp-agent

🧾 看它运行 — 交互式 KCP playground · 阅读揭晓

Knowledge Context Protocol 的参考 Agent。

竞技场 → — 未经修改、完整打包的真实规划器, 在浏览器中实时运行,与常见竞品正面对决。世界上最具确定性的 Agent。每个决策都有据可依。

KCP 定义了知识如何声明自身,以便 Agent 能够浏览它。kcp-agent 是另一半:端到端使用 KCP 的 Agent。给定一项任务和一个 knowledge.yaml,它会生成一份可检查的加载计划——要加载哪些单元以及加载顺序、跳过哪些单元及具体原因、如何在联邦中选择子清单,以及整个过程的成本——然后还可选择仅依据这些单元回答任务。

其有价值且新颖的核心是无需大模型且具有确定性。该计划是一份行动前审计产物——将可信渲染原则(“清单可以影响 Agent 知道什么,但绝不能影响它做什么”)扩展到整个 Agent 循环。只有最后的综合步骤会调用模型。

discover → verify signature → trust-gate → score units by task → federate (context + agent_identity)
        → temporal filter → budget (payment + rate_limits) → emit load plan → [follow] → [answer]

安装

npm install
npm run build
原生可执行文件

CI 会交叉编译自包含二进制文件(目标环境无需 Node/Deno),适用于 Linux x64/arm64、macOS x64/arm64 和 Windows x64——可从某个版本发布页面或任意 CI 运行中的 kcp-agent-natives 构件获取。也可以自行构建:

npm ci && npm run build
deno compile --allow-read --allow-env --allow-net --node-modules-dir=auto \
  --output kcp-agent dist/cli.js

使用

plan — 可检查的加载计划(无需 API 密钥)
node dist/cli.js plan "how do I deploy to production?" --manifest ./path/to/knowledge.yaml --env prod
Plan for: "how do I deploy to production?"
  companyx-knowledge-hub v1.0.0 · kcp 0.24 · env prod

Trust: · no manifest attestation requirement

Load plan (2 units):
  ● 1. front-door (score 4)  overview.md  free
  ● 2. deploy-guide (score 3) docs/deploy.md  free

Budget: tier default
Federation:
  → platform-engineering  needs github_pat before fetch  [acquire github_pat]
  · platform-engineering-dev  context ["dev","test"] excludes env 'prod'
Skipped (2):
  · auth-guide: no task-relevance match

每个阶段都对应规范中的一个层面:查询评分(§15)、时间有效性(§4.22)、Agent 证明(§3.2)、联邦 context + agent_identity(§3.6),以及付费/速率限制 (§4.14/§4.15)。Agent 无法证明身份的受限单元会列出,但标记为不可加载——默认拒绝,并附上原因。

为上下文窗口分配预算。 向模型提供内容时,Token 才是真正稀缺的资源,因此使用 --context-budget <n> 指定上限——它与金额 --budget 的工作方式完全相同: 按分数贪心选择;如果某个单元会超出上限,就会跳过并在原因中列出计算过程(over context budget: 1,240 tokens would exceed remaining 800 of 4,000),而分数较低但更小的单元仍有机会入选。由于规划器会在获取内容之前处理元数据(行动前审计),单元大小取自声明的 size_tokens(准确)或 bytes/4 (标记为估算);既未声明任何一种大小的单元仍会纳入,但会计为未测量(投影值是下限)——除非启用了 --strict,此时会默认拒绝该单元。--context-budget 可与 --budget 结合使用:单元必须同时符合两个上限。

机器可读计划

当其他 Agent 或集成要使用计划时,请使用 --json。输出会在顶层保留计划字段,并添加:

{
  "schemaVersion": 1,
  "kind": "plan"
}

kind 为 plan、tree(使用 --follow 时)或 trace(使用 --trace 时)。人类可读输出不属于兼容性接口。成功的 JSON 命令以 0 退出;规划器或清单错误会将诊断信息写入 stderr,并以非零状态退出。

ask — 先规划,再通过 Claude 回答
export ANTHROPIC_API_KEY=...        # or: ant auth login
node dist/cli.js ask "how does an agent get started here?" --manifest ./knowledge.yaml

ask 会运行相同的规划器,仅加载符合加载条件的单元,并让 Claude 根据这些单元作答——将单元内容视为知识,而非指令。需要 @anthropic-ai/sdk(可选依赖)和密钥;plan 两者都不需要。

ask --loop — 经审计的批判循环
node dist/cli.js ask "who won, and what does it mean for infrastructure?" \
  --manifest ./knowledge.yaml --loop --methods free,x402 --budget 0.50

确定性评分器采用词汇匹配,因此,如果任务的措辞与发布者使用的词汇不同,就可能漏掉相关单元。--loop 可以弥补这一差距,同时不牺牲确定性——模型提出,计划决定:

plan → LLM gap critique (metadata only) → term gate → re-plan → … → load → answer

快速批判模型(默认为 claude-haiku-4-5,可通过 --loop-model 更改)会查看计划的元数据摘要——ID、意图、评分、跳过原因,绝不包含单元内容——并提出额外的小写搜索词。确定性关卡会对这些词进行清理、去重并限制数量;任务字符串随之扩展;规划器从头重新规划。当批判模型不再提出词语、某一轮没有新增单元,或达到 --max-rounds(默认为 3)时,循环收敛。随后,综合阶段会根据最终计划中的合格单元回答原始任务。

批判模型永远不能做的事:开放访问关卡、改变信任/时效/受众决策,或花费资金——搜索词只影响相关性评分;循环收敛前不会加载或付费获取任何内容,最终计划的预算计算也会像单轮模式一样严格控制支出。每一轮都会被记录(提出的词语、接受项、拒绝项、新增单元、完整的重新规划产物)——使用 --json 时,计划链就是审计日志。

同一循环也可用作库(runLoop / askLoop,支持注入批判模型),而 skills/kcp-navigator/SKILL.md 则将这一规范打包为可移植的技能,供自行驱动 CLI 的 Agent 使用。

ask --ground — 验证答案,揭示无法证实的内容
node dist/cli.js ask "who won, and what does it mean?" --manifest ./knowledge.yaml --ground

计划的默认拒绝关卡决定哪些内容可以加载;溯源验证将同样的规范扩展到哪些内容可以断言。综合生成后,答案中的每条主张都会由一个独立验证器检查——它会单独调用一个不同于生成器的模型——该验证器必须将主张归因于某个已加载单元,否则就返回空结果。最终产物分为两部分:

Grounded (2/3 claims):
  ● The award went to the Nordic bid.
     ↳ chipfab-exclusive · sha 9f2c1a0b7e34
Unsubstantiated (1): — could not be grounded in a loaded unit
  ○ The datacenter runs on hydro power.
     no loaded unit supports this claim
⚠ partial-unsupported — 1 claim(s) could not be substantiated

只有在所引用的单元确实已加载且其内容哈希匹配时,主张才会获得溯源支持——因此,即使验证器错误归因(或受到提示词注入),引用了从未加载的单元,也无法让主张获得溯源支持:归因只是提议,溯源支持则需经过裁定。不受支持的主张会被揭示出来,而非悄然删除——这是“每项决策都经得起辩护”中诚实的那一面。每个揭示的缺口也是给发布者的信号:该任务需要清单未提供的证据。揭示的列表设有上限,以防受损的生成器用虚假缺口将其灌满。

--ground-rounds <n> 会形成闭环:揭示的缺口会生成改写词语,Agent 重新导航以尝试找到缺失的证据,然后再次进行溯源验证,最多进行 n 轮。三项彼此独立的限制保证循环终止,其中任一项都足以令其停止:词语关卡具有吸收性(一个词语一旦被接受,就会永久保留,因此重新导航只能从有限的合格集合中增加单元)、轮数上限,以及进展保护(某一轮没有新增单元时即停止)。循环不可能振荡——已加载集合只会单调增长,或循环停止。任何非 grounded 的终止状态(partial-unsupported、partial-budget、partial-rounds)仍会揭示剩余缺口。受损的验证器最多只能扩大合格集合内的导航范围——它永远无法越过关卡、指定 URL,或超出预算支出。

assess — 决定哪些内容可以付诸行动

计划中的各道关卡决定哪些内容可以加载;依据 grounding 决定哪些内容可以断言; assess() 决定结论是否达到置信度阈值,从而可以付诸行动。 它在综合之后运行——置信度是输出的属性,这正是它在结构上不可能成为预选级联中的第 14 道关卡的原因。

import { assess } from "kcp-agent";

const verdict = await assess(task, answer, loadedUnits, {
  threshold: 0.7,            // org policy — caller-supplied, never manifest data
  severity: "critical",
  evaluator,                 // optional: makeProviderEvaluator(provider) — a separate judge
});
// { gate: "confidence", passed, score, threshold, signals[], detail, asOf }

信任立场与 grounding 相同:置信度是一种提议(答案自身通过 extractSelfReport 提供的 Confidence: 0.82 格式自我报告,和/或注入的评估器给出的判断);关卡以确定性方式裁决—— 默认采用 min 聚合,对任何无法测量的内容均采取失败关闭策略。每个裁决都会原样保留原始 signals[],以便随着时间推移,依据实际结果校准阈值。裁决沿用各关卡的 二元结果加书面理由约定,但它是独立的下游产物——DecisionTrace 和 一致性测试向量均不受影响。

执行环节位于 kcp-harness:它的 harness_assess MCP 工具会运行此关卡,并通过审批工单将关键任务中未通过裁决的情况发送给 指定的人类,同时将裁决作为证据附上。

kind: skill — 受治理的程序,与知识分开设关

规范 §4.3a(v0.26.1)在普通知识之外新增了第二类单元:kind: skill 标记的是 Agent 可以 执行的内容——操作手册、脚本、程序等,而不只是可以阅读的内容。默认情况下,技能采用失败关闭策略: 除非清单中明确授予 load_eligible: true,否则 kind: skill 单元不具备调用资格; 其权限由 action_scope(可触及的 tools、paths、 capabilities)限定。该机制作为独立关卡 skill_eligibility 运行,并插入预选级联中的相关性关卡之后—— 级联共有十四道关卡,而非十三道。

units:
  - id: restart-web-service
    kind: skill
    load_eligible: true
    action_scope:
      tools: ["shell.exec"]
      paths: ["/opt/web-service"]
      capabilities: ["service.restart"]

未获授权的技能仍会纳入计划——Agent 可以看到它的存在,以及它为何与任务匹配, 遵循与其他所有关卡相同的先审计、后行动原则——但该技能会被暂缓加载(loadEligible: false),或者在 --strict 下被彻底移除;此时会具体归因于 skill_eligibility, 而非通用的严格模式截断。规划技能始终安全;调用技能则是另一项需明确授权的决策。请参阅下文的 受治理技能演示,以及 符合规范的实现指南, 了解移植实现必须复现的确切关卡约定。

演示 — 二十个场景,无模拟数据
node examples/demos.js            # all twenty, narrated
node examples/demos.js --list     # newsstand · transition · vault · org · audit · trace · loop · grounding · seal · incident · leash · summer · milky-way · moved-world · deja-vu · borrowed-memory · context-window · dogfood · second-opinion · governed-skill
node examples/demos.js vault      # one at a time
演示展示内容规范
报刊亭0.40 USDC 的上限:按评分购买,并在原因中列出计算过程以说明跳过的项§4.14
过渡期同一个问题,三个 --as-of 日期;由取代关系决定重叠日§4.22
保险库付款永远不会打开授权关卡——手持 x402,仍会失败关闭§4.11/§4.14
组织联邦 context 按环境切片;agent_identity 会在获取前规划凭证§3.6
审计对两个 --json 规划进行差异比较:能力开关具体移动了哪个关卡,以及其价格—
循环使用脚本化评论器的审计式批评循环:注入会被驳回,条款会重新规划,预算保持不变—
依据ask --ground:引用未加载单元的主张会失败关闭;闭环会重新导航,并根据真实字节为其提供依据—
03:00 警报波及四个联邦参与方的零日漏洞——证明、签名 CERT、取代关系、作为强制关卡的 TLP:AMBER,以及情报预算(examples/incident/)全部
借来的牵引绳脚本化的外部 MCP 客户端通过 stdio 重新规划事件——关卡相同、账本相同——随后由 kcp_replay 捕获其伪造的产物—
封印签名清单验证通过;签名后追加一个单元 → 规划前失败关闭§3.2
夏日计划一家人跨越四个联邦参与方度假——签名枢纽、时刻表取代关系、身份关卡保护的无障碍登记表、x402 旅游详情,以及被 validate lint 捕获的 not_for 陷阱(examples/summer/)§3.6/§4.11/§4.22
银河系整个企业文档体系——覆盖八个领域的签名枢纽:按环境切片的开发镜像、日期已过的未来法规、仅供人类查阅的 HR 文档、经 HSM 证明的配方、设有身份关卡且采用订阅费率层级的 ERP 供应商,以及 CSRD 年度交接(examples/milky-way/)§3.6/§4.14/§4.22
迁移的世界情景记忆:记录答案时不保存字节,按任务重叠度召回,然后重放——只要固定版本仍有效,就仍有依据;源一旦移动,依据便立即漂移—
似曾相识经记忆验证的复用:针对未变更清单的相同输入,可证明规划相同;新增选项无法命中;清单发生漂移时则拒绝复用—
借来的记忆MCP 会话去重:kcp_load 不会再次提供调用方已持有的字节(带 SHA 确认的存根),并会重新提供任何已发生漂移的单元—
上下文窗口--context-budget:令牌上限,按评分贪心选择,超预算单元会连同计算过程一起跳过;大小取自声明的 size_tokens 或 bytes/4—
自用测试Agent 验证并导航自己的仓库§2
第二意见在低置信度结论被采取行动前,由 assess() 设置关卡—
受治理的技能kind: skill 程序在获得明确的 action_scope 授权、具备调用资格前会失败关闭§4.3a

每个演示所叙述的事实,都由正式发布的 CLI 和库的真实输出解析或计算得出——没有任何硬编码——而且 test/demos.test.ts 会在 CI 中运行全部二十个演示,因此叙述本身就是回归测试套件。所有内容均可离线运行;无需 API 密钥。

本仓库描述自身

本仓库以 KCP 测试自身:根目录下的 knowledge.yaml 声明 README、源模块、演示清单和 CI 工作流为知识单元,并联合到 KCP 规范自身的清单。因此,Agent 可以导航自己的仓库:

node dist/cli.js plan "how does the planner score units?" --manifest .

test/manifest.test.ts 确保清单内容可靠——可解析、指向现有文件,并能合理地进行规划。

选项

标志含义
--manifest <loc>knowledge.yaml 的路径、目录或 HTTPS URL(必填)
--env <name>用于联邦 context 选择的运行时环境(dev/test/staging/prod)。默认拒绝:不提供时,永不跟随带有 context 标签的引用
--as-of <date>用于时间评估的 ISO 日期(默认:今天,UTC)
--max-units <n>所选单元的数量上限(默认 5)
--strict默认拒绝:丢弃不符合条件的单元,而不是列出它们
--role <role>Agent 声明的受众角色(默认:agent)
--methods <list>Agent 可结算的支付方式,例如 free,x402
--credentials <list>Agent 持有的凭据类型,例如 api_key,oauth2
--attest <provider>Agent 可提供的证明提供方
--budget <amount>按请求付费单元的支出上限——按分数贪心选择,跳过会超出上限的单元(并显示计算过程)。整个联邦遍历共用一个上限,而非每个清单各自一个
--currency <code>预算货币(默认 USDC)
--context-budget <n>计划加载到模型上下文窗口中的 Token 上限——按分数贪心选择,跳过会超出上限的单元(并显示计算过程)。可与 --budget 配合使用:单元必须同时符合两项上限
--follow获取并规划符合条件的联邦引用(默认拒绝:永不获取受门控或被排除的引用)
--max-depth <n>要跟随的联邦跳数(默认 1;隐含启用 --follow)
--max-nodes <n>整个遍历中获取的清单总数上限(默认 64;默认拒绝的扇出上限)
--allow-private-hosts允许获取环回、私有、链路本地主机及 http:// 地址——默认关闭(阻止 SSRF 攻击内部地址或元数据地址)
--no-verify跳过清单签名验证
--require-signature除非每个清单都带有已验证的签名,否则失败
--trust-key <loc>用于验证的固定 ed25519 公钥(路径、URL 或内联值)
--trace(plan)显示决策跟踪:逐个单元展示门控级联——每个单元依次经过的所有门控
--json以 JSON 格式输出计划(对于 ask,也输出答案)
--correlation-id <id>由调用方提供的不透明 ID,会回显到 --json 封装中,以便将计划产物关联到调用方的决策链或审计日志
--help打印用法和选项参考(也可使用 -h;在任何子命令后均可使用)
--once(watch)运行一次验证/规划周期后退出,而不是持续监视
--diff(watch)报告与上一周期相比的变化
--task <task>(watch)每个周期都要重新规划的任务
--publisher <name>(init)写入脚手架清单的发布者名称
--from-llms-txt <loc>(init)根据现有的 llms.txt 起草 knowledge.yaml——URL 或路径
--dry-run(init)打印生成的 knowledge.yaml,而不是写入文件
--force(init)覆盖现有的 knowledge.yaml
--model <id>(ask)模型 ID:provider/model(例如 openai/gpt-4o、anthropic/claude-opus-4-8)——默认 claude-opus-4-8
--base-url <url>(ask)OpenAI 兼容端点的基础 URL(覆盖提供方默认值)
--api-key <key>(ask)API 密钥——可替代环境变量 ANTHROPIC_API_KEY / OPENAI_API_KEY
--loop(ask)经审计的批判循环:规划 → 大模型差距批判 → 术语门控 → 重新规划
--max-rounds <n>(ask --loop)批判轮数上限(默认 3)
--loop-model <id>(ask --loop)批判模型——默认 claude-haiku-4-5
--ground(ask)根据已加载的单元验证答案中的每项声明;指出未经证实的声明
--ground-model <id>(ask --ground)验证模型——默认 claude-haiku-4-5
--ground-rounds <n>(ask)闭环溯源:发现差距时重新导航以查找证据(默认 0)
--check-gaps(replay)重新导航今天的清单,检查已溯源答案中发现的差距是否已弥合
--memory <dir>(remember/recall)情景记忆目录——每个产物对应一个按哈希寻址的条目
--replay(recall)根据今天的清单重新验证每段回忆的经历(命中项已发生漂移时以 1 退出)
--limit <n>(recall)返回的经历数量上限
--public-url <url>(serve)可访问此服务的公共 URL——根据清单声明的 serving.mcp(§3.12)进行自检;不匹配时在启动时发出警告
test/docs.test.ts 会确保这张表内容准确:parseArgs 接受的每个标志都必须出现在这里和 cli.ts 的头部,反之亦然。
validate — 检查 knowledge.yaml
node dist/cli.js validate .            # or a path, directory, or URL

错误是会误导 Agent 或导致 Agent 失败的结构性问题(重复的 ID、不安全或缺失的路径、指向不存在目标的 superseded_by,以及任何 Agent 都无法满足的证明要求);警告则是会削弱导航能力的声明(没有触发条件、已过期且没有后继项的单元)。错误时退出码为 1——任何发布清单的仓库都应在 CI 中运行此命令。

replay — 重新验证已保存的计划或基于依据的回答
node dist/cli.js plan "task" --manifest . --json > plan.json
node dist/cli.js replay plan.json       # exit 0 identical · exit 1 drifted

plan --json 生成的产物会固定清单的 sha256,并回显每项规划器输入。replay 会重新获取每份清单(包括 --follow 树中的每个节点),比较字节,使用已保存的输入重新运行纯规划器,并针对每份清单报告一致或已偏移,同时指出发生变化的字段。计划是证据;重放则是交叉质询。手动编辑产物也会导致偏移:重新计算出的计划将与之不符。

replay 会自动检测基于依据的回答产物(来自 ask --ground --json),并改为逐条交叉质询其中的声明:重新读取每条有依据声明所引用的单元,并将其 sha256 与固定值重新比较,结果为依据仍有效、已偏移(字节已更改)或已消失(单元已移除)。如果任何引用不再成立,则退出码为 1,因为过时的回答不能被视为已验证。使用 --check-gaps 时,它会重新导航今天的清单,以检查此前发现的缺口是否现已弥合(清单已补入回答之后缺失的证据)——缺口有其生命周期,而记忆是一份可针对变化后的世界重新验证的计划。

remember / recall — 将情景记忆作为可重放的计划
node dist/cli.js ask "who won the exclusive story" --manifest examples/fjordwire --ground --json > ans.json
node dist/cli.js remember ans.json --memory .kcp-memory        # log the episode (unit bytes stripped)
node dist/cli.js recall "the exclusive story winner" --memory .kcp-memory --replay

这里的记忆不是摘要或嵌入向量,而是计划/基于依据的回答产物本身,**去掉了唯一会让它在保留后变得危险的内容:单元字节。**如果在记忆日志中缓存受限或付费内容,之后调用 recall 时就能绕过访问门槛读取这些内容。因此,remember 只保留重放所需的信息——每个单元的 id、path、sha256 和引用表——并删除所有 content 字段。条目以去除内容后的产物进行哈希寻址,因此重复记录同一回答具有幂等性。

recall 会按词汇任务词项的重合度匹配过去的事件(使用规划器评分时采用的同一分词器),并按重合度排序。由于字节已被删除,召回的事件本身不提供新鲜度保证:使用 --replay 时,每个命中项都会根据今天的清单重新验证——有效(每个引用的单元都仍符合固定字节)、已偏移(某个引用已变化——退出码为 1)或无法验证(无法执行重放)。不使用 --replay 时,每个命中项都会报告为 无法验证——记忆绝不会谎称过时的回答仍然正确。记忆是一份可针对变化后的世界重新验证的计划。

memory-validated reuse — 保持确定性的缓存

向 plan 或 ask 传入 --memory <dir>,即可将情节日志变为缓存,其正确性依赖于与其他一切相同的属性:计划是 (manifest bytes, task, options) 的纯函数。规则是 召回(精确匹配)+ 重放(新鲜度)= 复用,任何不符合这一规则的情况都会安全失败。

node dist/cli.js plan "how do I deploy" --manifest . --memory .kcp-memory   # records + reports determinism
node dist/cli.js plan "how do I deploy" --manifest . --memory .kcp-memory   # ♻ provably identical to episode …
node dist/cli.js ask  "how do I deploy" --manifest . --ground --memory .kcp-memory   # reuses a clean grounded answer, skips the model

plan --memory 会记录每个计划;如果此前有情节使用相同的任务、清单和选项运行过,它会报告今天的清单是否与之逐字节相同(♻ 可证明相同),或是自那时起已发生漂移——这是一种确定性/审计信号,绝不会在 sha 变化后悄然复用。缓存键包含生效的 --as-of 日期,因此未固定日期的计划只有在同一天内才符合复用条件;使用不同能力(--role、--budget、……)运行会形成不同的计划,而非缓存命中。

ask --ground --memory 才是真正发挥复用价值的地方:调用模型前,它会查找相同请求对应的缓存有依据的答案并重放该答案——重新读取每个引用的单元,并重新核对其固定的 sha256。只有在所有引用仍然有效时,才会返回存储的答案(♻ 已复用,不调用模型);如果任何被引用的单元已发生漂移或不复存在,答案就会重新计算,绝不会提供过期内容。由于导入时已剥离单元字节,召回的答案绝不可能将受限内容偷偷带过下一道访问门槛——复用会实时通过防护重新读取这些单元。记忆就是一份可针对变化中的世界重新验证的计划。

mcp — 向任意 MCP 客户端提供规划器
node dist/cli.js mcp                   # stdio transport

它提供四种工具:kcp_plan(可检查的加载计划)、kcp_load(计划以及符合加载条件的单元内容,因此调用方 Agent 的模型可自行综合——kcp-agent 在此无需 API 密钥)、kcp_validate 和 kcp_replay(通过网络对保存的计划产物进行交叉审查)。kcp_plan/kcp_load 支持 CLI 的完整能力选项——role、methods、credentials、attest、budget——因此无论是哪个 MCP 客户端,证明和凭证门槛的判定都与命令行上的判定完全一致。借用规划器的 Agent 不必具备确定性;只要向具备确定性的对象发起请求即可。例如,可在 Claude Code 中注册:

claude mcp add kcp -- node /path/to/kcp-agent/dist/cli.js mcp

会话去重。 kcp_load 接受 known 参数——调用方已持有的单元,格式为 [{id, sha256}]。sha 仍匹配的单元会以 unchanged 存根形式返回(不提供字节,只确认 sha),而非再次提供其内容,从而在多轮会话中节省调用方的上下文窗口;响应会报告 deduped 和 bytesSaved。这是情节记忆在调用方一侧的实现,且不改变原有特性:服务保持无状态(调用方的窗口就是会话),仅当 sha 完全匹配时才会生成存根——任何漂移都会重新提供新鲜字节;由于 kcp_load 每次调用都会重新规划并重新执行门槛检查,调用方后来已无权访问的单元只会被直接省略,绝不会被伪装成存根偷偷带回。

knowledge.yaml 是成熟版 llms.txt

llms.txt 解决了同一问题中较简单的那一半——告诉 Agent 网站包含什么——并被发布者采用。它只是一个扁平的链接列表,也只能做到这一点。

同一个网站,双向转换:

# Acme Docs                                    kcp_version: "0.30"
                                               project: "Acme Docs"
> Everything you need to integrate Acme.       intent: "Everything you need to integrate Acme."

## Guides                                      units:
                                                 - id: "quickstart"
- [Quickstart](/quickstart):                       path: "quickstart"
    Get running in five minutes                    intent: "Get running in five minutes"
                                                   audience: [agent, human]
                                                   triggers: ["guides", "quickstart"]

转换现有文件——结果确定、无需调用模型,且绝不会覆盖已有的清单:

kcp-agent init --from-llms-txt https://acme.dev/llms.txt --dry-run

kcp-agent discover <url> 也会在回退到爬取前检查 /llms.txt,并提示你升级。

升级带来的好处,都是 llms.txt 无法表达的:

llms.txtknowledge.yaml
存在什么✅ 链接列表✅ 带有意图和触发条件的单元
面向谁❌audience、not_for、角色限制
何时有效❌valid_from / valid_until、替代关系
是否真实可信❌独立的 ed25519 签名
成本是多少❌payment、预算、速率限制
指向什么❌联邦到其他发布者的清单
Agent 可以用它做什么❌kind: skill / playbook、action_scope、load_eligible

转换会将这些项目全部标记为待办事项,而不是凭空编造。若转换后的清单擅自声称适用对象或有效期,就等于断言了你从未说过的内容。

签名

清单可以声明一个 signing 区块(方案为 ed25519,包含密钥和独立签名 URL——参见规范仓库自身的清单)。如果存在,kcp-agent 会在制定计划前验证清单原始字节的签名:无效签名始终会导致失败关闭;无法验证的签名(密钥无法访问)会发出警告,除非指定了 --require-signature。支持:JSON 签名信封({algorithm, public_key, signature})、原始 base64/hex 签名,以及 PEM / SPKI-DER / 32 字节原始密钥。使用 --trust-key 固定发布者密钥,防止清单为自身背书。

网络边界

清单是不可信输入,它会选择 Agent 随后要获取的 URL——联邦引用、签名和密钥位置、远程单元内容。所有远程读取都会经过一个受保护的获取函数(src/fetch.ts),默认采用失败关闭策略:

  • SSRF / 混淆代理——远程地址仅允许使用 https://;拒绝环回、私有、链路本地和云元数据地址(例如 169.254.169.254)。主机名会通过 DNS 解析并逐一检查所有地址;重定向由客户端手动跟随,防止公共主机将 Agent 引向私有地址。使用 --allow-private-hosts 可允许本地/内部清单。
  • 扇出——深度和循环已受到限制;现在 --max-nodes(默认值为 64)会限制单次 --follow 获取的清单总数,防止恶意枢纽扩散到数百万个清单。
  • 响应大小——每次读取都会以流式方式接受 8 MiB 上限检查,超出后即中止,并设置整个交互的超时时间,防止恶意端点耗尽内存。

通过 MCP 使用时,默认启用此保护——外部客户端正属于不可信调用方的情况。

编写便于 Agent 查找的触发词

评分器是基于词汇且确定性的——它会将意图、触发词和 id/path 与任务中的词语进行匹配;不使用模型,也不使用嵌入。这正是它的特点(可复现、可审计、免费),但也有一个实在的结果:一个单元只能通过其清单声明的词语被找到。 一个来自实际使用场景的漏匹配案例:

task: "sovereign compute award and infrastructure implications"
  · datacenter-power: no task-relevance match      ← the story's best infrastructure angle

该单元的触发词是 [datacenter, power grid, capacity, Nordics],意图中却从未提到 “infrastructure”——词汇完全没有重合,得分为 0,因此被跳过。应该修改清单,而不是规划器:

  • 围绕 Agent 会提出的问题编写触发词,而不是内容中的名词。 “infrastructure”“energy costs”“where does the compute run”——也就是任务中的表达方式——比文章中的词汇更有效。
  • 意图中也要加入问题相关的词语:意图会计分,因此 “How the power grid limits sovereign compute infrastructure” 可以被找到,而 “Live Nordic datacenter power-grid feed” 则不行。
  • 发布前,使用自己的清单运行 kcp-agent plan,并输入预期任务——跳过原因会准确说明真实 Agent 会漏掉什么,以及为什么。

库

import { loadManifest, plan, synthesize } from "kcp-agent";

const manifest = await loadManifest("./knowledge.yaml");
const p = plan(manifest, "how do I deploy?", { env: "prod", capabilities: { paymentMethods: ["free", "x402"] } });
// p.selected / p.skipped / p.federation / p.budget / p.trust — a pure, inspectable artifact
const { answer } = await synthesize(p);   // optional LLM step

import { assess } from "kcp-agent";       // post-synthesis confidence gate
const verdict = await assess("how do I deploy?", answer, [], { threshold: 0.7 });

设计

  • 确定性规划器(src/planner.ts)——纯函数,经过全面的单元测试(npm test),不执行 I/O,也不使用模型。计划可复现、可审计。
  • 独立的 KCP 客户端(src/client.ts)——从路径、目录或 HTTPS URL 解析 knowledge.yaml。不依赖规范仓库的内部实现。
  • 联邦跟随器(src/follow.ts)——围绕纯规划器的异步外壳:递归获取符合条件的引用,遇到失败即拒绝,并检测循环、逐跳验证签名。
  • 签名验证(src/verify.ts)——通过 WebCrypto 对确切的清单字节进行 ed25519 验证。
  • 综合层(src/synthesize.ts)——唯一会调用模型的部分;仅加载已规划的单元并回答任务。
  • 置信度关卡(src/assess.ts)——综合之后,根据调用方提供的阈值,对自报置信度和/或评估器置信度进行裁定;过程确定性,遇到失败即拒绝。
  • MCP 服务(src/mcp.ts)——通过 stdio 进行无依赖的 JSON-RPC 通信。

规范符合性

该 Agent 以KCP 0.25 为目标,并端到端使用以下子集。(规范仓库自身的清单目前声明 kcp_version: 0.21——这些层的清单彼此兼容。)

规范层章节位置
查询评分(意图/触发词/id+path)§15planner.ts scoreUnit
受众与 not_for / not_for_strict 定向§4.20planner.ts 相关性/负向路由关卡
访问权限是授权维度——付款不能替代访问权限§4.11planner.ts 访问权限关卡
时效有效性与替代关系§4.22planner.ts temporalStatus
Agent 认证要求§3.2planner.ts 信任关卡
联邦 context + agent_identity§3.6planner.ts + follow.ts
付款方式与层级§4.14planner.ts planPayment
速率限制层级§4.15planner.ts planBudget
清单签名(ed25519)签名区块verify.ts
发现(knowledge.yaml、.well-known/)§2client.ts

每一行都对应到 CI 测试,这些测试会在 docs/conformance.json 中列出,并在网站上呈现为 Receipts;如果引用的测试消失或更名,test/docs.test.ts 会使构建失败。

一致性向量

vectors/ 将规划器的决策固化为可移植的 (manifest, task, options) → expected outcome 测试用例——确定性核心的行为以数据而非代码的形式呈现。test/vectors.test.ts 用于验证参考规划器能否复现每个测试用例;任何第二种实现(用于构建 2–5 MB 静态二进制文件的 Go/Rust 移植版,或第三方实现)只要行为相同,即符合规范。两个独立实现通过相同的向量,就验证了规范,而不只是代码——这是证明协议没有歧义的最有力方式。测试集由参考规划器生成(npm run gen:vectors),因此预期结果绝不会由人工编写;该测试集已作为规范性 KCP 一致性套件提议上游采纳。

尚未涵盖:单元之间的依赖链、hints.load_strategy、合规性/审计区块。

指南

许可证

Apache-2.0 · 由 eXOReaction AS 提议,托管于 Cantara 之下。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。