☰
AI编程助手技能编排工作流:从提示词堆砌到推理框架实战
2026/10/14 5:15:38 网站建设 项目流程

1. 从"提示词堆砌"到"技能编排":这个工作流到底在解决什么

如果你最近半年一直在用 Codex 或者 Claude Code 这类命令行 AI 编程助手,大概率经历过这样一个阶段:一开始觉得它无所不能,写个函数、改个 bug、生成一段测试都很顺手;用着用着就发现,真正复杂的任务——比如"把这个模块重构成三层架构,顺便补上单元测试,再更新一下接口文档"——它就开始飘了。要么漏掉某一步,要么前后不一致,要么在某个环节反复打转。

问题不在于模型不够强,而在于我们给它的"工作方式"太随意了。大多数人用 AI 编程助手的方式,本质上就是"把需求丢进去,看它怎么发挥"。这种方式在简单任务上没问题,但一旦任务涉及多个步骤、多个文件、多个约束条件,就很容易失控。

AI-Infra-Auto-Driven-SKILLS v0.1.5这个项目,核心思路就是给这类 AI 编程助手装上一套"推理框架工作流"。它不是一个插件,也不是一个模型,而是一套技能(SKILLS)编排机制——把复杂任务拆解成可复用、可组合、可验证的技能单元,然后让 AI 按照预设的推理路径去执行。

打个比方:以前你让 AI 干活,就像让一个刚入职的实习生自由发挥,他可能很聪明,但不知道你们团队的规范;现在这套工作流,相当于给这个实习生配了一本"操作手册 + 检查清单 + 交接规范",他依然聪明,但做事有章法了。

这套东西适合谁?三类人最值得关注:一是重度使用 Codex / Claude Code 做日常开发的工程师,尤其是那些任务复杂度已经超出"单轮对话能搞定"范围的;二是在团队里推动 AI 辅助开发规范化的技术负责人,需要一套可复制、可传承的工作方式;三是对 AI Agent 编排、推理框架感兴趣的技术爱好者,想看看"技能化"这条路在实际工程中怎么落地。

v0.1.5 这个版本号本身就说明它还在早期,但方向很明确:把"提示词工程"升级成"技能工程"。下面我会从设计动机、核心机制、实操配置、踩坑经验几个维度,把这套工作流拆开讲清楚。

2. 为什么"技能化"比"长提示词"更适合复杂任务

2.1 长提示词的三条死路

很多人第一反应是:复杂任务嘛,我把提示词写长一点、写细一点不就行了?我一开始也是这么想的,实测下来,长提示词会撞上三堵墙。

第一堵墙是上下文稀释。当你把二十条规则塞进一个系统提示里,模型对每一条规则的注意力是会被摊薄的。你写了"必须写单元测试",它可能记住了;你又写了"必须遵循项目现有的命名规范",它可能就顾此失彼了。规则越多,单条规则的执行率越低,这是注意力机制决定的,不是模型"不听话"。

第二堵墙是无法复用。你为"重构模块 A"写了一大段提示词,下次要重构模块 B,发现大部分内容可以复用,但散落在对话历史里,复制粘贴又容易带上一堆无关上下文。提示词是"一次性"的,而技能应该是"资产化"的。

第三堵墙是无法验证。长提示词执行完,你怎么知道它每一步都做对了?只能靠人肉检查。而技能化的工作流,每个技能单元都可以定义"输入是什么、输出是什么、验收标准是什么",这就为自动化验证留了口子。

2.2 技能单元的三个特征

那什么叫"技能"?在这个工作流里,一个技能单元必须满足三个特征。

边界清晰。一个技能只做一件事。比如"扫描指定目录下所有 Python 文件的函数签名"是一个技能,"根据函数签名生成对应的单元测试骨架"是另一个技能。不要把两件事揉在一起,否则复用性就没了。

接口明确。技能有明确的输入和输出。输入可能是文件路径、代码片段、配置参数;输出可能是结构化数据、修改后的文件、一份报告。接口明确的好处是,技能之间可以像积木一样拼接。

可独立验证。每个技能执行完,能有一个明确的判断标准说"这一步成了"。比如"生成测试骨架"这个技能,验收标准可以是"每个目标函数都有对应的 test 函数,且文件能通过语法检查"。

2.3 推理框架:技能之间的"调度逻辑"

光有技能还不够,技能之间怎么串起来,才是工作流的核心。这就是"推理框架"要解决的问题。

举个实际场景:你要给一个老项目补测试。如果只是丢给 AI"帮我补测试",它可能上来就写,写完你发现它连项目用的测试框架都没搞清楚。而推理框架会强制它按顺序走:先探测项目结构和技术栈,再识别可测试的单元,再评估测试优先级,再逐个生成,最后统一跑一遍验证。

