Agent 实现方法论
From Scratch
学习地图
练习
术语表
← 返回首页
本章教程
本章练习
第 15 章测验
第 15 章测验
对应章节:服务化 v02:事件协议设计
共 8 题,答对率 ≥ 80% 即通过。请完成全部题目后点击「提交」。
Q1
第 15 章把 ch14 的 onEvent trace hook 升级成正式事件协议,核心动机是什么?
因为 ch14 的 trace 事件有 bug,必须重写
让 core 与传输层解耦:同一批事件既能被 CLI 打印,也能被 HTTP/SSE 服务推送、被 Web 前端渲染(ch16–ch18 复用)
让 trace 输出更花哨、更好看
让模型自己也能够消费事件
Q2
协议里 text_delta 的语义是什么?为什么「模型返回了文本但还要调用工具」的那一轮不发出 text_delta?
text_delta 是模型的思考过程;有工具调用时就只发思考不发文本
text_delta 是一段助手文本;有工具调用的轮次里文本只是中间态,只在停止轮(不再要工具)才以 text_delta 流出,避免前端把中间文本与最终回答混在一起渲染
text_delta 是工具执行结果的别名
text_delta 只在出错时发送
Q3
tool_call_start 与 tool_result 成对出现,设计上承担什么职责?
纯粹为了让日志好看
让模型看到工具的执行过程
让前端能渲染工具中间态(正在调用 → 结果显示),并且失败也是数据(ok:false + error 字符串),不打断主循环
用于按次计费
Q4
done 事件携带 usage(inputTokens/outputTokens),主要用途是什么?
让前端停止渲染
让循环知道该停下来
让调用方核算 token 用量(成本、配额、评估),同时作为一轮正常结束的哨兵
让工具注册表统计调用次数
Q5
本章 SSE 封装为 event 行、data 行加空行的帧格式,且 data 里也含 type 字段。为什么 data 里还要再带一份 type?
冗余浪费带宽,其实没必要
浏览器 EventSource 的 onmessage 只能拿到 data 字符串,无法区分命名事件——前端统一以 data.type 分发;event 行只是给 addEventListener 用的可选提示
为了兼容不支持 event 字段的旧浏览器
因为 JSON 里必须有 type 才能被序列化
Q6
协议里每个事件都带 sessionId,解决什么问题?
多会话隔离:一个服务同时服务多个客户端,事件按会话分桶、互不串流;客户端也按自己的 sessionId 订阅事件流
让模型记住用户身份
加密传输
让日志更好看
Q7
GET /events 的订阅处理是「先订阅、再回放已缓冲的事件」,解决什么竞态?
先订阅再回放(在同一同步 tick 内完成),迟到的订阅者既不丢事件也不收到重复事件
防止 SSE 连接数超限
防止事件顺序颠倒
让服务器可以关闭空闲连接
Q8
approval_request / approval_result 两型事件在 ch15 没有任何代码发出,为什么还要提前定义?
因为 mock 模型必须支持审批
凑数,等用到再定义也不迟
事件协议是跨章契约:ch18 权限层(auto/suggest/approve 三模式)将发出并消费它;契约先稳定、实现后到,前端的事件处理逻辑也可以提前设计
为了通过代码评审
提交