AI Coding进阶:用Do Work Skill让AI完整交付任务 之前做内部工具时我花在“把需求讲给 AI 听”上的时间比写代码本身还多。起初用 AI Coding 只是让它补齐某个函数、写个单测感觉效率提升有限。后来调整思路把 AI 当成一个能“接整包活”的协作工程师不光写代码还要搭项目结构、补配置、写文档、跑通验证流程。这个转变让我意识到真正拉开差距的不是某个 AI 工具多聪明而是你有没有一套可复用的“Do Work Skill”方案。这篇文章会围绕“AI Coding 如何从辅助写代码变成真实工程师手里的完整工作流”展开。我会先讲清楚概念再给一套可以直接套用的任务设计方法最后用一个完整的前后端小项目演示整个落地过程并附上高频问题和最佳实践。适合正在把 AI Coding 引入日常开发、但总觉得效果不稳定的读者。1. AI Coding 到底在解决什么问题1.1 从“代码补全”到“任务执行”早期主流的 AI 编码工具本质是“超强补全”。你写一个函数名它帮你补参数你写一行注释它生成一段逻辑。这种模式对简单片段很高效但放到真实项目里远远不够。真实开发中的工作流是创建文件 → 设计接口 → 实现业务逻辑 → 写测试 → 处理异常 → 补充文档 → 提交代码。任何一个环节断了AI 生成的代码都无法直接落地。最近一年AI Coding 工具开始从“补全代码”转向“完成任务”。一些平台推出了项目级生成能力比如 Vercel AI Vibe Coding Platform、GLM Coding Plan 等都尝试让 AI 直接承担一个微型项目的完整交付。行业里也有“数小时内完成过去需要数周的开发工作”的说法。这句话在理想场景下确实能实现但真实项目中仍然需要人来做架构决策、代码审查和安全把控。1.2 什么是 Do Work Skill“Do Work Skill”并不是某个官方专有名词而是一种工程方法把一项可重复的工程任务封装成 AI 能理解、能执行、能自我检查的完整工作单元。这里的“Skill”不是指某种编程语言技巧而是指“让 AI 把一件事从头做到尾”的指令包。一个完整的 Do Work Skill 通常包含四部分任务目标明确告诉 AI 要交付什么。上下文提供技术栈、项目结构、边界约束。执行步骤告诉 AI 先做什么、后做什么。验收标准告诉 AI 如何判断结果是否合格。举个例子普通用法是让 AI“写一个用户注册接口”。Do Work Skill 的用法是让 AI“在现有 FastAPI 项目中新增一个带参数校验、数据库写入、重复用户判断、单元测试和日志记录的用户注册接口并输出可运行的测试命令”。后者明显更接近真实工程需求。1.3 适合用 Do Work Skill 解决的常见场景项目脚手架初始化让 AI 生成统一规范的项目目录、依赖配置、基础启动文件。重复性 CRUD 模块业务系统里大量增删改查接口规格高度相似适合固化技能。单元测试补齐让 AI 阅读现有代码自动生成覆盖核心分支的测试用例。日志与监控配置在 Spring Boot、NestJS 等框架中统一接入日志和健康检查。数据库迁移脚本根据表结构变更生成可回滚的迁移 SQL。代码重构与格式化让 AI 把某段历史代码按团队规范重写并保持行为不变。这些场景有一个共同点规则清晰、产出明确、可验证。这正是 Do Work Skill 最适合发挥价值的地方。1.4 为什么工程师需要重新组织工作流很多团队已经购买了 AI Coding 工具但开发者反馈“生成的代码不敢用”“改来改去还不如自己写”。问题往往出在工作流设计上。当你只是零散地把代码片段丢给 AI它当然只能给你零散的答案。当你把完整的任务、上下文、验收标准一并交给 AI它的输出质量会显著提升。所以掌握 AI Coding 的关键不是学习某个具体工具的快捷键而是学会“把工程师的思考过程转译成 AI 能执行的指令结构”。Do Work Skill 就是这种转译能力的工程化沉淀。2. 环境准备与工具链选型2.1 工具选型思路当前市面上的 AI Coding 工具主要分为三类IDE 插件、CLI 命令行 Agent、云端工程生成平台。IDE 插件适合在编码过程中获得实时建议CLI Agent 适合执行跨文件、跨命令的完整任务云端平台适合快速原型验证和一对一对话式开发。选型时建议看三点是否支持读取本地项目上下文只能粘贴代码的工具效率会打折。是否支持执行命令和自动修复能主动运行测试并修错才是 Agent 级能力。是否方便接入现有 Git 流程AI 生成的代码是否能按分支、按 PR 合入决定团队协作顺畅度。2.2 环境配置建议本文示例不绑定特定 AI 品牌你可以在主流 IDE 插件或 CLI Agent 中任选一种。本地开发环境建议满足以下条件组件建议版本用途Python3.10 或更高后端示例运行Node.js18 或更高前端构建与 CLI 工具Git2.30 或更高版本控制Docker可选隔离环境和部署验证版本需要根据你的项目实际情况调整本文的重点是演示配置思路。可以先检查当前环境python --version node --version git --version2.3 工作目录与项目结构我建议为每个 AI Coding 任务单独建一个 Git 仓库至少包含以下目录my-project/ ├── prompts/ # 存放可复用的任务描述文件 ├── docs/ # 需求说明、设计文档、验收记录 ├── src/ # 源码目录 │ └── task_manager/ ├── tests/ # 自动化测试 └── scripts/ # 验证与构建脚本把任务描述文件化是 Do Work Skill 落地的关键一步。不要只在对话框里临时打字而是把任务卡保存下来方便复用和迭代。2.4 账号、权限与安全边界使用 AI Coding 工具时有几个红线必须提前划清不要把数据库密码、API Key、云厂商密钥直接粘贴到对话里。不要让 AI 拥有生产环境的直接操作权限。让 AI 生成的删除、更新类操作必须经过人工确认。涉及生产数据变更时先在测试环境验证并做好备份。安全边界不是限制效率而是保护工程底线。3. 构建 Do Work Skill 的核心设计3.1 任务描述从模糊需求到可验收描述一条模糊的指令往往得到一份无法验收的代码。比如“帮我写一个任务管理系统”AI 可能生成几百个文件也可能只生成一个 README。更糟糕的是它可能自由发挥出一套你完全不需要的复杂架构。我把任务描述拆成“五个要素”要素说明示例目标最终交付物是什么可运行的轻量任务管理系统输入AI 可使用的材料项目目录、技术栈说明步骤执行顺序先建模型再写 API再写前端约束必须遵守的边界使用 SQLite不引入前端框架验收如何判断完成启动后能增删改查测试通过把五要素写清楚后即使换一个 AI 工具任务也能被较稳定地执行。3.2 少给噪声多给约束AI 在生成代码时只能根据你提供的上下文做判断。如果上下文里塞满无关信息它反而会迷失重点。高效的上下文要满足两个原则够用技术栈、项目结构、关键依赖版本能支撑 AI 完成代码。精简不要贴整段历史代码除非和当前任务直接相关。一个清晰的上下文模板我通常是这么写的项目类型Python Web 服务 框架Flask 3.x 数据库SQLite 代码位置src/task_manager/ 运行命令python app.py 需要遵循使用参数化 SQL 防止注入日期使用 UTC 格式错误返回统一 JSON 结构。3.3 建立验证闭环AI 生成的代码必须经过验证才能进入代码库。我推荐一个“四步闭环”静态检查语法、格式、类型。自动测试单元测试、接口测试。人工 Review重点看安全、边界、业务正确性。合并发布通过后再合入主干分支。下面是一个简单的验证脚本示例#!/usr/bin/env bash # 文件路径scripts/verify.sh set -e echo 语法检查 python -m py_compile app.py echo 冒烟测试 curl -sf http://127.0.0.1:5000/api/tasks echo API is OK调用 AI 完成开发后可以要求它“运行验证脚本并把输出结果贴回来”。这一步能有效减少“看起来能用实际跑不起来”的情况。3.4 将技能沉淀为模板当验证通过后把任务描述、代码结构、验证脚本整理成一份 Skill 文档。这样下次遇到相似任务只需要改少量参数就能复用整套流程。4. 完整实战用 Do Work Skill 生成一个任务管理系统4.1 需求分析为了让示例可快速复现我设计了一个轻量任务管理系统支持创建任务、查看任务列表。支持更新任务状态todo / doing / done。支持删除任务。后端使用 Python Flask数据库使用 SQLite。前端使用原生 HTML JavaScript不引入前端框架。这个系统虽小但覆盖了增删改查、数据库操作、前后端联调和接口规范非常适合演示 Do Work Skill 的完整流程。4.2 创建项目结构task_manager/ ├── app.py ├── requirements.txt ├── templates/ │ └── index.html └── scripts/ └── verify.sh建议在开始之前先把目录创建好并把任务描述写入prompts/task.md再交给 AI Coding 工具执行。4.3 编写核心代码下面是我期望 AI 生成的完整代码。首先是后端# 文件路径task_manager/app.py from datetime import datetime from flask import Flask, request, jsonify, render_template import sqlite3 app Flask(__name__) DB_PATH tasks.db def get_db(): conn sqlite3.connect(DB_PATH) conn.row_factory sqlite3.Row return conn def init_db(): conn get_db() conn.execute( CREATE TABLE IF NOT EXISTS tasks ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, status TEXT NOT NULL DEFAULT todo, created_at TEXT NOT NULL ) ) conn.commit() conn.close() app.route(/) def index(): return render_template(index.html) app.route(/api/tasks, methods[GET]) def list_tasks(): conn get_db() tasks conn.execute(SELECT * FROM tasks ORDER BY id DESC).fetchall() conn.close() return jsonify([dict(row) for row in tasks]) app.route(/api/tasks, methods[POST]) def create_task(): data request.get_json(forceTrue) title data.get(title, ).strip() if not title: return jsonify({error: title is required}), 400 conn get_db() created_at datetime.now().strftime(%Y-%m-%d %H:%M:%S) cur conn.execute( INSERT INTO tasks (title, status, created_at) VALUES (?, ?, ?), (title, todo, created_at), ) conn.commit() task_id cur.lastrowid conn.close() return jsonify({id: task_id, title: title, status: todo, created_at: created_at}), 201 app.route(/api/tasks/int:task_id, methods[PATCH]) def update_task(task_id): data request.get_json(forceTrue) status data.get(status) valid_status {todo, doing, done} if status not in valid_status: return jsonify({error: status must be one of todo/doing/done}), 400 conn get_db() cur conn.execute(UPDATE tasks SET status ? WHERE id ?, (status, task_id)) conn.commit() updated cur.rowcount 0 conn.close() if not updated: return jsonify({error: task not found}), 404 return jsonify({id: task_id, status: status}) app.route(/api/tasks/int:task_id, methods[DELETE]) def delete_task(task_id): conn get_db() cur conn.execute(DELETE FROM tasks WHERE id ?, (task_id,)) conn.commit() deleted cur.rowcount 0 conn.close() if not deleted: return jsonify({error: task not found}), 404 return jsonify({message: deleted}), 200 if __name__ __main__: init_db() app.run(host0.0.0.0, port5000, debugTrue)这段代码有几个值得注意的设计所有 SQL 都使用参数化查询避免拼接字符串造成注入删除接口返回被删除结果或明确错误数据库初始化使用CREATE TABLE IF NOT EXISTS具备幂等性。这几点都应该写进任务卡让 AI 按规范生成。然后是前端页面!-- 文件路径task_manager/templates/index.html -- !DOCTYPE html html langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 title任务管理系统/title style body { font-family: system-ui, sans-serif; max-width: 640px; margin: 40px auto; padding: 0 16px; } .task-item { display: flex; align-items: center; justify-content: space-between; border: 1px solid #eee; border-radius: 6px; padding: 10px 12px; margin-bottom: 8px; } .task-item .status { font-size: 13px; color: #888; } button { cursor: pointer; } /style /head body h1任务管理系统/h1 div input idtitleInput placeholder输入任务名称 stylepadding: 8px; width: 60%; / button onclickaddTask()添加任务/button /div div idtaskList stylemargin-top: 20px;/div script async function loadTasks() { const res await fetch(/api/tasks); const tasks await res.json(); const list document.getElementById(taskList); list.innerHTML ; tasks.forEach(task { const div document.createElement(div); div.className task-item; div.innerHTML span${escapeHtml(task.title)}/span span classstatus${task.status}/span span button onclickchangeStatus(${task.id}, doing)进行中/button button onclickchangeStatus(${task.id}, done)完成/button button onclickdeleteTask(${task.id})删除/button /span ; list.appendChild(div); }); } async function addTask() { const input document.getElementById(titleInput); const title input.value.trim(); if (!title) { alert(任务名称不能为空); return; } await fetch(/api/tasks, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify({ title }) }); input.value ; loadTasks(); } async function changeStatus(id, status) { await fetch(/api/tasks/${id}, { method: PATCH, headers: { Content-Type: application/json }, body: JSON.stringify({ status }) }); loadTasks(); } async function deleteTask(id) { if (!confirm(确定删除该任务)) return; await fetch(/api/tasks/${id}, { method: DELETE }); loadTasks(); } function escapeHtml(text) { const div document.createElement(div); div.textContent text; return div.innerHTML; } loadTasks(); /script /body /html依赖文件# 文件路径task_manager/requirements.txt flask3.0,4.04.4 运行与验证现在安装依赖并启动项目cd task_manager pip install -r requirements.txt python app.py启动后浏览器访问http://127.0.0.1:5000可以看到任务管理页面。也可以通过 curl 验证接口# 查询任务列表 curl http://127.0.0.1:5000/api/tasks # 创建任务 curl -X POST http://127.0.0.1:5000/api/tasks \ -H Content-Type: application/json \ -d {title: 学习 AI Coding} # 更新任务状态 curl -X PATCH http://127.0.0.1:5000/api/tasks/1 \ -H Content-Type: application/json \ -d {status: doing} # 删除任务 curl -X DELETE http://127.0.0.1:5000/api/tasks/1预期结果创建接口返回 201 和任务 JSON更新返回任务状态删除返回{message: deleted}。这里要特别提醒删除操作在实际项目中不可逆建议生产环境改为软删除或至少在操作前进行备份。4.5 让 AI 生成这个系统的任务卡如果要把上述系统交给 AI Coding 工具来生成需要写一份任务卡。下面是一份可以直接粘贴使用的模板请帮我生成一个轻量任务管理系统要求如下 1. 技术栈Python Flask SQLite后端提供 REST API。 2. 功能支持创建任务、查询任务列表、更新任务状态todo/doing/done、删除任务。 3. 前端使用原生 HTML JavaScript 实现单页界面不引入前端框架。 4. 文件结构app.py、templates/index.html、requirements.txt。 5. 运行方式本地安装依赖后执行 python app.py浏览器访问 http://127.0.0.1:5000。 6. 代码规范使用参数化 SQL 防止注入删除接口必须返回明确结果数据库初始化要幂等。 7. 产出物完整代码、运行说明、接口调用示例。把这份任务卡交给 AI Coding Agent 后再结合前面提到的验证闭环你会明显感觉到输出物从“参考代码”变成了“可运行功能”。5. 常见问题与排查思路问题现象常见原因解决思路AI 生成的代码一运行就报错缺少依赖或版本不兼容先检查 requirements.txt 和包安装记录统一依赖后重试Agent 执行到一半中断上下文太长或一次任务过大拆成多个子任务逐个验证后再合并生成的代码不符合技术栈任务描述中没有明确约束在任务卡中写死框架版本和关键依赖数据库表结构不符合预期没有说明表字段和关系在任务卡中给出建表 SQL 或字段定义前端页面样式混乱没有给出 UI 约束补充简单样式规范或参考页面截图AI 修改了不该改的文件没有限定文件范围明确“只能在 src/task_manager/ 下新增文件”等限制遇到报错时不要急着把整段报错原样丢给 AI。更高效的方式是先把报错信息整理成“在哪个步骤、执行了什么命令、看到了什么现象、期望什么结果”然后让 AI 结合代码定位问题。这样排查思路更清晰也不容易把 AI 带到沟里。6. 最佳实践与工程建议6.1 把任务卡当成一等公民任务卡不应该只在聊天窗口里出现一次。我建议在仓库里建立prompts/目录把常用任务整理成 markdown 文件。比如generate_crud.md、fix_test_failure.md、add_api_logging.md。下次遇到类似任务时直接复制改造而不是从零开始描述。这套文件就是团队积累的“技能库”。6.2 代码审查不能省AI 生成代码的速度越快人工审查就越重要。我见过最危险的情况是AI 生成了一个看起来正确的删除接口但因为缺少 WHERE 条件或缺少状态判断导致误删数据。在真实生产环境中删除操作必须经过确认批量更新必须限制影响范围。即使让 AI 写代码架构师和资深开发也要守住质量底线。6.3 用版本控制管理 AI 产出AI 生成代码建议在独立分支上进行不要直接推送到主干。这样方便对比 AI 改动前后差异也方便回滚。提交信息可以标记来自 AI例如feat: 由 AI 生成任务管理模块 - 后端 REST API - 前端单页界面 - 数据库初始化脚本后续代码走查时这种标记能帮助团队快速识别哪些模块需要额外关注。6.4 控制单次任务的粒度不要试图让 AI 一次性完成“完整业务系统”这既难控制质量也难排查问题。更稳妥的方式是控制在 30 分钟到 2 小时能完成的粒度。例如“完成用户模块的注册接口和单元测试”就比“完成整个用户系统”更合理。6.5 记录“哪些 prompt 有效”同一条任务描述在不同工具上的表现可能不同。建议团队维护一份“有效样例”文档记录哪些表达更准确、哪些约束能避免生成烂代码。这类沉淀比个别工具的快捷键更有长期价值。7. 总结与学习路线到这里你应该已经理解了 Do Work Skill 的核心它不是一个神秘概念而是把工程师的复杂工作拆解成 AI 能稳定执行的任务单元。整篇文章从概念、环境、任务设计到完整项目实战和问题排查覆盖了一个真实工程师接触 AI Coding 时最常遇到的关键环节。如果今天只记住一件事我建议从“把最小的重复任务固化成 Skill”开始。挑选一个你在工作中经常做、规则清晰、产出明确的小任务写一份任务卡让 AI 完整跑一遍再根据结果迭代任务卡。过程中你会慢慢掌握如何给 AI 提供上下文、如何设计验收标准、如何卡住质量底线。下一步可以继续学习的方向包括AI Coding Agent 如何接入 CI/CD 流程、如何使用本地模型工具链、如何在团队中建立 AI 代码审查规范以及更深入的工具调用与自动化测试策略。核心仍然是那句话AI 写代码只是起点把一件事从开始做到可验收才是真实工程师的价值所在。