这个顺序不是拍脑袋定的,而是把人类工程师做这件事时的隐性决策过程显性化了。你带过一个新人就知道,你不会让他直接写代码,你会先让他"看一遍项目结构""搞清楚用的什么框架""从最简单的模块开始练手"。推理框架就是把这种带教逻辑固化下来。

提示:推理框架的价值不在于"限制 AI",而在于"把资深工程师的决策路径沉淀成可执行的流程"。你越是把复杂任务交给 AI,越需要这种沉淀。

3. SKILLS 目录结构与技能定义文件的写法

3.1 目录怎么摆:一个能长期维护的结构

这套工作流落地到项目里,第一步是把目录结构定下来。我试过几种摆法,最后稳定下来的结构是这样的:

.ai-skills/ ├── skills/ │ ├── scan-project-structure/ │ │ ├── SKILL.md │ │ └── examples/ │ ├── detect-tech-stack/ │ │ ├── SKILL.md │ │ └── examples/ │ ├── generate-test-skeleton/ │ │ ├── SKILL.md │ │ └── examples/ │ └── verify-changes/ │ ├── SKILL.md │ └── examples/ ├── workflows/ │ ├── add-tests.yaml │ └── refactor-module.yaml └── config.yaml

几个关键点解释一下。skills/下每个子目录是一个独立技能,用动词开头命名,一眼能看出这个技能干什么。每个技能目录里必须有一个SKILL.md,这是技能的定义文件;examples/放几个输入输出的样例,方便 AI 理解预期。

workflows/放的是工作流定义,也就是"哪些技能按什么顺序组合"。用 YAML 写,因为可读性好,也方便程序解析。config.yaml放全局配置,比如默认的模型参数、超时时间、日志级别。

为什么技能和 workflow 要分开?因为技能是可复用的原子,workflow 是场景化的编排。同一个"生成测试骨架"技能,既可以用在"给老项目补测试"的 workflow 里,也可以用在"新功能开发"的 workflow 里。分开之后,改技能不影响 workflow,改 workflow 也不动技能。

3.2 SKILL.md 的骨架:让 AI 一眼看懂要干什么

SKILL.md是整个工作流的核心载体。它的写法直接决定了 AI 能不能正确执行。我踩过不少坑之后,总结出一个比较稳的骨架:

# Skill: generate-test-skeleton ## 目的 为指定 Python 模块中的每个公开函数生成单元测试骨架。 ## 输入 - module_path: 目标模块的文件路径(必填) - framework: 测试框架,可选 pytest / unittest,默认 pytest - output_dir: 测试文件输出目录,默认 tests/ ## 前置条件 - 目标模块文件存在且可读 - 项目已安装所选测试框架 ## 执行步骤 1. 读取 module_path 指向的文件 2. 用 AST 解析出所有顶层函数定义 3. 过滤掉以下划线开头的私有函数 4. 为每个函数生成一个 test_<函数名> 的测试函数 5. 测试函数体内包含:正常输入、边界输入、异常输入三个占位断言 6. 写入 output_dir 下对应的测试文件 ## 输出 - 生成的测试文件路径列表 - 每个文件包含的测试函数数量 ## 验收标准 - 每个公开函数都有对应的测试函数 - 生成的文件能通过语法检查 - 不覆盖已存在的测试文件(除非显式指定 force) ## 注意事项 - 如果函数有类型注解,测试骨架里要保留类型信息 - 如果模块里有类方法,暂时跳过,只处理顶层函数

这个骨架里,"执行步骤"和"验收标准"是最不能省的两块。执行步骤是给 AI 的"操作指南",验收标准是给 AI 的"自检清单"。很多人写技能定义时只写目的和输入,结果 AI 执行起来天马行空,就是因为缺了这两块。

3.3 技能定义的粒度:多细才算合适

粒度是个很微妙的问题。太粗,技能就退化成"提示词",失去复用价值;太细,技能数量爆炸,维护成本高。

我的经验法则是:一个技能的执行步骤控制在 5 到 9 步之间。少于 5 步,说明这个技能可能太简单,不值得单独抽出来;多于 9 步,说明它可能承担了多个职责,应该拆分。

还有一个判断标准:如果一个技能的执行步骤里出现了"然后根据情况选择 A 或 B"这种分支,就要考虑拆成两个技能。因为分支意味着这个技能有多个执行路径,验证起来会很麻烦。把分支逻辑放到 workflow 层去处理,技能本身保持线性。

注意:技能定义不是越详细越好。写得太细,AI 反而容易在细节里迷失,忽略整体目标。关键是"步骤清晰 + 验收明确",中间的具体实现留给 AI 发挥。

4. 推理框架怎么串:workflow 编排与状态传递

4.1 workflow 的 YAML 写法

技能定义好了,接下来是把它们串成 workflow。一个典型的"给老项目补测试"的 workflow 长这样:

