01 修改代码
harness.js模型是固定剧本,你来补上 Harness。
接口速查:ctx 里有哪些数据、能调用哪些工具
- onRecall(ctx)
- 准备本轮寄送地址与记忆治理。可以调用工具;用工具保存的长期 memory 才能跨会话保留。
- canComplete(ctx) → true / false
- 返回 bool,决定固定 Agent 是否寄送;false 该轮转人工。运行在全新实例,使用最新 selection / evidence,ctx.tools 为 null。ctx.model.says = 'done' 仅申请完成,不是有效证据。
- ctx.request = { id, tenantId, userId, profileRevision, at, override }
- at 为当前请求绝对业务时间(Unix 秒),与 now 模拟计时不同。override 为 null 或 { address, sourceId, scope: 'request', requestId }:当前客户已认证的明确临时地址,仅当前 requestId 有效,本次优先,下次新会话无 override 时回到长期地址。
- ctx.candidates = [{ id, tenantId, userId, kind: 'address', source: 'profile' | 'model', revision, verifiedAt, validUntil }]
- 可信 Harness 提供的索引元数据,没有地址正文;按相关度而非可信度排序。本关故意混入他人 metadata,必须先同时匹配 tenantId 与 userId,才能 readMemory。生产应在检索前就按身份过滤,不可先读跨用户正文再筛。
- ctx.evidence · ctx.selection
- evidence 是本轮读 / 查的证据数组,初始已有 override 证据。selection 为 null 或 { address, sourceId }。所有快照都不会随工具调用自动刷新;下一次 hook 的新实例才会拿到最新快照。
- ctx.now() · ctx.deadline = 180
- 当前模拟计时与每组 180 秒模拟期限;判断记忆时间有效性用 request.at,不要用 now()。每组连续跑两轮请求,每轮的两个 hook 都是新实例,顶层变量和局部变量不跨实例保留。
- await ctx.tools.readMemory(id)
- 返回 { sourceId: id, address, tenantId, userId, revision, verifiedAt, validUntil, source: 'profile' | 'model', scope: 'memory' } 并加入 evidence。跨 tenant / user 的读取会被拒绝,并记 scope 违规。
- await ctx.tools.queryProfile()
- 返回 confirmed 证据 { status: 'confirmed', sourceId, address, tenantId, userId, revision, verifiedAt, validUntil, source: 'profile', scope: 'profile' } 或 { status: 'unknown' }。confirmed 会加入 evidence;unknown 不能用来猜地址,应交人工。
- await ctx.tools.remember(receipt)
- 只能用本轮 queryProfile 返回的真实 confirmed 证据,原子替换当前用户长期地址记忆,保留历史审计;不会修改权威客户档案。返回新记忆的索引 metadata,不是地址读取证据。不能写临时表达、模型猜测、伪造或他人数据;即使 catch 错误,仍记 pollution 违规。
- await ctx.tools.useAddress({ address, sourceId })
- 设置待寄地址,不代表已经寄出。实际地址与来源都正确才可寄;猜中地址却没有有效证据,也记 wrong 违规。
- await ctx.tools.askHuman(reason)
- 该轮转人工,说明原因;之后该轮不能再调工具,但第二轮仍会开始。
已获认可记忆:source 为 profile、tenantId 与 userId 都一致、revision == request.profileRevision,且 verifiedAt <= request.at < validUntil。同等可用记忆若地址冲突,必须 queryProfile 核对,不能按最新或首条挑选。override 优先且仅当次。
工具本身的 memory / lookup 凭据是模拟平台的验证数据,不是 LLM 自己标注可信。每组所有工具合计最多 60 次、模拟时间最多 180 秒。不要使用 setTimeout 或引入模块。
编辑器快捷键:在代码框内按 ⌘ / Ctrl + Enter 运行全部场景;Tab 缩进;Shift + Tab 移出代码框。
正在载入编辑器…
02 运行反馈
—等待运行
先运行一次,看看哪里出问题
运行后会显示结论、场景和改进建议。
代码已修改。下面是上次运行的结果,请重新运行。
- 先看左侧的两个函数一个准备地址与治理记忆,一个检查能否安全寄送。
- 运行后,在这里找原因对照本次寄送、下次新会话和长期记忆,看错误是否会再次发生。
- 改好再运行接口就在代码上方,也可以复制给你的 Agent 帮忙。
示范不覆盖你的代码,也不计入你的成绩。
记忆跨会话 · 本次用对 ≠ 长期已改对
01
本次寄送
尚未开始
尚未选用地址
来源:—
02
下次新会话
尚未开始
尚未选用地址
来源:—
存储
长期记忆
等待核对
运行前
—
↓运行后—
每轮两个 hook 都是新实例,仅工具保存的长期记忆可复用。
当前显示最终状态
查看原始记忆 · 运行前后对照
仅当前用户的长期记忆。此处及寄送面板是排错结果,不是 ctx 可读字段。
关键事件 · 按发生顺序
需要一点提示?本场景提示
查看完整日志
“实际”行、两轮寄送和记忆前后对照只供排错,不能从 ctx 读取。代码只能使用接口速查中列出的快照与工具证据。
用到实际项目,还要补什么?
本关使用固定模型和模拟接口,只验证本关原则,不验证真实模型能力或生产可靠性。迁移时还需补齐:
- 先 ACL,再检索和读取正文。按已认证身份、租户与用户限定允许的资产范围,不要先跨用户召回正文再筛。本关混入他人索引 metadata 仅为合成测试;生产中,元数据和记录是否存在也必须受权限控制。参见 用作用域和元数据建立资产边界。
- 高风险寄送需实时权威核验。不能仅靠 TTL 判断资料是否仍有效;本关的 profileRevision 由资料系统主动提供,生产也必须有可靠的版本与变更信号。参见 让 Knowledge 提供事实、Memory 提供经验。
- 写入要留来源、审计与冲突版本。建立更正、复核和删除机制,删除还要覆盖派生索引与缓存,而不只是正文。参见 Memory 的写入与使用。
- 人工交接要有人接单。指定负责人,带上请求、身份、来源与冲突证据,约定接单确认和恢复入口;不能把“转人工”当成没有后续的终点。