第十章:实操练习
5个实操练习
学习时间: 8 小时 | 难度: ⭐⭐⭐⭐ | 前置: 第一至九章
学习目标
完成本章后,学员将能够:
- 通过阅读源码理解 Tool 接口设计
- 绘制查询循环的完整流程图
- 分析 StreamingToolExecutor 的并发模型
- 设计改进方案并实现简化版权限管道
练习 1: 阅读 Tool.ts,理解接口设计
时长: 1.5 小时 | 难度: ⭐⭐⭐
任务
阅读 src/Tool.ts (792行),完成以下任务:
- 列出所有接口字段:整理 Tool 类型的完整字段列表,包括类型、默认值、用途
- 识别元数据字段:找出所有「行为元数据」字段(isConcurrencySafe、isReadOnly 等),分析它们如何被编排层使用
- 找出 buildTool 函数:分析它的默认值设置逻辑,理解 Fail-Closed Defaults 模式
交付物
## Tool 接口字段分析
| 字段 | 类型 | 默认值 | 用途 | 被谁使用 |
|------|------|--------|------|---------|
| name | string | 必填 | ... | ... |
| ... | ... | ... | ... | ... |
## 行为元数据分析
### isConcurrencySafe
- 默认值: false
- 被 StreamingToolExecutor 使用
- 决定工具是否可以并行执行
### isReadOnly
- 默认值: false
- 被权限系统使用
- 决定是否需要权限确认
...
## buildTool 默认值分析
提示
- 注意区分「可选字段」和「有默认值的字段」
- 关注
call()vsexecute()的命名(文档中常见的错误) - 找出
validateInput和checkPermissions的区别
练习 2: 阅读 query.ts,画出查询循环流程图
时长: 2 小时 | 难度: ⭐⭐⭐⭐
任务
阅读 src/query.ts (1732行),完成以下任务:
- 识别状态转换:找出所有 Continue 类型及其触发条件
- 绘制流程图:用 Mermaid 或 ASCII art 绘制完整的查询循环流程图
- 分析错误处理:找出 Withhold-then-Recover 的具体实现
交付物
graph TD
A[query 入口] --> B[构建 System Prompt]
B --> C[准备消息]
C --> D[流式 API 调用]
D --> E{stop_reason?}
E -->|tool_use| F[StreamingToolExecutor]
F --> G[注入结果]
G --> C
E -->|end_turn| H[返回结果]
E -->|max_tokens| I{恢复次数 < 3?}
I -->|是| J[恢复尝试]
J --> C
I -->|否| K[报告错误]
E -->|prompt_too_long| L[context-collapse]
L --> C
E -->|error| M[重试/报告]
E -->|interrupt| N[用户中断]
提示
- 关注
switch语句中的stop_reason分支 - 找出恢复尝试的计数逻辑
- 注意
prompt_too_long的多级恢复策略
练习 3: 阅读 StreamingToolExecutor,理解并发模型
时长: 1.5 小时 | 难度: ⭐⭐⭐⭐
任务
阅读 src/services/tools/StreamingToolExecutor.ts (530行),完成以下任务:
- 分析并发模型:理解读并行写串行的实现机制
- 找出分区逻辑:
isConcurrencySafe如何决定工具进入并行队列还是串行队列 - 分析错误级联:AbortController 如何取消所有兄弟工具
交付物
## 并发模型分析
### 队列结构
- parallelQueue: Tool[] — 并行执行队列
- serialQueue: Tool[] — 串行执行队列
### 分区逻辑
当 LLM 流式输出 tool_use block 时:
1. 调用 tool.isConcurrencySafe(input)
2. 如果 true → 加入 parallelQueue,立即开始执行
3. 如果 false → 等待 parallelQueue 清空,独占执行
### 错误级联
当任何工具执行失败时:
1. 调用 abortController.abort()
2. 所有正在并行执行的工具被取消
3. 串行队列中的工具不会开始执行
### 结果收集
- 结果按原始顺序缓冲输出
- 即使并行执行的工具,结果也按 LLM 输出顺序返回
提示
- 关注
addTool()方法的分支逻辑 - 找出
waitForAll()的实现 - 注意结果缓冲区如何维护顺序
练习 4: 对比 OMC 的工具系统,设计改进方案
时长: 2 小时 | 难度: ⭐⭐⭐⭐
任务
基于第三章学到的知识,为 OmcHarness 的工具系统设计改进方案:
- 现状分析:列出 OMC 当前工具接口的字段
- 差距识别:对比 Claude Code 的 Tool 接口,找出缺失的字段
- 改进设计:设计增强版的工具接口
- 迁移方案:如何在不破坏现有代码的情况下升级
交付物
## OMC 工具接口增强方案
### 现状
interface CurrentTool {
name: string
description: string
call(input: any): Promise<any>
}
### 增强版
interface EnhancedTool {
name: string
description: string
inputSchema: ZodSchema // 新增:输入验证
// 行为元数据(新增)
isConcurrencySafe(input: any): boolean
isReadOnly(input: any): boolean
isDestructive(input: any): boolean
// 生命周期(新增)
validateInput?(input: any): Promise<ValidationResult>
checkPermissions(input: any): Promise<PermissionResult>
// 执行
call(input: any): Promise<ToolResult>
}
### 迁移策略
1. 新接口向后兼容(所有新字段有默认值)
2. 现有工具无需修改即可继续工作
3. 逐步添加元数据字段
4. 新工具必须实现完整接口
提示
- 默认值要偏向安全侧(Fail-Closed)
- 考虑向后兼容性
- 优先实现收益最大的字段(isConcurrencySafe, isReadOnly)
练习 5: 设计一个简化版的权限管道
时长: 1 小时 | 难度: ⭐⭐⭐
任务
基于第四章学到的知识,设计一个简化版的 3 层权限管道:
- Layer 1: 规则匹配(deny/allow 规则)
- Layer 2: 模式决策(bypass/normal 模式)
- Layer 3: 用户交互(确认/拒绝)
交付物
// simplified-permission-pipeline.ts
interface PermissionRule {
tool: string
pattern?: string
action: 'allow' | 'deny' | 'ask'
}
interface PermissionContext {
mode: 'normal' | 'bypass'
rules: PermissionRule[]
}
type PermissionResult = 'allow' | 'deny' | 'ask'
async function checkPermission(
toolName: string,
toolInput: any,
context: PermissionContext
): Promise<PermissionResult> {
// Layer 1: 规则匹配
const ruleResult = matchRules(toolName, toolInput, context.rules)
if (ruleResult === 'deny') return 'deny'
// Layer 2: 模式决策
if (context.mode === 'bypass') return 'allow'
// Layer 3: 返回规则结果
return ruleResult || 'ask'
}
function matchRules(
toolName: string,
toolInput: any,
rules: PermissionRule[]
): PermissionResult | null {
for (const rule of rules) {
if (rule.tool === toolName || rule.tool === '*') {
if (!rule.pattern || matchPattern(toolInput, rule.pattern)) {
return rule.action
}
}
}
return null // 无匹配规则
}
提示
- 从简单开始,逐步增加复杂度
- 规则匹配要考虑优先级(deny > allow > ask)
- 测试用例要覆盖边界情况
提交要求
每个练习需要提交:
- 分析文档 (Markdown 格式)
- 源码截图 (关键代码片段)
- 流程图 (Mermaid 或 ASCII art)
- 思考题答案 (每个练习 2-3 个思考题)
评分标准:
- 完整性 (40%): 是否覆盖所有要求
- 准确性 (30%): 分析是否正确
- 深度 (20%): 是否有独到见解
- 可读性 (10%): 文档是否清晰
← 09-OmcHarness启示 | 附录 →