name: add-tests description: 为指定模块补充单元测试 version: 0.1.5 steps: - id: scan skill: scan-project-structure input: root: "{{ project_root }}" output: project_structure - id: detect skill: detect-tech-stack input: structure: "{{ scan.project_structure }}" output: tech_stack - id: generate skill: generate-test-skeleton input: module_path: "{{ target_module }}" framework: "{{ detect.tech_stack.test_framework }}" output: generated_files - id: verify skill: verify-changes input: files: "{{ generate.generated_files }}" checks: ["syntax", "coverage_smoke"] output: verify_result on_failure: - log: "步骤 {{ failed_step }} 失败,原因:{{ error }}" - action: stop

这里有几个设计点值得说。每个 step 有独立的 id,方便在后续步骤里引用它的输出。输入用模板变量,{{ scan.project_structure }}表示引用 scan 这一步的输出。输出显式命名,这样下一步能明确知道要接什么。

on_failure定义了失败时的行为。这里我选择"记录日志并停止",而不是"自动重试"。原因是:在补测试这种任务里,如果某一步失败了,往往意味着前置假设不成立(比如项目结构探测失败),盲目重试只会浪费 token。失败时停下来让人看一眼,比自动重试更划算。

4.2 状态传递:为什么不能靠"对话历史"

很多人会想:技能之间传数据,直接让 AI 记住不就行了?反正对话历史都在。这个想法在简单场景下能跑通,但一旦步骤多了就会出问题。

对话历史是线性累积的,而 workflow 的状态是结构化的。当你有 8 个步骤,每步都产生一堆中间数据,对话历史会变得又长又乱,AI 很容易"记混"——把第三步的输出当成第五步的输入。而且对话历史里的信息是自然语言,没法做精确的字段引用。

所以这套工作流强制要求:每一步的输出必须是结构化的,通过显式的变量引用传递。{{ scan.project_structure }}这种写法,本质上是在告诉 AI"去 scan 这一步的输出里,找 project_structure 这个字段"。这样即使对话很长,引用关系也是明确的。

实测下来,这个设计对长流程的稳定性提升非常明显。以前跑 6 步以上的任务,中途"失忆"是常事;改成显式状态传递之后,只要每步的输出格式对,后面基本不会串。

4.3 条件分支与循环:workflow 的进阶玩法

基础 workflow 是线性的,但实际任务经常需要分支和循环。这套框架支持两种进阶结构。

条件分支用when字段:

- id: generate skill: generate-test-skeleton when: "{{ detect.tech_stack.has_tests }} == false" input: module_path: "{{ target_module }}"

意思是:只有当项目当前没有测试时,才执行生成步骤。如果已经有测试了,就跳过,直接进验证。

循环用foreach字段:

- id: generate_all skill: generate-test-skeleton foreach: "{{ scan.project_structure.modules }}" input: module_path: "{{ item.path }}"

这会对扫描出来的每个模块都执行一次生成技能。循环的粒度控制很重要——不要在一个技能内部循环,而要在 workflow 层循环。因为技能内部循环,失败时你不知道是哪个元素出的问题;workflow 层循环,每个元素是独立的一步,失败定位很清晰。

5. 实测中的坑:从"能跑"到"跑得稳"之间隔着什么

5.1 坑一:技能输出格式不稳定

最早的时候,我在SKILL.md里写"输出一个 JSON,包含文件路径列表",结果 AI 有时候输出纯 JSON,有时候输出带解释的 JSON,有时候干脆输出一段自然语言描述。下游步骤解析就崩了。

解决办法是在技能定义里给出输出格式的精确模板,并且要求 AI"只输出这个格式,不要有任何额外文字"。比如:

{ "generated_files": ["path/to/test_a.py", "path/to/test_b.py"], "test_count": 12 }

同时在SKILL.md里加一句:"输出必须是合法的 JSON,不要用 markdown 代码块包裹,不要添加任何解释性文字。" 这一句看起来啰嗦,但实测能显著降低格式漂移。

5.2 坑二:前置条件没检查,后面全白干

有一次跑"补测试"的 workflow,前面几步都过了,到生成步骤才发现项目用的是unittest而不是pytest,生成的骨架全得重来。问题出在detect-tech-stack这个技能没有把"测试框架"作为必检项。

后来我在每个技能的"前置条件"里都加了一条硬性要求:如果某个前置条件不满足,技能必须直接报错退出,而不是"尽力而为"。宁可早失败,也不要带着错误的假设往下跑。因为越往后,返工成本越高。

5.3 坑三:验收标准太模糊,等于没有

"生成的文件能通过语法检查"——这个验收标准看起来明确,但实际执行时,AI 可能只检查了它自己生成的那部分,没检查整个文件。结果文件里原有的代码有语法错误,它也没发现。

