恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
Agent Skills 实战:从设计、开发到测试的完整指南
首页
资讯中心
/
Agent Skills 实战:从设计、开发到测试的完整指南
Agent Skills 实战:从设计、开发到测试的完整指南
发布时间:2026/10/7 12:04:50
1. 从“skills”这个热词说起它到底在解决什么问题最近半年不管是在技术社区、开发者群聊还是各类项目讨论区“skills”这个词出现的频率高得离谱。有人把它当成一种新的能力封装方式有人拿它来给智能体做“技能包”还有人直接把它当作项目模块化的代名词。但如果你只是把它理解成“技能”两个字那就太表面了。我接触过的几个实际项目里skills 已经变成了一种介于“函数库”和“工作流编排”之间的中间层——它既不是纯粹的代码复用也不是简单的配置管理而是把某个具体场景下的完整操作逻辑打包成一个可被调用、可被组合、可被测试的独立单元。这个思路其实很符合当下智能体应用开发的真实需求。以前我们做一个自动化流程往往是把一堆 API 调用、条件判断、异常处理全部塞进一个大函数里改一处就要动全身。而 skills 的做法是把每个独立能力拆出来比如“读取表格并清洗数据”是一个 skill“根据关键词检索文档”是另一个 skill“把结果整理成固定格式输出”又是一个 skill。每个 skill 有自己的输入输出定义、有自己的依赖声明、有自己的测试用例。这样带来的好处非常直接调试的时候可以单独跑某个 skill复用的時候可以直接引用组合的时候只需要关心 skill 之间的数据流。从热搜词也能看出来大家关心的方向集中在几个点上Agent Skills 怎么测试、怎么开发、怎么安装、有哪些好用的推荐、国内怎么获取官方市场的内容。这说明 skills 已经过了概念普及期进入了实操落地阶段。我写这篇东西的目的就是把我在实际项目里折腾 skills 的经验整理出来包括整体设计思路、核心细节、实操步骤、常见坑和排查方法。不管你是刚听说这个词还是已经动手在写自己的 skill应该都能找到能直接抄作业的部分。2. 内容整体设计与思路拆解2.1 为什么要把能力拆成 skill 而不是写成一个函数我最早接触类似概念是在做 GKE 上的自动化运维脚本时。当时的需求很简单每天定时检查集群里所有节点的资源使用情况超过阈值就发通知同时把异常节点记录下来。一开始我写了一个两百多行的 Python 脚本里面混杂了 kubectl 调用、数据解析、阈值判断、消息推送、日志写入。跑了两周之后问题来了阈值判断的逻辑需要调整但我改完之后发现消息推送的格式也跟着变了因为两个部分的代码耦合在一起变量互相引用。更麻烦的是我想单独测试“阈值判断”这个逻辑必须把整个脚本跑起来构造完整的集群环境。后来我把这个脚本拆成了四个独立的 skillfetch_node_metrics、evaluate_threshold、format_alert_message、send_notification。每个 skill 只做一件事输入输出用明确的 JSON schema 定义。拆完之后测试evaluate_threshold只需要给它一组模拟的 metrics 数据完全不需要连集群。调整阈值逻辑也不会影响消息格式。这就是 skills 思路最核心的价值把变化的部分隔离出来让每个单元可以独立演进。从架构层面看这种拆分方式还带来了一个额外的好处组合的灵活性。以前我想把“节点检查”改成“Pod 检查”需要改脚本里的好几处。现在只需要换掉fetch_node_metrics这个 skill换成fetch_pod_metrics后面的阈值判断和消息推送完全不用动。这种可替换性在智能体场景下尤其重要因为智能体需要根据不同的任务动态选择不同的 skill 组合。2.2 skill 的边界怎么划多细才算合适这是我在实际项目里踩过最多的坑。一开始我拆得太细把“读取文件”和“解析 JSON”拆成两个 skill结果组合的时候发现每个 skill 之间的数据传递成本比 skill 本身的逻辑还高。后来我又试过拆得太粗把“读取文件、解析、过滤、排序、输出”全部塞进一个 skill结果又回到了耦合的老路。经过几个项目的迭代我总结出一个比较实用的判断标准一个 skill 应该对应一个“有意义的业务动作”。什么叫有意义的业务动作就是当你向别人描述这个流程的时候会自然地说出“然后我们做一步 XXX”的那个 XXX。比如“然后我们根据关键词搜索文档”“然后我们把结果按时间排序”“然后我们生成摘要”。这些就是合适的 skill 粒度。而“然后我们把字符串转成小写”这种就不应该单独成为一个 skill它应该是某个 skill 内部的实现细节。另一个判断维度是复用频率。如果一个能力在三个以上的流程里都会用到那它就值得被拆成独立 skill。如果只是某个特定流程里用一次那放在那个流程的 skill 内部就好。我在做 Genkit 相关的项目时就按照这个原则把“调用大模型生成结构化输出”拆成了一个通用 skill因为几乎每个流程都需要它而且输入输出的格式要求是一致的。2.3 技术选型为什么我最终选择了声明式定义加运行时解析skills 的实现方式有很多种。最简单的是直接写函数用命名约定来标识哪些是 skill。稍微复杂一点的是用装饰器或者注解来标记。我试过这两种方式最后选择了声明式定义加运行时解析的方案。具体来说每个 skill 用一个独立的配置文件YAML 或者 JSON来描述它的元信息名称、描述、输入参数 schema、输出 schema、依赖项、执行入口。运行时根据这些配置来加载和调用 skill。这么选的原因有三个。第一配置和实现分离。skill 的实现可以用任何语言写只要符合入口约定就行。这对于混合技术栈的项目特别友好我可以用 Python 写数据处理 skill用 Node.js 写消息推送 skill用 Shell 写系统检查 skill它们之间通过统一的配置来描述和组合。第二便于自动化测试。因为每个 skill 的输入输出都有 schema 定义我可以自动生成测试用例也可以自动校验实际输出是否符合预期。第三方便动态发现和组合。运行时可以扫描配置目录自动加载所有可用的 skill智能体或者编排引擎可以根据任务需求动态选择合适的 skill 组合。当然这个方案也有代价需要额外维护配置文件而且配置和实现之间可能出现不一致。我的应对方法是加一个启动时的校验步骤检查每个配置声明的入口文件是否存在、输入输出 schema 是否合法、依赖项是否都能解析到。这个校验步骤帮我省了很多调试时间。3. 核心细节解析与实操要点3.1 skill 的元信息应该包含哪些字段一个完整的 skill 定义我通常会包含以下字段。这些字段不是拍脑袋想的而是在实际使用中逐步补充进来的每一个都对应着具体的需求场景。字段名类型是否必填说明namestring是skill 的唯一标识建议用蛇形命名如fetch_node_metricsversionstring是语义化版本号便于依赖管理和灰度升级descriptionstring是一句话说明这个 skill 做什么会展示给编排引擎和用户input_schemaobject是输入参数的 JSON Schema 定义用于校验和文档生成output_schemaobject是输出结果的 JSON Schema 定义entrypointstring是执行入口如python:skills/fetch_metrics.py:rundependenciesarray否依赖的其他 skill 名称列表timeoutnumber否超时时间秒默认 30retry_policyobject否重试策略包括最大重试次数和退避方式tagsarray否标签用于分类和检索这里重点说几个容易忽略的字段。version字段看起来简单但在多团队协作时非常关键。我曾经遇到过因为某个 skill 升级后输出格式变了导致依赖它的上游流程全部报错的情况。后来强制要求所有 skill 必须声明版本并且上游引用时必须指定版本范围才解决了这个问题。retry_policy也是实际跑起来之后才加的因为网络调用类的 skill 偶尔会因为瞬时故障失败没有重试机制的话整个流程就断了。3.2 输入输出 schema 的设计原则schema 设计直接决定了 skill 好不好用。我遵循的原则是输入尽量宽松输出尽量严格。输入宽松的意思是对于可选参数给默认值对于类型允许合理的自动转换比如字符串数字自动转成数字。输出严格的意思是返回的字段名、类型、结构必须完全符合 schema不能多也不能少。为什么这么设计因为输入是调用方给的调用方可能来自不同的上下文格式不完全一致是常态。如果输入校验太严格调用方需要做很多适配工作反而降低了 skill 的复用性。而输出是 skill 给下游用的下游可能直接拿去做进一步处理如果格式不稳定下游就要写很多防御性代码。我在做文档检索 skill 的时候一开始输出里包含了原始文档的完整内容后来发现下游只需要摘要和引用位置完整内容反而增加了传输和解析成本。于是我把输出 schema 改成只包含summary、source、score三个字段下游的使用体验立刻好了很多。还有一个细节错误输出也要定义 schema。很多人在设计 skill 的时候只考虑成功情况结果出错时返回一个字符串或者直接抛异常下游处理起来很麻烦。我的做法是统一错误输出格式包含error_code、error_message、details三个字段。这样下游可以根据error_code做不同的处理而不是去解析错误字符串。3.3 依赖管理skill 之间怎么引用才不乱skill 之间的依赖关系是最容易失控的地方。我见过一个项目skill 的依赖图深达七层改一个底层 skill 要评估对几十个上游的影响。为了避免这种情况我给自己定了两条规矩。第一条依赖深度不超过三层。也就是说一个 skill 可以依赖另一个 skill那个 skill 可以再依赖一个但不能再往下。如果发现需要更深的依赖说明粒度划分有问题应该把中间层合并或者重新拆分。这条规矩逼着我在设计阶段就想清楚 skill 的层次结构而不是等到依赖图乱成一团再重构。第二条禁止循环依赖。这个听起来是废话但在实际项目里真的会出现。比如 skill A 调用 skill B 做数据清洗skill B 在某些情况下又调用 skill A 做格式转换。这种循环依赖在运行时会导致死循环或者栈溢出。我的做法是在加载阶段就做拓扑排序如果检测到环就直接报错不允许启动。依赖声明的方式我推荐用名称加版本范围比如fetch_node_metrics^1.2.0。这样在升级依赖时可以有控制地推进而不是被动地跟着最新版走。对于关键依赖我还会在 CI 流程里加一步集成测试确保升级后上下游能正常协作。4. 实操过程与核心环节实现4.1 从零开始定义一个 skill完整示例下面我以一个实际项目里的 skill 为例展示从定义到实现到测试的完整过程。这个 skill 的功能是“根据关键词在文档库中检索相关段落”。选择这个例子是因为它涉及外部调用、数据处理、结果排序等多个环节比较有代表性。首先创建 skill 的配置文件skills/doc_search/skill.yamlname: doc_search version: 1.0.0 description: 根据关键词在文档库中检索相关段落返回按相关度排序的结果 input_schema: type: object properties: query: type: string description: 检索关键词 top_k: type: integer default: 5 minimum: 1 maximum: 20 min_score: type: number default: 0.5 minimum: 0 maximum: 1 required: - query output_schema: type: object properties: results: type: array items: type: object properties: content: type: string source: type: string score: type: number total_found: type: integer required: - results - total_found entrypoint: python:skills/doc_search/main.py:run timeout: 15 retry_policy: max_retries: 2 backoff: exponential tags: - retrieval - nlp这个配置里input_schema定义了三个参数其中query是必填的top_k和min_score有默认值。output_schema定义了返回结构results是一个数组每个元素包含内容、来源和分数。entrypoint指向 Python 文件的run函数。retry_policy设置了最多重试两次退避方式为指数退避。接下来实现main.pyimport json from typing import Dict, Any def run(inputs: Dict[str, Any]) - Dict[str, Any]: query inputs[query] top_k inputs.get(top_k, 5) min_score inputs.get(min_score, 0.5) # 调用检索服务获取原始结果 raw_results _call_search_service(query, top_k * 2) # 过滤低分结果并截断 filtered [r for r in raw_results if r[score] min_score] final filtered[:top_k] return { results: [ { content: r[content], source: r[source], score: round(r[score], 4) } for r in final ], total_found: len(filtered) } def _call_search_service(query: str, limit: int) - list: # 实际项目中这里会调用外部检索接口 # 此处用模拟数据演示 return [ {content: f关于 {query} 的段落一, source: doc1.md, score: 0.92}, {content: f关于 {query} 的段落二, source: doc2.md, score: 0.78}, {content: f关于 {query} 的段落三, source: doc3.md, score: 0.45}, ]这个实现里有一个细节值得注意我调用检索服务时请求了top_k * 2条结果然后在本地过滤和截断。这么做是因为检索服务返回的分数可能和本地阈值标准不完全一致多取一些可以保证过滤后有足够的结果。如果直接请求top_k条过滤掉低分后可能就不够数了。4.2 本地测试与调试怎么单独跑一个 skillskill 开发过程中最常用的操作就是单独测试。我通常会写一个简单的测试脚本读取 skill 配置构造输入调用入口函数然后校验输出是否符合 schema。这个脚本不需要启动整个编排引擎几秒钟就能跑完一轮。import yaml import json import importlib def load_skill(skill_dir): with open(f{skill_dir}/skill.yaml) as f: config yaml.safe_load(f) module_path, func_name config[entrypoint].split(:)[1].rsplit(., 1) module importlib.import_module(module_path.replace(/, .)) func getattr(module, func_name) return config, func def test_skill(skill_dir, inputs): config, func load_skill(skill_dir) result func(inputs) # 这里可以加 schema 校验 print(json.dumps(result, ensure_asciiFalse, indent2)) return result if __name__ __main__: test_skill(skills/doc_search, {query: skills 开发, top_k: 3})跑这个脚本输出会是类似这样的结构{ results: [ {content: 关于 skills 开发 的段落一, source: doc1.md, score: 0.92}, {content: 关于 skills 开发 的段落二, source: doc2.md, score: 0.78} ], total_found: 2 }注意total_found是 2 而不是 3因为第三条的分数 0.45 低于默认阈值 0.5被过滤掉了。这个结果符合预期。4.3 组合多个 skill编排流程的搭建单个 skill 跑通之后下一步就是把它们组合起来完成一个完整任务。我以“检索文档并生成摘要”这个流程为例展示编排配置的写法。name: doc_search_and_summarize version: 1.0.0 description: 检索文档并生成摘要 steps: - id: search skill: doc_search^1.0.0 inputs: query: {{ inputs.keyword }} top_k: 5 - id: summarize skill: text_summarize^1.0.0 inputs: texts: {{ steps.search.results | map(attributecontent) | list }} max_length: 200 depends_on: - search outputs: summary: {{ steps.summarize.summary }} sources: {{ steps.search.results | map(attributesource) | list }}这个编排配置定义了两个步骤先调用doc_search检索然后把检索结果的内容传给text_summarize生成摘要。depends_on声明了步骤之间的依赖关系编排引擎会根据这个关系决定执行顺序。输入输出用模板语法引用{{ inputs.keyword }}表示从流程输入中取keyword字段{{ steps.search.results }}表示取search步骤的输出。这种声明式编排的好处是流程逻辑和 skill 实现完全解耦。我可以随时替换doc_search为另一个检索 skill只要输入输出 schema 兼容就行。也可以调整步骤顺序或者增加新的步骤不需要改任何 skill 的代码。4.4 参数计算与选择超时和重试怎么定超时和重试这两个参数看起来简单但设不好会出大问题。我见过因为超时设得太短导致大量正常请求被中断的也见过因为重试次数太多导致故障时流量翻倍把下游打挂的。我的经验值是超时时间设为该 skill 在正常负载下 P99 耗时的 2 到 3 倍。比如doc_search在正常情况下的 P99 耗时大约是 3 秒那超时设 8 到 10 秒比较合适。设得太短偶发的慢请求会被误杀设得太长真正卡死的请求会占用资源太久。要得到 P99 耗时需要在测试环境或者预发环境跑一段时间的压测收集实际数据。重试策略方面我只对幂等且瞬时故障可恢复的 skill 开启重试。比如网络调用类的 skill 适合重试因为失败往往是瞬时的。而写数据库类的 skill 不适合盲目重试因为可能造成重复写入。重试次数一般设 2 到 3 次退避方式用指数退避比如第一次等 1 秒第二次等 2 秒第三次等 4 秒。这样可以在故障时给下游恢复的时间同时避免重试风暴。5. 常见问题与排查技巧实录5.1 skill 加载失败从报错信息定位问题skill 加载失败是最常见的问题表现是启动时报错或者运行时找不到 skill。我把常见的报错和排查方法整理成了下面这个速查表。报错信息可能原因排查方法Skill not found: xxx配置文件不存在或路径不对检查 skills 目录下是否有对应的 yaml 文件确认名称拼写Invalid schema in skill xxxschema 定义不符合 JSON Schema 规范用在线 JSON Schema 校验工具检查配置Entrypoint not resolvable: xxx入口文件路径错误或函数名不存在确认文件路径相对于项目根目录函数名与代码一致Circular dependency detectedskill 之间存在循环依赖用依赖分析工具画出依赖图找到环并打破Version conflict for skill xxx同一 skill 被引用了不兼容的版本检查所有引用处的版本范围统一到兼容版本我印象最深的一次排查是Entrypoint not resolvable这个错误。配置里写的是python:skills/doc_search/main.py:run但实际文件路径是skills/doc_search/main.py看起来没问题。后来发现是因为项目根目录下有一个同名的skills包Python 导入时优先找到了那个包而不是文件路径。解决办法是在入口解析时加上项目根目录的绝对路径前缀避免歧义。5.2 输出不符合 schema怎么快速定位是哪个字段的问题输出校验失败时报错信息往往只说“output does not match schema”不告诉你具体哪里不对。我的做法是在测试脚本里加一个详细的校验函数逐字段对比。def validate_output(output, schema): errors [] for field, spec in schema.get(properties, {}).items(): if field not in output: if field in schema.get(required, []): errors.append(fMissing required field: {field}) continue value output[field] expected_type spec.get(type) if expected_type string and not isinstance(value, str): errors.append(fField {field}: expected string, got {type(value).__name__}) elif expected_type integer and not isinstance(value, int): errors.append(fField {field}: expected integer, got {type(value).__name__}) elif expected_type number and not isinstance(value, (int, float)): errors.append(fField {field}: expected number, got {type(value).__name__}) elif expected_type array and not isinstance(value, list): errors.append(fField {field}: expected array, got {type(value).__name__}) return errors这个函数会逐字段检查类型和必填项返回具体的错误列表。比通用的 schema 校验器输出更友好定位问题快很多。我把它集成到了 CI 流程里每次提交代码都会自动跑一遍所有 skill 的测试用例输出不符合 schema 的直接报错。5.3 性能问题skill 调用变慢的排查思路skill 组合流程跑得慢可能的原因有很多。我通常按照以下顺序排查。先看是不是某个 skill 本身慢。把每个 skill 的耗时打点记录下来找出耗时最长的那个。如果是外部调用慢考虑加缓存或者换更快的服务。如果是计算逻辑慢看看有没有优化空间比如把 O(n²) 的算法改成 O(n log n)。再看是不是 skill 之间的数据传输慢。如果某个 skill 的输出很大传给下一个 skill 时需要序列化和反序列化这个开销可能比 skill 本身的逻辑还大。解决办法是让 skill 之间传递引用而不是完整数据比如传文档 ID 而不是文档内容下游需要时再根据 ID 去取。最后看是不是编排引擎的调度开销大。如果 skill 数量很多每个 skill 的启动和销毁都有成本。可以考虑把常用的 skill 常驻内存避免频繁加载。我在一个项目里把 skill 的加载方式从“每次调用重新导入”改成“启动时预加载并缓存”整体流程耗时下降了将近 40%。5.4 版本升级导致的上游故障怎么做到平滑过渡skill 升级是不可避免的但升级导致上游故障是可以避免的。我的做法是遵循“先兼容再切换后清理”的三步走策略。第一步新版本 skill 保持对旧版本输入输出的兼容。比如旧版本输出里有一个score字段新版本想改成relevance_score那就两个字段都输出旧字段标记为 deprecated。这样上游不用改代码就能继续工作。第二步通知所有上游调用方给出迁移时间窗口。在窗口期内上游逐步把引用版本从旧版切到新版同时把字段引用从旧字段改成新字段。这个过程可以通过配置中心动态调整不需要重新部署。第三步窗口期结束后移除旧字段和旧版本。这时候所有上游都已经迁移完毕移除不会造成影响。如果发现有上游没迁移就单独沟通必要时延长窗口期。这套流程看起来麻烦但比升级后半夜被叫起来修故障要轻松得多。我在一个多团队协作的项目里推行这套流程之后skill 升级导致的生产故障从每月两三次降到了零。6. 我踩过的坑和总结出的实用技巧6.1 不要过早优化 skill 的粒度刚开始做 skill 拆分的时候我总想着要拆得足够细觉得越细越灵活。结果拆出来一堆只有几行代码的 skill组合的时候光是在配置里写依赖关系就写了几百行而且调试的时候要在十几个 skill 之间跳来跳去效率反而降低了。后来我学乖了先按照最粗的粒度拆跑通之后再根据实际需要逐步细化。大部分情况下一个流程拆成三到五个 skill 就够了不需要更多。6.2 给每个 skill 写一个“最小可运行示例”这个习惯帮我省了很多时间。每个 skill 的目录下放一个example.py或者example.sh里面是最简单的调用示例几行代码就能跑起来。新同事接手项目时不用看文档直接跑示例就知道这个 skill 怎么用。我自己调试的时候也经常用比翻配置文件和源码快得多。6.3 日志要打够但不要打太多skill 的日志是排查问题的关键但日志太多会淹没重要信息。我的做法是每个 skill 至少打三类日志入口参数、出口结果、关键中间状态。入口和出口日志用 INFO 级别中间状态用 DEBUG 级别。生产环境只开 INFO需要排查时动态调到 DEBUG。这样平时不会刷屏出问题时又能拿到足够的信息。6.4 定期做依赖关系可视化skill 多了之后依赖关系会变得复杂。我每个月会跑一次依赖分析脚本把 skill 之间的依赖关系画成图。不需要很漂亮的图用 Graphviz 生成一个简单的有向图就行。看着图很容易发现不合理的地方比如某个 skill 被太多上游依赖说明它承担了太多职责或者某个区域的依赖特别密集说明可以进一步拆分。6.5 测试用例要覆盖边界情况skill 的测试不能只测正常路径。我要求每个 skill 至少覆盖以下场景正常输入、空输入、超长输入、类型错误的输入、依赖服务不可用。这些场景在实际运行中都会遇到提前测过之后线上出问题时心里有底。特别是“依赖服务不可用”这个场景很多人不测结果线上真出问题时发现 skill 直接崩溃而不是优雅降级。6.6 文档要写在 skill 定义里不要单独维护我见过很多项目把 skill 的文档写在单独的 wiki 或者 README 里结果代码改了文档没改文档很快就过时了。我的做法是把文档写在 skill 的description字段和 schema 的description字段里然后用工具自动生成文档页面。这样文档和代码永远同步不会出现不一致的情况。6.7 版本号要严格遵守语义化版本规范major.minor.patch这个规范看起来简单但严格执行的项目不多。我的要求是不兼容的改动必须升 major新增功能升 minor修 bug 升 patch。这样上游在引用的时候可以用^1.2.0表示“兼容 1.x 的最新版”用~1.2.0表示“只接受 1.2.x 的补丁更新”。版本号规范了依赖管理就轻松很多。6.8 给 skill 加一个“健康检查”入口这个技巧是从服务治理那边借鉴过来的。每个 skill 除了正常的执行入口再加一个健康检查入口返回 skill 是否可用、依赖是否就绪、最近一次执行是否成功。编排引擎在调用 skill 之前可以先做健康检查如果 skill 不可用就跳过或者走降级逻辑而不是等到调用失败再处理。这个机制在依赖外部服务的 skill 上特别有用可以避免因为某个外部服务挂了导致整个流程卡死。6.9 用环境变量管理环境相关的配置skill 里经常需要读取一些环境相关的配置比如数据库连接串、API 地址、密钥等。这些不要硬编码在 skill 代码或者配置文件里而是通过环境变量注入。这样同一个 skill 可以在开发、测试、生产环境使用不同的配置不需要改代码。我通常会在 skill 定义里声明需要哪些环境变量启动时检查是否都已设置缺失的话直接报错避免运行时才发现问题。6.10 定期清理不再使用的 skill项目跑久了总会有些 skill 因为业务调整不再被引用。这些“僵尸 skill”如果不清理会占用加载时间、增加维护成本、干扰依赖分析。我每个季度会跑一次引用分析找出最近三个月没有被任何流程引用的 skill确认无用后归档或者删除。清理之前先备份万一后面又需要了可以快速恢复。7. 从 skills 出发的扩展思路skills 这套思路不只适用于智能体或者自动化流程。我在其他场景也尝试过类似的做法效果都不错。比如做前端开发时把常用的 UI 组件封装成独立的 skill每个 skill 包含组件代码、样式、测试用例和使用示例。做数据分析时把数据清洗、特征提取、模型训练、结果评估分别封装成 skill用编排配置串起来。甚至写技术文档时也可以把“查资料”“列大纲”“写初稿”“校对”当成 skill 来管理每个阶段有明确的输入输出。这种思路的核心价值在于把复杂问题分解成可管理的小单元并且让这些小单元可以独立演进和灵活组合。不管具体技术栈是什么这个原则都适用。我现在的习惯是拿到一个新任务时先想“这个任务可以拆成哪几个 skill”而不是直接开始写代码。想清楚拆分方式之后实现和调试都会顺畅很多。如果你刚开始接触 skills我的建议是从一个小流程开始拆成两三个 skill跑通之后再逐步扩展。不要一上来就设计一个大而全的 skill 体系那样很容易陷入过度设计的陷阱。先跑起来再根据实际遇到的问题调整这样成长最快。