Agent Skills实战:从提示词到可复用技能单元的工程化

发布时间:2026/8/28 17:56:36
Agent Skills实战:从提示词到可复用技能单元的工程化 如果你最近在用各种 AI Agent 框架可能会遇到一个很典型的现象同一个模型有人能让它稳定完成一整套数据分析加可视化产出有人却连一份格式正确的 JSON 都拿不回来。差别往往不在模型智商而在有没有给 Agent 配好“技能”。这里的“技能”不是提示词里多写几句“你是一个专家”而是让 Agent 具备可复用、可校验、可组合的能力单元。GitHub 上 Addy Osmani 维护的 agent-skills 项目恰好把这类实践整理成了一个可供学习的资源集。这篇文章会先讲清楚 Agent Skills 到底是什么、它和普通提示词有什么区别然后用一个完整示例演示如何设计、注册、调用和验证一个技能。如果不想看理论可以直接跳到第 6 节跑代码。先说判断Agent 的能力上限由模型决定但能力下限更多由技能体系决定。团队协作时技能才是可以沉淀、评审、复用的资产。1. 这篇文章真正要解决的问题很多开发者第一次接触 Agent 开发时会经历三个阶段。第一阶段觉得大模型什么都能干。第二阶段发现真实任务里大模型经常“自由发挥”输出不稳定。第三阶段开始研究函数调用、工具调用、Agent 编排这时候才会意识到一个真正能在项目里落地的 Agent靠的不是“模型懂”而是“工程上可控”。Agent Skills 解决的是就是“工程上可控”这一环。它的核心思路是把 Agent 完成某类任务所需要的指令、参数定义、执行逻辑、错误处理和验证方法打包成一个相对独立的能力单元。Agent 在收到任务后可以根据任务描述自动选择合适的技能或者由开发者直接指定调用链。这样输出质量不再完全依赖模型“临场发挥”而是落在了一套可测试、可维护的代码和配置上。从更宏观的视角看Agent 项目正从“单体智能”走向“组件化智能”。单体智能是让一个模型从头到尾理解并完成所有事情组件化智能则是把任务拆成多个子任务分别交给更可靠的模块去执行。Agent Skills 就是这个组件化过程中的基础单元。这篇文章适合下面几类读者正在使用 LangChain、LlamaIndex、Coze、Dify 等平台开发 Agent 应用的开发者团队里已经跑通了简单的 Agent Demo但发现效果不稳定的人想了解“技能”这一层抽象以及如何把自己的业务能力接入 Agent 的人。读完这篇文章你能理解 Agent Skills 的设计动机知道怎么用最小成本为 Agent 增加一个可复用的技能还能掌握一套监控和排查思路。整个过程不需要从零训练模型不需要改模型参数只需要在应用层做工程化设计。2. Agent 技能Agent Skills是什么概念与原理2.1 从“会聊天”到“会干活”大模型本身是一个“语言引擎”它的强项是生成符合语境的文本。但在实际业务里用户要的不是文本而是结果。比如“查一下这个接口的响应延迟”“把这批数据清洗后生成报表”“检查这段代码里的资源泄漏风险”。要让 Agent 真正完成这些任务需要一条链路理解任务 → 拆解步骤 → 调用工具/接口 → 处理结果 → 返回答案。Agent Skills 在这个链路里负责的是“调用工具/接口”之外的那部分逻辑怎么描述任务、需要哪些参数、执行什么操作、出错怎么办、结果如何校验。一个技能通常由四部分组成技能描述说明这个技能能做什么、适合什么场景参数定义声明调用这个技能需要传入哪些字段执行逻辑可以是一段代码、一个 API 调用也可以是一套外部工具脚本验证与错误处理用来判断技能是否执行成功以及失败时如何反馈给上层 Agent。2.2 提示词、工具、技能三方对比很多人会把 Agent Skills 和“提示词工程”混在一起也会把它和“工具调用”混在一起。可以从几个维度做一个对比对比维度提示词 Prompt工具 Tool技能 Skill本质文本指令可调用的函数/API结构化的能力单元复用性弱容易散落中可以跨场景调用强可打包、分享、版本化可编排性不适合编排支持但缺少流程支持且可组合成更复杂工作流错误处理依赖模型判断函数内部处理内置校验和反馈机制通俗类比口述菜谱一把菜刀一位只会做川菜的厨师用类比来说提示词是“口述怎么做”工具是“给你工具”技能则是“一个可以直接帮你做好的专业模块”。Agent 不需要重新理解技能内部原理只需要传入参数并接收结果。2.3 为什么技能层抽象很重要从工程实践看技能层抽象带来三个直接好处。第一稳定。技能内部逻辑是代码不是模型生成的文本它的行为是可以预期、可以测试的。模型只负责“决定调哪个技能”和“把结果组织成回答”不再负责具体步骤的每一步推理这就大幅降低了“自由发挥”的可能性。第二复用。同一个技能可以在不同 Agent 中使用。比如“代码安全审计”技能既可以被代码审查 Agent 使用也可以被 CI 机器人使用。团队里沉淀技能就等于沉淀经验。第三可治理。技能有明确的输入输出定义方便做权限控制、日志记录、审计和灰度发布。这对于企业环境来说非常重要因为生产环境里我们不能接受一个“行为不可预测”的 AI 组件直接操作核心数据。3. 为什么 agent-skills 这类项目值得关注3.1 项目背景判断Addy Osmani 是 Google Chrome 团队中为人熟知的技术专家长期关注 Web 性能和前端工程化。他在 GitHub 上维护 agent-skills 项目把 AI Agent 开发中的技能设计、组织与使用经验整理成资源集对很多刚开始构建 Agent 应用的开发者来说是一个很好的切入点。需要说明的是agent-skills 不是一个大而全的 Agent 框架它更像是一套参考实践和资源清单。它的价值在于把“技能”这个抽象概念落到一组可以学习的示例上帮助开发者理解技能应该怎么划分、怎么命名、怎么描述、怎么集成。对于团队来说这可以当作设计内部 Agent 技能体系的一份起点文档。3.2 从“一个 Agent 干所有事”到“一组技能解决问题”在老思路里开发者倾向于把任务完整地写进一个提示词希望模型“自己搞定一切”。这种做法适合 Demo 和简单任务但在真实业务中会很快碰壁因为长任务的中间步骤一旦出错模型很难自行纠正而且定位问题时非常痛苦。技能化的思路则是把大任务拆成多个小技能。比如一个“生成周报”的任务可以拆成“读取数据源”技能、“分析趋势”技能、“生成 Markdown 表格”技能、“校验数据一致性”技能。每个技能独立测试、独立维护。Agent 只负责调度和编排具体能力由技能来保障。这正是 agent-skills 这类项目所承载的工程思维把不可控的智能行为拆解成可控的工程模块。3.3 什么时候用技能什么时候直接写代码一个新手容易困惑的问题是我有 Python 函数了为什么还要包一层技能关键判断标准是这个能力是要给 Agent 用的还是要给普通代码用的。如果是普通代码调用直接 import 函数就行。如果是让 Agent 在“自主理解任务”后调用就必须给模型提供清晰的信息包括技能描述、参数说明和适用场景。模型不是程序员它看不到函数内部实现只能靠技能描述来决定“什么时候该用这个技能”。所以技能的描述文本甚至比实现代码更重要。一个写得模糊的技能描述会让模型在错误的时候调用正确的技能或者在正确的时候错过它。这一点在 agent-skills 的实践里被反复强调。4. 环境准备与前置条件在开始编写技能之前需要准备一套最小可运行的环境。下面的版本号不建议直接照搬建议以你实际项目的依赖为准这里重点演示通用思路。4.1 基础运行环境操作系统Windows 10/11、macOS 或主流 Linux 发行版均可Python建议使用 3.10 及以上版本方便使用较新的类型注解和语法Node.js如果技能涉及 JavaScript/TypeScript 生态再安装 Node 18 以上版本包管理器Python 使用 pip 或 poetryNode 使用 npm 或 pnpm代码编辑器VS Code 或者其他你熟悉的 IDE。4.2 Agent 运行框架技能本身只是一个“能力单元”要和 Agent 配合才会发挥作用。你可以基于任意常见框架接入例如 LangChain、LlamaIndex、Coze、Dify 等。本文示例会展示一个不依赖特定框架的通用实现方便你迁移到自己的技术栈中。如果用 Python 环境常见的依赖包括 openai SDK、pydantic 用于参数校验以及 fastapi 用于暴露服务接口。这些依赖并不强求全部安装按需选择即可。建议先在一个独立的虚拟环境中操作避免污染全局 Python 环境python -m venv venv source venv/bin/activate # Windows 下使用 venv\Scripts\activate pip install pydantic openai fastapi uvicorn4.3 API Key 与安全设置如果技能会调用大模型接口需要准备对应的 API Key。这里有一个容易被忽视的安全问题不要把 Key 硬编码在代码里。推荐使用环境变量并在 .gitignore 中忽略 .env 文件。# .env 文件示例不要提交到版本库 AGENT_API_KEYyour_api_key_here AGENT_MODEL_NAMEgpt-4o-mini# config.py import os API_KEY os.getenv(AGENT_API_KEY, ) MODEL_NAME os.getenv(AGENT_MODEL_NAME, gpt-4o-mini)如果是在企业内部使用更稳妥的方式是接入密钥管理服务例如云厂商的 KMS 或自建的 Vault而不是在应用配置里传递密钥。4.4 技能目录规划推荐在项目里单独创建一个 skills 目录每个技能一个子目录结构尽量一致。后续可以直接按目录扫描并自动注册技能。skills/ ├── code_audit/ │ ├── skill.yaml │ ├── main.py │ └── README.md ├── data_clean/ │ ├── skill.yaml │ ├── main.py │ └── README.md └── weekly_report/ ├── skill.yaml ├── main.py └── README.md这种组织方式有两个好处一是方便别人阅读和评审二是方便写脚本做自动发现不需要在代码里手动维护一份技能清单。5. 核心流程拆解设计一个 Agent 技能的最小路径不管技能本身多复杂设计过程都可以拆成五个步骤。每一步都存在容易踩坑的地方下面逐个说。5.1 定义技能边界首先要明确“这个技能负责什么、不负责什么”。边界模糊是技能设计里最常见的问题。比如“数据分析”技能听起来很全能但真正落地时你会发现它什么都做不好。更好的做法是拆分“数据清洗”“统计摘要”“趋势分析”各自独立成技能。判断标准很简单如果这个技能的描述里出现了“和/或”说明边界可能过大建议再拆分。5.2 编写技能描述技能描述是给模型看的不是给人看的。好的描述应当包含三部分这个技能能做什么适合什么场景不适合什么场景。举个例子好的描述是“代码审计技能分析给定代码片段中的安全风险和资源泄漏问题适用于 Python、Java、JavaScript 代码。不擅长处理部署配置和基础设施问题。”这个描述里既有“何时使用”的信息也明确划掉了“何时不要用”能显著减少模型误调用概率。5.3 定义参数 Schema参数定义相当于技能的“接口契约”。用 JSON Schema 或 Pydantic 模型声明让模型知道该传什么、每个字段类型是什么、哪些字段必填。这一步不能省略否则调用时经常会出现字段名和类型不匹配的问题。5.4 实现执行逻辑执行逻辑是技能的核心代码。需要注意两点一是输入参数必须先校验再使用二是执行逻辑要足够内聚尽量不要在技能内部再调其他 Agent否则会引入不确定性。5.5 注册并测试最后一步是把技能注册到 Agent 的可用技能列表中。注册过程通常就是把技能的名称、描述、参数 Schema 和执行入口注册到框架的注册表中。注册完成后至少要跑通三个测试正常调用、参数错误、执行异常。三个测试都要有确定的行为不能让模型在异常时“猜”该如何回答。6. 完整示例给 Agent 添加一个“代码审计”技能下面用一个完整示例把上面的流程串起来。这个示例会模拟一个“代码审计”技能用来检查 Python 源码中常见的资源泄漏和异常处理问题。为了演示清晰实现会保持轻量不依赖具体 Agent 框架方便迁移。6.1 技能定义文件技能定义使用 YAML 格式这是 agent-skills 项目非常推荐的声明方式。先创建一个文件skills/code_audit/skill.yamlname: code_audit description: 分析给定 Python 代码片段中的资源泄漏、缺少异常处理和潜在性能问题。 适合用于代码审查、CI 检查、代码提交前自检等场景。 不擅长处理前端样式问题不适合对非 Python 代码做全面审计。 version: 1.0.0 author: team_platform parameters: type: object properties: code: type: string description: 需要审计的 Python 源码文本 language: type: string enum: [python] description: 代码语言目前仅支持 python default: python required: - code注意description字段中明确写了“适合什么”和“不适合什么”这是为模型准备的关键决策信息。6.2 技能执行入口创建skills/code_audit/main.py# 文件路径skills/code_audit/main.py import ast from typing import Any, Dict, List class CodeAuditResult: 审计结果结构 def __init__(self, severity: str, line: int, message: str): self.severity severity self.line line self.message message def to_dict(self) - Dict[str, Any]: return { severity: self.severity, line: self.line, message: self.message, } def audit_code(code: str, language: str python) - Dict[str, Any]: 审计一段 Python 代码。 if language ! python: return { success: False, error: f暂不支持语言: {language}, issues: [], } issues: List[CodeAuditResult] [] try: tree ast.parse(code) except SyntaxError as e: return { success: False, error: f代码语法错误: {e}, issues: [], } # 检查文件操作是否缺少 with 语句 for node in ast.walk(tree): if isinstance(node, ast.Call): func_name None if isinstance(node.func, ast.Name): func_name node.func.id elif isinstance(node.func, ast.Attribute): func_name node.func.attr if func_name in (open, connect, startswith): # 判断外层是否被 with 包裹 parent_with False for parent in ast.walk(tree): if isinstance(parent, ast.With): for item in parent.items: if item.context_expr is node: parent_with True # 这里的检测逻辑比较简单只作为演示 if not parent_with and open in func_name: issues.append(CodeAuditResult( severitywarning, linegetattr(node, lineno, 0), message检测到 open() 调用建议使用 with 语句管理资源, )) # 检查裸 except if isinstance(node, ast.ExceptHandler): if node.type is None: issues.append(CodeAuditResult( severitywarning, linegetattr(node, lineno, 0), message裸 except 会吞掉所有异常建议明确捕获异常类型, )) return { success: True, issues: [issue.to_dict() for issue in issues], } if __name__ __main__: sample_code def read_file(path): f open(path, r) data f.read() return data def safe_divide(a, b): try: return a / b except: return None result audit_code(sample_code) print(result)这个实现刻意保持简洁重点不是做完整的静态分析而是演示技能的执行入口应该怎么组织。你可以在真实项目中接入 pylint、bandit、semgrep 等成熟工具把它们的扫描结果转换成上面的统一格式。6.3 注册技能到 Agent 运行时技能的注册逻辑可以在每个框架中自定义。下面是一个简单的注册器示例它扫描 skills 目录读取 YAML 定义并将执行入口挂载到注册表中# 文件路径skill_registry.py import importlib.util import os import sys from typing import Callable, Dict, Any import yaml SKILLS_DIR skills def load_skill(skill_dir: str) - Dict[str, Any]: 加载一个技能目录返回技能元信息 skill_yaml os.path.join(skill_dir, skill.yaml) main_py os.path.join(skill_dir, main.py) with open(skill_yaml, r, encodingutf-8) as f: meta yaml.safe_load(f) spec importlib.util.spec_from_file_location( f{os.path.basename(skill_dir)}_main, main_py ) module importlib.util.module_from_spec(spec) spec.loader.exec_module(module) return { meta: meta, execute: module.audit_code, } def register_all_skills() - Dict[str, Dict[str, Any]]: 扫描 skills 目录注册所有技能 registry {} if not os.path.exists(SKILLS_DIR): return registry for name in os.listdir(SKILLS_DIR): skill_path os.path.join(SKILLS_DIR, name) if not os.path.isdir(skill_path): continue try: skill load_skill(skill_path) registry[skill[meta][name]] skill print(f[registry] 已注册技能: {skill[meta][name]}) except Exception as e: print(f[registry] 技能加载失败: {name}, 错误: {e}) return registry if __name__ __main__: reg register_all_skills() print(f共注册 {len(reg)} 个技能)这里用importlib动态加载技能目录下的main.py并将audit_code函数作为执行入口。执行入口的统一签名很重要输入一个字典输出一个字典这样上层 Agent 才能用统一方式调用所有技能。6.4 让 Agent 根据描述选择技能注册好技能之后Agent 需要根据任务描述决定调用哪个技能。这里给出一个简化的选择逻辑它演示了基于描述的匹配思路。生产环境中这个选择可以由大模型完成也可以由规则引擎完成。# 文件路径agent_demo.py from skill_registry import register_all_skills # 假设这是已经注册好的技能注册表 REGISTRY register_all_skills() def run_agent_task(user_task: str, target_code: str) - dict: 简化版 Agent 调度示例 1. 根据任务关键词选择合适的技能 2. 调用技能执行 3. 返回结果 task_lower user_task.lower() # 这里演示一个简单规则生产环境应由模型做调度 if 审计 in task_lower or 安全 in task_lower: skill_name code_audit else: return {success: False, error: 未找到匹配技能} if skill_name not in REGISTRY: return {success: False, error: f技能 {skill_name} 未注册} skill REGISTRY[skill_name] result skill[execute]({code: target_code, language: python}) return {skill: skill_name, result: result}在真实场景里模型应该拿到每个技能的“描述 参数 Schema”然后自行判断。这里用规则匹配是为了降低运行成本也让流程更直观。理解了这个最小示例后换成模型决策是顺理成章的。7. 运行结果与效果验证7.1 执行技能脚本先直接运行技能本身cd skills/code_audit python main.py预期输出会包含几条审计问题格式类似下面这样{ success: true, issues: [ { severity: warning, line: 2, message: 检测到 open() 调用建议使用 with 语句管理资源 }, { severity: warning, line: 8, message: 裸 except 会吞掉所有异常建议明确捕获异常类型 } ] }如果输出格式和预期一致说明技能本身可以正常工作。这里判断成功的标准不是“有没有发现问题”而是“返回结构是否正确、异常分支是否被处理”。7.2 运行带注册的 Agent 示例回到项目根目录运行注册脚本python skill_registry.py预期输出[registry] 已注册技能: code_audit 共注册 1 个技能如果这里显示 0 个技能优先检查 skills 目录路径是否正确以及skill.yaml中的name字段是否和目录名匹配。7.3 验证一次完整调度运行 agent_demo.py 中的逻辑传入“审计这段代码”任务python -c from agent_demo import run_agent_task; print(run_agent_task(请审计这段代码, def f():\n return open(\x\)))预期结果中会包含skill: code_audit和审计问题列表。这说明从任务输入到技能选择、到执行、到返回结果整条链路是通的。7.4 失败时先看哪里如果链路不通按下面的优先级排查技能脚本独立运行是否成功先排除技能内部 bug注册时是否打印了“已注册技能”确认注册器没有静默失败技能名称是否匹配run_agent_task中使用的技能名必须和skill.yaml中一致输入参数是否命中Agent 传参时是否把代码放在code字段里。8. 常见问题与排查思路以下问题是技能开发过程中出现频率最高的几类问题现象可能原因排查方式解决方案Agent 在不需要的时候调用了技能技能描述写得太宽泛检查技能description看是否存在“万能”表述明确写出适用场景和非适用场景需要调用技能时 Agent 没有调用技能描述没有呈现关键触发词查看 Agent 日志中模型收到的技能列表在描述中补充触发场景关键词技能参数传错模型总是漏字段参数 Schema 定义不清晰检查必填字段和描述文本为每个参数补充详细描述必要时提供示例技能执行报错Agent 无法恢复技能内部缺少异常兜底手动执行技能入口复现异常在技能执行入口统一捕获异常返回结构化错误新增技能后 Agent 反而变笨可用技能太多选择噪音变大查看模型实际收到的技能数量收敛技能列表按任务分组或增加路由层技能在本地正常部署到服务器失败环境依赖不一致对比本地和服务器 Python/依赖版本使用依赖锁定文件统一基础镜像技能输出偶尔不稳定技能内部又调用了大模型审查技能实现中是否包含模型调用技能内部尽量用确定性代码避免模型二次生成多个技能相互调用形成循环技能边界划分不清检查技能描述和依赖关系重新梳理边界禁止技能之间相互递归调用比较容易被忽略的一点是“技能太多导致模型选择困难”。当一个 Agent 暴露给模型 40 个技能时选择的准确率一定低于只暴露 8 个相关技能时的表现。所以技能体系不是越多越好而是越清晰越好。你可以把技能按业务域分组先做一个粗粒度路由再在每组内让模型做细粒度选择。另一个常见坑是技能内部的“隐藏模型调用”。如果技能的最终输出是模型生成的那么这个技能的可靠性就和直接使用提示词没有本质区别。技能的价值在于确定性内部如果还要调模型就要确保这个调用被严格控制和验证。9. 最佳实践与工程建议9.1 技能命名与描述规范技能名称建议使用“动词_对象”的结构比如fetch_github_issue、clean_dataframe、audit_code。这种命名法在技能列表里一眼能看出作用模型在匹配时也更容易命中。描述文本建议按“做什么 适用场景 不适用场景”三段来写不让模型做过多猜测。避免使用“这是一个用于各种数据分析的综合性工具”这样的模糊表达它等于没有描述。9.2 参数严格校验每个技能入口的第一步都应该是参数校验。以 Python 为例可以用 pydantic 定义输入模型from pydantic import BaseModel, Field class CodeAuditInput(BaseModel): code: str Field(..., description要审计的 Python 源码) language: str Field(python, description代码语言) def audit_code_with_validation(raw_input: dict): try: data CodeAuditInput(**raw_input) except Exception as e: return {success: False, error: f参数校验失败: {e}} # 继续执行审计逻辑参数校验失败时必须返回结构化错误而不是抛出未处理异常。这样上层 Agent 才能理解发生了什么并决定下一步策略。9.3 返回值统一结构所有技能尽量返回统一结构。这里推荐一个最小契约{ success: true, data: {}, error: null }失败时{ success: false, data: null, error: 错误描述 }统一结构的好处是上层可以写一套通用的错误处理逻辑而不是针对每个技能单独写分支。9.4 日志与可观测性技能执行时要记录关键信息被谁调用、输入参数摘要、执行耗时、返回结果状态。日志字段建议包含skill_name、request_id、input、output、latency_ms、success。这样在排查问题时可以用请求 ID 串联一条完整链路。技能内部的敏感数据不要记录到日志。比如代码内容可能包含密钥或内部逻辑日志里只记录代码长度和哈希值更加安全。9.5 技能版本与管理技能也会演进和业务代码一样需要版本管理。建议在skill.yaml中保留version字段并且在技能列表里暴露版本号。当某个 Agent 应用需要固定技能版本时可以锁定版本避免上游变更影响线上行为。更稳妥的方式是把技能放进独立的 Git 仓库用 CI 做校验和发布。每一轮变更都走代码评审合并后自动同步到对应环境。9.6 安全边界的敬畏技能一旦接入 Agent就等于把操作权交给了模型调度。某些技能可能涉及文件删除、数据库写入、数据外发等危险操作。这类技能必须做三重防护最小权限进程运行账户只授予完成任务所需的最小权限审批机制高危技能不直接执行而是把执行请求发给人工确认操作审计所有高危技能的调用都记录完整上下文包括任务描述和参数。就算 Agent 不会主动作恶也要假设它可能被提示注入攻击诱导。这是所有面向生产环境的 Agent 应用都必须考虑的问题。10. 总结与后续学习方向这篇文章从“为什么 Agent 经常不给力”出发聊清楚了 Agent Skills 的核心价值把不可控的智能行为拆成稳定、可复用、可治理的能力单元。在第 2 节中可以看到技能和提示词、工具并不是一回事。提示词是文本指令工具是函数技能则是带有描述、参数契约、执行逻辑和错误处理的结构化能力包。第 3 节解释了 agent-skills 这类项目为何值得关注本质上是因为它把“技能化设计”从概念变成了可参考的实践。第 5、6、7 节用一个代码审计技能串起了设计、实现、注册、调度和验证的完整流程。第 8 节和第 9 节则给出了日常开发中最常见的坑和团队落地建议。如果想继续深入建议按这个顺序实践把自己手头一个重复性的“提示词工程”任务重构成一个技能先跑通最小闭环为技能补充参数校验、结构化错误返回和日志字段接入实际使用的 Agent 框架看看模型是否能在任务中正确选择这个技能把多个技能组合成一个多技能工作流验证编排能力最后再考虑技能版本管理、权限控制和团队共享机制。记住一个原则技能的稳定来自于实现的确定性技能的上限则需要靠清晰的描述和调度来保证。不要试图让一个技能包罗万象宁可多拆几个也不要做一个看起来很全能、用起来却抓不准的技能。Agent 应用的能力成熟度很多时候就是看一个团队能不能把技能体系搭建得足够清晰。