验收标准要可执行、可量化。比如改成:"对每个生成的文件,运行python -m py_compile <file>,退出码必须为 0。" 这样 AI 就知道具体要跑什么命令、看什么结果,而不是凭感觉判断。

5.4 坑四:技能之间的"隐式依赖"

workflow 里,generate步骤依赖detect步骤的输出。但如果detect失败了,generate会拿到一个空值,然后生成一堆垃圾。这种"隐式依赖"在流程长了之后特别容易出问题。

我的做法是在 workflow 层显式声明依赖:

- id: generate skill: generate-test-skeleton depends_on: [detect] input: framework: "{{ detect.tech_stack.test_framework }}"

depends_on的作用是:如果detect没成功,generate直接跳过,不会拿着空值硬跑。这样失败链路是清晰的,不会产生"看起来跑了但结果是错的"这种最坑的情况。

6. 把工作流接进 Codex / Claude Code 的实际操作

6.1 接入方式:不是插件,是"上下文注入"

这套工作流本身不是一个需要安装的插件,它的接入方式是把技能定义和 workflow 定义作为上下文注入给 AI 助手。具体来说,有两种常见做法。

第一种是项目级注入。在项目根目录放一个约定好的入口文件(比如.ai-skills/README.md),里面说明"本项目使用 AI-Infra-Auto-Driven-SKILLS 工作流,技能定义在 skills/ 下,workflow 在 workflows/ 下"。每次启动 AI 助手时,让它先读这个文件,建立对工作流的认知。

第二种是任务级注入。当你有一个具体任务要跑时,直接把对应的 workflow 文件和它依赖的技能定义一起喂给 AI。这种方式上下文更聚焦,适合任务边界清晰的场景。

我个人的习惯是两者结合:项目级注入建立"这个项目有工作流"的认知,任务级注入提供"这次具体跑哪个 workflow"的指令。

6.2 一次完整的执行示例

假设你要给一个模块补测试,实际操作流程是这样的。

第一步,告诉 AI:"读取.ai-skills/workflows/add-tests.yaml,按这个 workflow 执行,target_module 设为src/utils/parser.py。"

第二步,AI 会先读 workflow 定义,然后按顺序读取每个步骤引用的技能定义。这时候它已经知道整个流程要干什么了。

第三步,它开始执行scan步骤,扫描项目结构,输出结构化结果。接着执行detect,识别技术栈。然后执行generate,生成测试骨架。最后执行verify,跑验收检查。

第四步,你拿到一份执行报告,包含每步的输出和最终的验收结果。如果某步失败,报告里会明确指出是哪一步、什么原因。

整个过程你只需要下一条指令,剩下的编排由 workflow 负责。这就是"技能化"相比"长提示词"的价值——你把复杂度前置到了技能和 workflow 的定义里,执行时反而简单了。

6.3 怎么判断一个任务值不值得做成 workflow

不是所有任务都值得做成 workflow。我的判断标准是三条:重复频率、步骤数量、失败成本。

如果一个任务你一周要做三次以上,步骤超过 4 步,而且做错了要返工很久,那就值得做成 workflow。反过来,一次性的、两三步就能搞定的、错了也无所谓的任务,直接对话解决就行,没必要上工作流。

这个判断很重要,因为维护 workflow 是有成本的。技能定义要更新,workflow 要适配项目变化,这些都是隐性成本。只有当收益明显大于成本时,才值得投入。

7. 版本演进与后续可以怎么扩展

v0.1.5 这个版本,核心是把"技能定义 + workflow 编排 + 状态传递"这套骨架搭起来了。从版本号看,它还在很早期,但骨架已经能支撑实际使用了。

从我个人使用的体感来看,接下来有几个方向值得关注。一是技能的自动发现与推荐——当项目里积累了几十个技能之后,怎么让 AI 知道"这个任务该用哪几个技能",是个值得解决的问题。二是执行过程的可观测性——现在只能看最终报告,如果能实时看到每步的中间状态,调试会方便很多。三是跨项目的技能共享——有些通用技能(比如"扫描项目结构")其实可以跨项目复用,怎么组织这种共享,是个工程问题。

不过这些都是后话。就当前版本而言,如果你正在用 Codex 或 Claude Code 处理复杂任务,我建议你先从一个最常做的任务开始,把它拆成 3 到 5 个技能,写一份 workflow,跑通一遍。跑通之后你会发现,以前那些"AI 又飘了"的问题,很多其实不是模型的问题,而是我们没给它一套稳定的工作方式。

最后分享一个我自己的小习惯:每次 workflow 跑失败,我都会问自己一个问题——"这次失败,是技能定义的问题,还是 workflow 编排的问题,还是我输入的问题?" 把失败归因清楚,下次改对地方,工作流才会越用越顺。这个习惯比任何工具都重要。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询