search_products 时,结果到手就应该已经排好序;agent 的活只是判断哪些结果符合用户目标、展示几条、怎么呈现——排序这件事归搜索系统,不归模型。→ 详细present_products、present_itinerary 或 present_plan_comparison;服务端校验这次调用、补全数据后发出一个事件;客户端负责渲染。因为组件本身就是工具调用,它们天然以原生格式躺在 messages 数组(对话的消息记录)里,重新加载旧对话时不用再解析。→ 详细
▲ 图注:presentation tool 的契约示例。左边模型流式生成 present_event_pacing 的参数(活动 Harbor Lights Festival、已售 62%、基线 55%、比基线高 7 个点),中间的解析器每闭合一个 JSON 单元就先画一块(标题、进度条、基线、徽标),参数校验完毕后经服务端校验与补全,右边客户端出现一张售票进度卡片。
eager_input_streaming: true,跳过缓冲,同时也放弃了服务端的 schema 保证。作者的 eval 里,Claude Sonnet 级及以上的模型违反 schema「非常罕见」,但仍建议给调用包一层重试,兜住偶尔漏网的一次。→ 详细
▲ 图注:尽早派发的时间线。模型输出流一直持续到第 5 秒才结束,但 get_usage 在约第 2 秒参数写完就立刻开跑,check_upgrade_eligibility 在约第 3.5 秒开跑——每个工具在自己的参数流完那一刻启动,而不是等整条回复结束。
user_facing_message 参数,让模型自己写。→ 详细
▲ 图注:同一个请求(十月去里斯本,找一家水边的精品酒店,再安排第一晚的晚餐)。左边等全部完成才渲染,6.0 秒里只有转圈;右边流式输出 + 进度行 + 尽早派发,总耗时同样 6.0 秒,但 0.9 秒就首次渲染,先出「正在查十月空房」「正在找第一晚的餐厅」两行进度,再出酒店 Casa do Rio(河畔精品,每晚 240 美元)和餐厅 Mesa do Cais(晚 8 点、水边露台)卡片。图中计时为示意。
▲ 图注:请求的三段式排序。Session A、B、C 共用一块稳定前缀(一个热缓存条目服务所有会话),后面接各自的上下文与历史(A 已 9 轮、B 已 3 轮、C 刚开始,只有这一段是冷的),再后是本轮新消息(下一轮才被缓存),最末是永不缓存的易变时间;反例 Session D 把一个时间戳放在最前面,它之后的内容一律缓存不上。
shoe_size 鞋码、default_store 默认门店、preferred_report_cadence 偏好的报表频率)、一个短值、一个类别,以及它来自哪个会话;有些键预先定好、人人都有,其余由抽取器自己发现。数据库的好处是:记忆库变大后仍可查询,能基于特定属性做确定性的行为,还能和你已有的用户数据做关联(join)。→ 详细
▲ 图注:异步记忆抽取。顾客说订了门垫和置物架托架、想改成到店自提,门店选「市中心,和平常一样」,还说「户外用品就别推了,我们公寓没有户外空间」,助手把自提安排暂存、等顾客确认;独立的记忆抽取器读完这段对话,往账户偏好里写入两条事实——自提:通常在市中心店自提;家:公寓没有户外空间。
apply_change 只对已经通过真实界面批准过的 ID 才会成功——运营后台里的一个按钮、CLI(命令行)里的一次确认,或者 agent 跑在 Managed Agents 上时平台自带的工具审批确认。→ 详细
▲ 图注:快照式 eval 只跑一轮。注入的状态是运营说「把周六那场演出的楼座票价调到 58 美元」,agent 已调用 stage_price_change 为 Midnight Revue 周六场暂存了编号 4821 的变更(楼座 52 美元 → 58 美元,费用不变);后端用模拟的活动目录、售票节奏数据和变更台账顶替;被测的这一轮是用户说 apply it(执行吧)。代码评分器检查 apply_change 是否走了审批路径、服务费与场地费是否没动,LLM 评判检查回复有没有说明变更正在等待审批,按 5 分制打分。
本文为文章,无问答环节。