Claude Skills实战:构建专业级AI Agent的完整指南

发布时间:2026/10/3 20:55:03
Claude Skills实战:构建专业级AI Agent的完整指南
去年年底到今年AI Agent 开发几乎成了圈子里绕不开的话题。我自己的项目从简单的 Prompt 组合到接入各种工具链踩了不少坑也一直在找一个既灵活又不至于失控的落地方式。直到我把Claude Skills用进生产项目才真正感觉到“Agent 开发”这件事从拼 Prompt 变成了拼工程化能力。这篇文章不聊概念只讲我在实际项目中怎么用 Claude Skills 搭一个专业级 AI Agent从核心设计、目录规范、脚本实现到排查实录全部是我自己验证过的路径你可以直接照着抄。整篇内容适合两类人一是已经用 Claude 写代码、做自动化但觉得“对话式”开发不够稳定的开发者二是想从零开始搭建 Agent又不想一上来就被 LangGraph、多智能体框架绕晕的朋友。读完你会清楚Skills 和 MCP 的分工边界在哪里一个可复用的技能应该怎么拆遇到“技能加载失败”“上下文刷爆”这类问题该怎么定位。1. 站在 Agent 开发的分岔路口为什么 Claude Skills 值得学如果你和我一样从 AI 编程工具刚火的时候就开始折腾大概会经历三个阶段先是觉得“对话生成代码好神奇”然后发现“改来改去还是得自己动手”最后开始研究“怎么让模型自动执行多步骤任务”。Claude Skills 就是第三个阶段的产物它把“一次性对话生成”升级成了“可复用、可组合、可审计的技能调用”。我最初看到 Skills 这个概念时第一反应是“这不就是高级版的 Prompt 模板吗”结果动手搭了一个代码审查技能之后发现完全不是一回事。核心区别在于Skills 让 Claude 具备了一套完整的“感知-决策-执行”闭环。模型不再只是“读你写的提示词然后给建议”而是能够在合适的时候主动调用你准备好的脚本、读取你指定的文件、按照你预设的检查清单执行任务最终给出结构化结果。1.1 从 Prompt 工程到技能装配范式转变先聊一个我自己的真实感受以前做自动化最痛苦的不是模型不会写代码而是“它每次写的都不一样”。同一个需求今天让它生成一个数据清洗脚本它给你用 pandas明天再问又改成了纯 Python 文件读写。不是模型不好而是它的行为边界太宽了。Claude Skills 出现之后这个问题被“技能装配”的思路解决了。每个技能本质上是一个带有 YAML 元信息的目录里面有一个SKILL.md文件描述这个技能是干什么的、什么时候该调用、有哪些执行步骤再加上可选的脚本目录。当 Claude 在执行任务时感觉到“当前场景和某个技能描述匹配”它就会自动加载这个技能的指令和工具。这样你就把“每次对话都要从零约束模型”变成了一次性定义、无限次复用。我项目里有一个“日志巡检”技能定义好之后每次让它检查服务器日志它都会按照我写的检查顺序来先过滤 ERROR 级别再按时间窗口聚合最后生成报告。输出风格、字段格式完全稳定这一点在交付客户项目的时候非常加分。1.2 与 MCP、Agent SDK、Function Calling 的分工与边界很多人会把 Claude Skills 和 MCP 混在一起其实它们是互补关系不是替代关系。我打个比方MCP 是“插头”解决的是 Claude 怎么连接外部数据源和工具Skills 是“作业指导书”解决的是 Claude 拿到工具之后怎么做才规范。一个管连接一个管流程。在实际项目里我的经验是先看任务需不需要外部数据源。如果只是让 Agent 基于已有文件、代码库做分析和操作Skills 就够了不需要引入额外的服务。如果 Agent 要读数据库、调用第三方 API、操作内部运维平台那就通过 MCP 把这些能力接进来然后在 SKILL.md 里说明“执行这个任务时优先使用哪个 MCP 工具”。这里顺带提一下 Agent SDK 和 Function Calling 的边界。Function Calling 是模型和函数之间的“一次性握手”适合单轮工具调用Agent SDK 偏重于构建完整的智能体运行时适合复杂的状态流编排而 Claude Skills 更像是一种轻量级的“能力模块”你既可以在 Claude Code 里直接用也可以配合 Agent SDK 把它们组织成更大的任务图。如果项目还处于验证阶段我建议优先从 Skills 入手成本最低见效最快。2. 构建你的第一个 Claude Skills Agent整体设计与思路拆解我真正把 Claude Skills 用到生产环境是给团队搭了一个“代码变更影响分析 Agent”。这个 Agent 的输入是一段 git diff输出是受影响的模块、潜在风险点、建议补充的测试用例、需要人工确认的变更项。早期用纯 Prompt 做每次输出格式都不一样后来用 Skills 重写输出稳定性和可维护性直接上了一个台阶。这个项目从设计到落地大概花了三天核心就一句话把 Agent 的“经验”沉淀成“技能”把“技能”变成可被模型自动触发的工程资产。下面我把整个设计思路和方案选型过程拆开来讲包括每个选择背后的原因。2.1 与“无脑堆 Prompt”相比Skills 方案的三个核心优势设计方案的时候我其实纠结过是继续在 CLAUDE.md 里写一堆长篇指令还是迁移到 Skills。当时对比下来Skills 压倒性胜出核心优势有三个第一个优势是触发成本低。CLAUDE.md 里的指令不管当前任务需不需要Claude 每次都要把所有内容读进上下文既占 token 又会造成“指令疲劳”——写太多规则模型反而不知道该优先遵守哪一条。Skills 是按需加载的模型根据当前任务判断是否命中某个技能然后再读取该技能的完整描述。也就是说技能一多上下文反而更干净。第二个优势是可版本化。每个技能都是一个独立目录天然适合用 Git 管理。我可以给产品版本创建一个技能分支给测试环境创建另一个技能分支哪个技能出现回归单独回滚那一个目录就行。这在纯 Prompt 方案里是做不到的——CLAUDE.md 一改整个 Agent 行为都受影响。第三个优势是边界清晰。Skills 可以在 YAML 头里声明允许使用哪些工具甚至指定模型。这种“技能内部声明”让权限控制变得很直观我可以把一个技能配置成只能读文件不能执行命令把另一个技能配置成可以调用 Bash 但不能联网。作为交付物给客户演示的时候也特别容易讲清楚。相比之下纯 Prompt 方案里的权限是靠“语气”约束的模型偶尔会不听。2.2 方案选型Skills 少量脚本 vs 完整 Agent 框架在动手之前我还考虑过直接用 LangGraph 或者 Spring AI 那套多智能体框架来做。后来放弃了原因很简单对于单 Agent 多技能的场景上框架是过度设计。LangGraph 适合需要复杂状态机、多 Agent 协作、精细控制循环时长的场景但如果你核心诉求是“让 Claude 在正确的时候做正确的事”Skills 天然就是那个“正确的事”的容器。这不是说框架没用。实际上当我需要同时跑“代码分析 Agent”和“文档生成 Agent”并且要共享结果时我会用 Agent SDK 做编排让两个 Agent 通过共享状态协作。但每个 Agent 内部的“专业能力”依然来自 Skills。所以更准确的说法是Skills 是 Agent 的“肌肉”框架是“骨骼”两者并不冲突。另一个差点让我走弯路的选择是“有没有必要每个步骤都写脚本”。我的答案是不需要。Skills 的 SKILL.md 里可以直接写步骤指令让 Claude 自己决定怎么执行。只有那些对确定性要求极高的环节比如解析 git diff、过滤日志、解析 JSON才值得写一个独立脚本因为让模型用自然语言去解析复杂文本偶尔会出低级错误但脚本永远不会。我最终的方案是约 30% 的环节写成 Python 脚本70% 的环节用自然语言步骤描述。3. 从零到一专业级 Agent 的实操过程与核心实现有了设计思路接下来就是动手。这一节我会完整展示我是怎么搭建一个“代码变更影响分析 Agent”的从技能目录结构、SKILL.md 的 YAML 配置到核心 Python 脚本、Agent 主配置每一步都给出可直接复制的代码。这个项目目录规范我后来直接复用到其他 Agent 上算是被验证过的模板。需要提前说明的是下面的实现基于 Claude Code Claude Skills 的常见实践路径Skill 目录结构、YAML 字段是当前版本验证可用的方案。如果未来 Claude 版本更新导致字段变化核心思路依然成立无非是配置字段名称有调整。3.1 第一步初始化技能目录与工程骨架先约定一下技能存放位置。Claude Code 默认会扫描两个技能目录用户级目录~/.claude/skills/和项目级目录.claude/skills/。我的习惯是通用技能比如代码审查、日志分析放用户级任何项目都能用项目专属技能比如针对某个系统的变更分析放项目级避免污染其他项目。# 创建项目级技能目录 mkdir -p .claude/skills/impact-analysis/scripts # 查看目录结构 tree .claude/skills/ # .claude/skills/ # └── impact-analysis # ├── SKILL.md # └── scripts # ├── parse_diff.py # └── report_generator.py这里有一个细节技能目录名建议用英文短横线命名比如impact-analysis不要用空格或者中文。原因有两个一是模型在自然语言描述中引用技能时短横线命名更容易被准确识别二是在文件路径中短横线不会引发转义问题。我最初建了一个叫代码分析工具的目录后面在脚本里引用路径时踩了不少坑统一改成英文后就好了。3.2 第二步编写 SKILL.md 并理解 YAML frontmatterSKILL.md 是整个技能的“大脑”。它分为两部分开头的 YAML frontmatter 和正文的 Markdown 指令。模型会先读取 frontmatter 里的 description 来决定“当前场景是否要用这个技能”命中之后才会读取正文来执行具体步骤。--- name: impact-analysis description: 分析代码变更影响范围识别风险模块生成测试建议。当用户提供 git diff、代码变更、commit 信息或要求评估某个改动的影响范围时使用本技能。典型触发场景包括代码审查、合并请求预检、变更风险评估、上线前影响面确认。 allowed-tools: - Bash - Read - Write model: claude-sonnet-4-5 ---这几个字段的含义我逐个说明name技能的唯一标识建议和目录名保持一致。description这是整个 SKILL.md 里最重要的字段。模型就是靠它来判断“什么时候该用这个技能”。如果描述太窄模型会漏用太宽则会在不该用的时候强行触发。我这边测试下来最有效的描述写法是“功能描述 触发条件 典型场景列举”三段式命中率能从 60% 提到 90% 以上。allowed-tools技能可以使用的工具白名单。这里我只给了 Bash、Read、Write意思是这个技能可以做文件读写和命令执行但建议你根据场景收紧。比如一个纯分析技能完全不需要 Write 权限。model可选字段指定该技能使用哪个模型执行。像这种需要严谨分析的任务我会指定 Sonnet响应速度更快且成本适中。需要高难度推理时再切到 Opus。说完 frontmatter再看 SKILL.md 正文部分。正文以 Markdown 编写核心任务是告诉模型“拿到这个技能之后按照什么步骤执行、中间要注意什么、输出什么格式”。我给这个技能写的正文指令如下# 代码变更影响分析技能 ## 执行步骤 1. 首先通过 git diff --stat 概览变更范围再通过 git diff commit1 commit2 获取完整变更内容。 2. 调用 python3 scripts/parse_diff.py diff文件路径 解析变更提取变更文件列表、新增/删除行数、涉及的关键函数名。 3. 根据解析结果逐一判断每个变更文件的风险等级 - 高风险改动核心业务逻辑、公共工具函数、数据库迁移脚本。 - 中风险改动模块内部实现但不涉及对外接口。 - 低风险新增独立文件、注释修改、不影响逻辑的格式化调整。 4. 生成测试建议针对高风险文件列出重点回归场景针对中风险文件列出冒烟测试范围。 5. 将结果写入 markdown 文件 impact_report_YYYYMMDD.md输出给用户。 ## 注意事项 - 如果 diff 中涉及依赖管理文件如 requirements.txt、package.json务必在报告中单独列出并提示团队检查依赖冲突。 - 如果变更文件包含 TODO/FIXME 注释在报告中单独标记。 - 分析结论必须基于 diff 内容不要推测文件内容必要时才读取目标文件。这段正文的目标是让模型“有章法地干活”而不是漫无目的地看代码。你可以把它理解成给实习生写了一份带流程、带标准、带交付物要求的任务书模型按着这份任务书执行产出的稳定度就会非常高。3.3 第三步编写核心解析脚本并理解“为什么需要脚本”SKILL.md 解决的是“怎么干活”但有些环节我还是坚持用脚本。拿 diff 解析来说直接让模型读一段几百行的 git diff 并总结变更点它勉强能用但一旦 diff 达到几千行模型会开始丢细节、漏文件。脚本不会。下面这个是parse_diff.py的简化版本核心功能是解析 diff 并统计变更文件与函数级变更点。#!/usr/bin/env python3 import re import sys from collections import defaultdict def parse_diff(diff_text): 解析 git diff 文本返回文件级变更统计和函数变更点。 file_changes [] current_file None hunk_info None func_changes [] for line in diff_text.splitlines(): if line.startswith(diff --git): # 新文件开始 match re.match(rdiff --git a/(.*) b/(.*), line) if match: current_file match.group(2) file_changes.append({ file: current_file, additions: 0, deletions: 0, funcs: [] }) elif line.startswith() and current_file: hunk_info line # 提取 hunk 中提及的函数名常见于 Java/Python 等语言 func_match re.search(r.*\s*(?:-\s*)?(?:class|def|func|function)\s([a-zA-Z_][a-zA-Z0-9_]*), line) if func_match: func_changes.append({file: current_file, func: func_match.group(1)}) elif current_file and (line.startswith() and not line.startswith()): file_changes[-1][additions] 1 elif current_file and (line.startswith(-) and not line.startswith(---)): file_changes[-1][deletions] 1 elif current_file and line.startswith() and ( in line and ) in line: # 粗略识别新增函数调用 call_match re.search(r([a-zA-Z_][a-zA-Z0-9_]*)\s*\(, line[1:]) if call_match: file_changes[-1][funcs].append({type: call, name: call_match.group(1)}) # 合并函数变更信息到文件变更 for fc in func_changes: for fc_item in file_changes: if fc_item[file] fc[file]: fc_item[funcs].append({type: def, name: fc[func]}) return file_changes if __name__ __main__: if len(sys.argv) 2: print(Usage: python3 parse_diff.py diff_file) sys.exit(1) with open(sys.argv[1], r, encodingutf-8) as f: content f.read() result parse_diff(content) for item in result: print(f文件: {item[file]} ({item[additions]}/-{item[deletions]})) for func in item[funcs]: print(f 变更点: {func[type]} - {func[name]})这个脚本不复杂但它把“提取变更文件、统计增删行数、定位函数级别变更点”这三个最耗 token 的操作从模型手里拿走了。模型只需要读取脚本输出的一小段结构化文本就能基于它做分析和判断上下文占用大幅下降。写脚本时有一个比较容易忽略的点不要试图让脚本一步到位生成最终报告。脚本只负责“数据提取”把报告交给模型去写因为报告需要结合业务语境做表达这是模型的强项而数据提取是确定性的交给脚本才可靠。不要反着来。3.4 第四步配置 Agent 主入口并在 Claude Code 中验证技能目录和脚本准备好之后还需要有一个“Agent 主入口”让 Claude 知道当前项目的背景、任务目标和如何使用这些技能。这个入口就是项目根目录下的CLAUDE.md在 Claude Code 中扮演“团队负责人”的角色统领所有技能调用。# 项目背景 这是一个电商后端仓库技术栈为 Python FastAPI PostgreSQL。 本项目使用 Claude Skills 构建“代码变更影响分析 Agent”。 # Agent 工作目标 当收到 git diff 后自动调用 impact-analysis 技能输出变更影响报告。 # 工作规范 - 所有影响分析必须调用 impact-analysis 技能不得脱离技能自行分析。 - 生成报告使用统一模板变更概览、风险模块、测试建议、待确认事项。 - 报告输出到 docs/impact-reports/ 目录文件名格式 impact_report_YYYYMMDD.md。 # 常用命令 - 查看当前分支变更git diff main...HEAD - 运行技能脚本python3 .claude/skills/impact-analysis/scripts/parse_diff.py diff文件配置好之后我在 Claude Code 里直接开始验证# 进入项目目录 cd ~/work/ecommerce-backend # 启动 Claude Code claude然后在对话中输入帮我分析一下 main...HEAD 的变更影响范围Claude 的表现是先读取 CLAUDE.md了解项目背景然后识别到“变更影响范围”这个任务命中了impact-analysis技能自动加载 SKILL.md按步骤执行git diff生成 diff 文件调用parse_diff.py解析最后基于解析结果生成一份结构完整的impact_report_20250601.md。整个过程中我唯一做的事情就是输入了一句需求。模型自主完成了任务识别、技能加载、命令执行、脚本调用、报告生成。这就是 Claude Skills 构建 Agent 的完整闭环。4. 常见问题与排查技巧实录搭好第一版之后我开始在不同项目里复用这套方案期间踩过的坑不少。这里挑几个出现频率最高的问题整理成速查表每一条都是我自己定位和解决的不是理论推测。4.1 问题一技能明明存在Agent 却不调用这个是我见过最多的问题多半出在 SKILL.md 的description字段上。Claude 判断是否使用技能几乎完全依赖这个字段的语义匹配度。如果你的 description 写的是“用于分析代码变更”模型在面对“帮我看看这个改动有没有问题”时大概率会漏选这个技能为什么因为“看看有没有问题”和“分析变更影响范围”在语义上不是强关联。我测试出来的有效做法是在 description 里把常见的口语化触发词都列出来。比如“审查代码改动、评估 merge request 风险、说明这次改动的后果、列出需要重点测试的地方”。这些同义表达越多模型精准命中的概率越高。写完 description 之后建议用不同问法各试五次出现两次以上漏触发就需要补充触发词。4.2 问题二技能脚本权限不足或路径找不到如果你的技能脚本是 Python 或 shellClaude Code 调用时偶尔会遇到两种报错permission denied 和 file not found。前者是脚本没有执行权限后者是相对路径出了问题。处理权限问题给脚本加执行权限即可。路径问题则需要注意一个坑SKILL.md 里引用脚本时建议用相对于技能目录的路径并且在执行前先让模型确认当前工作目录。如果你的技能位于项目级目录而 Claude 的执行目录在项目根目录那么scripts/parse_diff.py是有效的。但如果技能位于用户级目录而你在别的项目里调用就要在 SKILL.md 里明确写明绝对路径或调用方式否则模型会懵。我现在的习惯是在 SKILL.md 正文开头加一行“脚本执行路径说明”比如本技能脚本位于技能目录/scripts/parse_diff.py 执行方式python3 技能目录/scripts/parse_diff.py 参数让模型先根据SKILL.md文件位置推导技能目录再拼接脚本路径实测下来路径错误率基本归零。4.3 问题三上下文被技能内容刷爆技能本身的内容会占用上下文如果你的 SKILL.md 写了几千字再加上外部读取的文件上下文很容易告急。尤其是多个技能依次触发时上下文膨胀非常快。我的解决思路是把 SKILL.md 精简到“流程控制”级别详细的规则、规则表、检查清单不要写在 SKILL.md 里而是放到技能目录下的另一个文件比如rules.md或prompts.md并在 SKILL.md 里指示模型“执行到某一步时再去读取这个文件”。这样上下文里永远只有当前需要的详细规则不需要一次性加载全部内容。例如我把“测试建议生成规则”单独放到scripts/test_rule.mdSKILL.md 里只写生成测试建议时先读取 scripts/test_rule.md 中的规则再按规则输出。这样技能加载时的 token 成本降到最低模型执行到这一步才会按需读取详细规则。4.4 问题四模型不按 SKILL.md 的步骤执行有时候模型加载了技能但没有严格按 SKILL.md 里的步骤走而是自己另起炉灶。这个问题通常出在 SKILL.md 的描述语气上。如果你写的是“建议按以下步骤”模型就会觉得这是可选建议如果你写的是“必须按顺序执行以下步骤不得跳过”模型的服从度会高很多。另外还可以在前面提到的 frontmatter 里加一个参数disable-model-invocation: false默认就是 false这个字段的作用是允许模型自主触发技能。如果你希望某个技能只能被显式调用、不能被模型自主触发就设为 true。对于关键的生产流程技能我有时会刻意设为 true并在 CLAUDE.md 里要求“只有明确调用技能时才执行对应工作流”这是一种防止模型乱来的控制手段。5. 实战建议从“能用”到“好用”的经验沉淀这套基于 Claude Skills 的 Agent 方案我已经跑了三个生产项目从最初只能做代码影响分析扩展到了自动化运维巡检、数据库变更评审、文档一致性校验等多个场景。最后分享几条从实战里沉淀下来的建议帮助你少走弯路。5.1 技能边界划分一个技能只做一件事技能设计的核心原则我总结成一句话一个技能只做一件事但把这一件事做到极致。我最初犯过的错误是试图做一个“全栈开发助手技能”结果模型经常不知道是该先写后端还是先写前端加载技能后也不知道该执行哪一步。拆成“后端代码审查”“前端组件分析”“接口文档生成”三个独立技能后每次触发都非常精准输出质量也明显提升。拆分的粒度参考标准是看这个技能的执行步骤是否能在一屏之内读完。如果 SKILL.md 正文超过 80 行大概率是塞了太多职责建议继续拆分。小的技能块还有一个优势就是可以自由组合。比如我做自动化运维巡检时会把“日志分析”和“资源监控”拆成两个技能当需要排查性能问题时让它们依次触发两段分析结果拼在一起就是一份完整诊断报告。5.2 技能脚本的可靠性与可测试性只要技能里包含脚本就要把脚本当作正式的代码来对待。我的要求有三条必须能独立运行、必须有输入校验、必须有清晰的输出格式。独立运行意味着不依赖 Claude Code 环境。我会先在终端里手动执行一遍python3 scripts/parse_diff.py /tmp/test.diff确认输出符合预期然后再放进技能里。输入校验主要是防止模型传了错误参数导致脚本崩溃。比如 parse_diff.py 里就判断了文件是否存在参数是否传全。输出格式上脚本输出的每一行都要设计成容易解析的形态我用的是“前缀 内容”的结构比如文件:、变更点:这样模型读取后能够准确提取信息不会在解析输出上浪费 token。5.3 用版本管理来管理技能本身最后一个小建议把技能目录当作一个独立项目来做版本管理。我现在会把所有自研技能放在一个claude-skills仓库里每次修改都会记录变更原因。收益是什么呢我给你讲一个真实场景某天我发现代码审查技能突然变得“特别严格”每个 PR 都给出大量警告仔细对比才发现是上周往 SKILL.md 里加了一条“发现潜在性能问题必须警告”的规则结果模型把所有循环遍历都当成了性能风险。因为技能有 Git 历史我一行git revert就恢复了正常整个过程不到一分钟。仓库共享也给团队协作带来很大便利。我建了一个内部的技能索引文档列清楚每个技能的名称、用途、适用场景、维护人。新同事接手时不再需要翻聊天记录找“当时是怎么配置的”直接拉仓库、看 README、试用技能就能上手。把 Agent 开发从“个人魔法”变成“团队工程能力”这才是 Claude Skills 真正让我兴奋的地方。