文章目录0. Case一个 MySQL Migration数据库的脚本变更修复挂了1. Prompt Engineering手动把问题问清楚Prompt Engineering 的优点但它的问题也很明显2. Context Engineering把项目上下文固化下来AGENTS.mddb/mysql-schema-map.mddb/mysql-migration-rules.mddb/mysql-verification.mddb/mysql-risk-boundaries.md现在 prompt 就变短了它解决了什么3. Loop Engineering让流程持续运行LOOP.mdmysql-loop-state.md三个 Skill 的职责1. mysql-migration-triage2. minimal-mysql-fix3. mysql-verifier强烈建议要跟实施使用的模型不同4. 让整个Loop跑起来的关键mysql-migration-loop.sh5. 一些小建议不要一上来就做完整 Loop第一阶段Prompt Engineering第二阶段Context Engineering第三阶段Loop Engineering L1第四阶段Loop Engineering L26. 三种方法的本质区别7. 最重要的安全红线结论随着近一年 AI 编程工具进步2026月06月又从西方飘出来一个热词——Loop Engineering时不时就蹦出某大佬说我现在已经不用Prompt Engineering全心投入Loop Engineering而身为AI大阅兵的碳基猴子们是不是前脚还在陷在Prompt Engineering和Context Engineering的沼泽里现在又来了个Loop Engineering了一个头两个大那先别大了今天博主就以一个具体且简单的MySQL 数据库的脚本变更修复的案例来讲清楚三者到底有什么区别以及怎么落地。0. Case一个 MySQL Migration数据库的脚本变更修复挂了假设我们有一个 PR要给customers表增加一个字段lifetime_value表示客户历史付费金额。PR里的SQL Migration是-- migrations/20260624_add_customer_lifetime_value.sqlALTERTABLEcustomersADDCOLUMNlifetime_valueDECIMAL(12,2)NOTNULLDEFAULT0;UPDATEcustomers cJOINorders oONo.customer_idc.idSETc.lifetime_valueSUM(o.total_amount)WHEREo.statuspaid;CI报错虽然这个脚本有点弱智但重在说明问题凑合着看吧此处就不就结了ERROR 1111 (HY000): Invalid use of group function问题原因是MySQL不能在UPDATE ... SET里这样直接使用SUM()聚合函数。正确思路是先在子查询里按customer_id聚合再 JOIN 回customers表更新。修复后的SQL应该类似ALTERTABLEcustomersADDCOLUMNlifetime_valueDECIMAL(12,2)NOTNULLDEFAULT0;UPDATEcustomers cLEFTJOIN(SELECTcustomer_id,SUM(total_amount)AStotal_paidFROMordersWHEREstatuspaidGROUPBYcustomer_id)paid_ordersONpaid_orders.customer_idc.idSETc.lifetime_valueIFNULL(paid_orders.total_paid,0);接下来就以这个 case 拿来对比三种AI Engineering工程方法。1. Prompt Engineering手动把问题问清楚最传统的方式是你把 SQL、报错、要求复制给AI或LLM例如你是资深 MySQL 数据库工程师。 请修复下面的 MySQL migration。 要求1. 只做最小改动。2. 不要 DROP。3. 不要 TRUNCATE。4. 不要 DELETE。5. 不要连接生产库。6. 保留 MySQL 语法。7. 输出修复后的 SQL。8. 解释为什么原 SQL 会失败。 错误 ERROR1111(HY000): Invalid use of groupfunction原脚本 ALTER TABLE customers ADD COLUMN lifetime_value DECIMAL(12,2)NOT NULL DEFAULT0;UPDATE customers c JOIN orders o ON o.customer_idc.id SET c.lifetime_valueSUM(o.total_amount)WHERE o.statuspaid;模型大概率会给出一个正确修复ALTERTABLEcustomersADDCOLUMNlifetime_valueDECIMAL(12,2)NOTNULLDEFAULT0;UPDATEcustomers cLEFTJOIN(SELECTcustomer_id,SUM(total_amount)AStotal_paidFROMordersWHEREstatuspaidGROUPBYcustomer_id)paid_ordersONpaid_orders.customer_idc.idSETc.lifetime_valueIFNULL(paid_orders.total_paid,0);然后你自己本地localhost:3306的MySQL实例上进行验证mysql-uroot-p-eDROP DATABASE IF EXISTS app_test;mysql-uroot-p-eCREATE DATABASE app_test;# schema.sql 是你测试库的建表语句# seed.sql 是写入或刷新数据的脚本mysql-uroot-papp_testschema.sql mysql-uroot-papp_testseed.sql mysql-uroot-papp_testmigrations/20260624_add_customer_lifetime_value.sql再跑验证查询SELECTc.id,c.lifetime_value,IFNULL(SUM(CASEWHENo.statuspaidTHENo.total_amountELSE0END),0)ASexpected_ltvFROMcustomers cLEFTJOINorders oONo.customer_idc.idGROUPBYc.id,c.lifetime_valueHAVINGc.lifetime_valueexpected_ltv;期望结果是0 rows恭喜你已经完美的完成了这次任务。Prompt Engineering 的优点简单、快、适合临时问题你遇到一个SQL报错贴给AI或LLM让它解释和修复这没有问题有你这个碳基猴子在看管了着AI或LLM不会给你惹太大的麻烦。但它的问题也很明显Prompt Engineering的问题不是“模型不会回答”而是每次都要靠人手动兜底碳基猴子手动复制上下文碳基猴子手动说明数据库规则碳基猴子手动说明哪些操作危险碳基猴子手动验证 SQL手动判断能不能合并这适合修一个问题不适合长期工程化新鲜劲过完后身为碳基猴子的你肯定会觉得什么事都得找本猴能不能偷个懒于是你就构思出了Context Engineering。2. Context Engineering把项目上下文固化下来Context Engineering不是写一个更漂亮的prompt而是把模型每次需要看的东西整理成稳定文件也就是说不要每次都重新告诉 AI我们用 MySQL 不要用 PostgreSQL 语法 不要 DROP 不要 TRUNCATE 不要连生产库 大表 ALTER 要小心 metadata lock orders.status paid 才算收入这些都应该成为项目上下文说白了就是让AI浸泡在一个有限的泳池里面池子里面的水就是AI能接触到的上下文当然游泳嘛水够就行太大了在海里也容易淹死_上下文也是如此项目可以这样组织就是所谓的框架或者脚手架设计repo/ AGENTS.md db/ mysql-schema-map.md mysql-migration-rules.md mysql-verification.md mysql-risk-boundaries.md migrations/ 20260624_add_customer_lifetime_value.sqlAGENTS.md# Agent Instructions You are working on MySQL migration scripts. Default behavior: - Prefer minimal SQL changes. - Use MySQL syntax only. - Never connect to production databases. - Never use DROP, TRUNCATE, or DELETE unless explicitly approved. - Avoid destructive ALTER statements. - Explain metadata lock risk for large tables. - If a migration may lock a large table, escalate to human review. Before claiming success: - Run migration on a local MySQL test database. - Run verification queries. - Show changed files.db/mysql-schema-map.md# MySQL Schema Map customers: - id BIGINT PRIMARY KEY - email VARCHAR(255) NOT NULL - created_at DATETIME NOT NULL orders: - id BIGINT PRIMARY KEY - customer_id BIGINT NOT NULL - total_amount DECIMAL(12, 2) NOT NULL - status VARCHAR(32) NOT NULL - created_at DATETIME NOT NULL Business meaning: - orders.status paid counts toward customer lifetime value. - pending, canceled, refunded orders do not count.db/mysql-migration-rules.md# MySQL Migration Rules Good: - Use explicit JOINs in UPDATE statements. - For aggregates in UPDATE, use a derived table. - Use IFNULL for nullable aggregate results. - Add indexes before large backfills if needed. - Test migrations against local MySQL. Bad: - DROP TABLE - TRUNCATE TABLE - DELETE without WHERE - UPDATE without clear scope unless it is an intentional backfill - ALTER large tables without lock review - Production database URLs in scripts Important MySQL-specific note: - MySQL DDL statements like ALTER TABLE usually cause implicit commits. - Do not assume BEGIN / COMMIT protects the full migration the same way it might in PostgreSQL.db/mysql-verification.md# MySQL Verification Create test database: mysql -uroot -p -e DROP DATABASE IF EXISTS app_test; mysql -uroot -p -e CREATE DATABASE app_test; Load schema and seed data: mysql -uroot -p app_test schema.sql mysql -uroot -p app_test seed.sql Run migration: mysql -uroot -p app_test migrations/20260624_add_customer_lifetime_value.sql Verify result: SELECT c.id, c.lifetime_value, IFNULL(SUM(CASE WHEN o.status paid THEN o.total_amount ELSE 0 END), 0) AS expected_ltv FROM customers c LEFT JOIN orders o ON o.customer_id c.id GROUP BY c.id, c.lifetime_value HAVING c.lifetime_value expected_ltv; Expected result: 0 rowsdb/mysql-risk-boundaries.md# MySQL Risk Boundaries Escalate to human if: - Script contains DROP. - Script contains TRUNCATE. - Script contains DELETE. - Script changes auth, payments, permissions, user identity, or secrets. - Script alters a very large table. - Script may cause long metadata locks. - Script changes more than one migration file. - Script requires business interpretation not present in schema docs.现在 prompt 就变短了Read AGENTS.md and db/mysql-*.md first. Fix this MySQL migration: migrations/20260624_add_customer_lifetime_value.sql CI error: ERROR 1111 (HY000): Invalid use of group function Make the smallest safe SQL change. Use MySQL syntax only. Do not use DROP, TRUNCATE, DELETE, or production credentials. Run the verification steps from db/mysql-verification.md.这就是Context Engineering的价值不是让模型聪明一点而是让模型每次都在正确上下文里工作。它解决了什么相比Prompt Engineering它解决了几个问题项目规则可以复用 数据库语法不会混淆 业务含义不会每次重讲 验证命令固定 危险边界明确但它还没有解决一个问题谁来持续检查 PR 谁来发现 CI 挂了 谁来决定什么时候重试 谁来记录上次处理到哪里这就是Loop Engineering要解决的事情。3. Loop Engineering让流程持续运行Loop Engineering的核心不是“写一个更复杂的prompt”而是设计一个可以重复运行的工作循环。对于MySQL Migration场景这个loop可以是抽象成定时检查 PR ↓ 找到 labelmysql-migration 的 PR ↓ 读取 CI 错误 ↓ 判断是不是低风险 MySQL migration 错误 ↓ 开独立 worktree ↓ 让 AI 修一个 migration 文件 ↓ 启动本地 MySQL 测试库 ↓ 跑 migration ↓ 跑 verification query ↓ verifier 检查 diff 和风险 ↓ 通过则开 fix branch 或评论 patch ↓ 高风险则交给人这时项目结构会变成repo/ LOOP.md mysql-loop-state.md mysql-loop-run-log.md loop-budget.md db/ mysql-schema-map.md mysql-migration-rules.md mysql-verification.md mysql-risk-boundaries.md .grok/ skills/ mysql-migration-triage/ SKILL.md minimal-mysql-fix/ SKILL.md mysql-verifier/ SKILL.md scripts/ mysql-migration-loop.shLOOP.md# MySQL Migration Loop Pattern: MySQL Migration Babysitter Mode: L2 assisted fix Cadence: every 30 minutes on PRs labeled mysql-migration Auto-merge: disabled Allowed actions: - Read PR metadata - Read CI logs - Check out PR branch in isolated worktree - Modify one migration file - Run migration against local MySQL test database - Open fix branch or comment patch Forbidden actions: - No production database access - No auto-merge - No DROP - No TRUNCATE - No DELETE - No destructive ALTER - No touching auth, payments, permissions, secrets, or infra Human Gates: - destructive SQL - migration touches more than one file - table may be large - possible long metadata lock - missing verification query - third failed attemptmysql-loop-state.md# MySQL Loop State Last run: 2026-06-24 10:30 Europe/Berlin ## PR #217 — add customer lifetime value Status: CI red Label: mysql-migration File: - migrations/20260624_add_customer_lifetime_value.sql Error: - ERROR 1111 (HY000): Invalid use of group function Risk: - Low - One migration file - No DROP / TRUNCATE / DELETE - No production connection Attempts: - 1 / 3 Last action: - Implementer replaced aggregate in UPDATE with derived table. - Verifier confirmed MySQL syntax. - Local migration passed. - Verification query returned 0 rows. Next action: - Comment patch summary on PR.这个文件非常重要。没有stateloop每次运行都会失忆。它可能重复修同一个PR、重复评论、重复尝试甚至无限循环。三个 Skill 的职责Loop里最好把AI角色拆开不要让一个模型自己改、自己审、自己宣布通过不要让一个模型自己改、自己审、自己宣布通过不要让一个模型自己改、自己审、自己宣布通过。1. mysql-migration-triage只负责判断这个 PR 能不能自动处理输出类似{pr:217,classification:fixable,risk:low,reason:Only one MySQL migration file changed and the error is a local aggregate UPDATE issue.,target_file:migrations/20260624_add_customer_lifetime_value.sql}如果看到危险SQL比如DROPTABLEcustomers;就应该输出{classification:escalate,risk:high,reason:Migration contains destructive SQL.}2. minimal-mysql-fix只负责做最小修复只改目标 migration 文件 不重构 不碰生产连接 不 DROP 不 TRUNCATE 不 DELETE它把错误SQLUPDATEcustomers cJOINorders oONo.customer_idc.idSETc.lifetime_valueSUM(o.total_amount)WHEREo.statuspaid;改成UPDATEcustomers cLEFTJOIN(SELECTcustomer_id,SUM(total_amount)AStotal_paidFROMordersWHEREstatuspaidGROUPBYcustomer_id)paid_ordersONpaid_orders.customer_idc.idSETc.lifetime_valueIFNULL(paid_orders.total_paid,0);3. mysql-verifier强烈建议要跟实施使用的模型不同只负责审查不负责修改它必须检查migration 是否能在本地 MySQL 跑通 verification query 是否返回 0 rows 是否只改了目标文件 是否包含 DROP / TRUNCATE / DELETE 是否碰了生产连接 是否可能导致大表长时间 metadata lock这个角色非常关键。很多 AI 自动化失败就是因为让同一个模型自己改 自己测 自己说通过这是不合格的工程设计更严格的做法是模型1如Opus 4.8GLM-5.2负责自实施改动模型2GPT 5.5Deepseek V4负责按要求测试和评估是否能通过当然4. 让整个Loop跑起来的关键mysql-migration-loop.sh下面是一个让整个Loop跑起来的关键shell脚本重点是帮助理解每一步的职责本质是此刻就把自己想象成当年的造物主或上帝就好就看你的智慧是否足以造出你自己的心中的完美世界了当然别胆怯完美的产品都是迭代出来的这个脚本可能也不完美当然也不是人一口气想出来的第5节会细讲迭代逻辑此处就先看一下这个脚本本身仅供学习参考#!/usr/bin/env bash# 遇到错误就退出# -e: 任意命令失败就停止# -u: 使用未定义变量就报错# -o pipefail: 管道中任何一步失败都算失败set-euopipefail######################################### 0. 基础配置########################################STATE_FILEmysql-loop-state.mdRUN_LOGmysql-loop-run-log.mdPR_LABELmysql-migrationREPO_DIR$(pwd)MYSQL_USER${MYSQL_USER:-root}MYSQL_HOST${MYSQL_HOST:-127.0.0.1}MYSQL_PORT${MYSQL_PORT:-3306}MYSQL_BASE_CMD(mysql-h$MYSQL_HOST-P$MYSQL_PORT-u$MYSQL_USER)echo## Run$(date-Iseconds)$RUN_LOG######################################### 1. 找到需要处理的 PR########################################PRS$(ghprlist\--label$PR_LABEL\--stateopen\--jsonnumber,title,headRefName,files,statusCheckRollup)if[$PRS[]];thenecho- No PRs with label$PR_LABEL. Exit.$RUN_LOGexit0fiecho$PRS.loop-mysql-prs.json######################################### 2. 让 triage agent 判断能不能自动处理########################################agent run mysql-migration-triage\--input.loop-mysql-prs.json\--state$STATE_FILE\--output.loop-mysql-triage.json######################################### 3. 读取 triage 结果########################################CLASSIFICATION$(jq-r.[0].classification.loop-mysql-triage.json)PR_NUMBER$(jq-r.[0].pr.loop-mysql-triage.json)TARGET_FILE$(jq-r.[0].target_file.loop-mysql-triage.json)######################################### 4. 没事可做就退出########################################if[$CLASSIFICATIONnoop];thenecho- PR #$PR_NUMBERnoop.$RUN_LOGexit0fi######################################### 5. 风险高就交给人########################################if[$CLASSIFICATIONescalate];thenghprcomment$PR_NUMBER\--bodyMySQL Loop: human review required. See$STATE_FILE.echo- PR #$PR_NUMBERescalated.$RUN_LOGexit0fi######################################### 6. 低风险拉取 PR 分支到独立 worktree########################################BRANCH$(ghprview$PR_NUMBER\--jsonheadRefName\--jq.headRefName)WORKTREE../mysql-loop-pr-$PR_NUMBERgitfetch origin$BRANCHgitworktreeadd$WORKTREEorigin/$BRANCHpushd$WORKTREE######################################### 7. 让 AI 做最小 SQL 修复########################################agent run minimal-mysql-fix\--target$TARGET_FILE\--state$REPO_DIR/$STATE_FILE\--context$REPO_DIR/db\--output.loop-mysql-fix.json######################################### 8. 创建本地 MySQL 测试库########################################DB_NAMEapp_test_pr_$PR_NUMBER${MYSQL_BASE_CMD[]}-eDROP DATABASE IF EXISTS${DB_NAME};${MYSQL_BASE_CMD[]}-eCREATE DATABASE${DB_NAME};######################################### 9. 加载 schema、seed、migration########################################${MYSQL_BASE_CMD[]}$DB_NAMEschema.sql${MYSQL_BASE_CMD[]}$DB_NAMEseed.sql${MYSQL_BASE_CMD[]}$DB_NAME$TARGET_FILE######################################### 10. 跑业务验证查询########################################${MYSQL_BASE_CMD[]}$DB_NAME--batch--raw-e SELECT c.id, c.lifetime_value, IFNULL(SUM(CASE WHEN o.status paid THEN o.total_amount ELSE 0 END), 0) AS expected_ltv FROM customers c LEFT JOIN orders o ON o.customer_id c.id GROUP BY c.id, c.lifetime_value HAVING c.lifetime_value expected_ltv; .loop-mysql-verify-result.txt######################################### 11. 让 verifier 独立检查########################################agent run mysql-verifier\--diff$(gitdiff)\--verify-result .loop-mysql-verify-result.txt\--output.loop-mysql-verifier.jsonVERDICT$(jq-r.verdict.loop-mysql-verifier.json)######################################### 12. 通过则推一个修复分支########################################if[$VERDICTpass];thengitcheckout-bloop/mysql-pr-$PR_NUMBER-fixgitadd$TARGET_FILEgitcommit-mfix: repair MySQL migration for PR #$PR_NUMBERgitpush originloop/mysql-pr-$PR_NUMBER-fixghprcomment$PR_NUMBER\--bodyMySQL Loop: proposed fix branch loop/mysql-pr-$PR_NUMBER-fix. Migration passed locally and verification query returned no mismatches.elseghprcomment$PR_NUMBER\--bodyMySQL Loop: attempted fix failed verifier. Human review required.fi######################################### 13. 清理测试库########################################${MYSQL_BASE_CMD[]}-eDROP DATABASE IF EXISTS${DB_NAME};######################################### 14. 回到原目录########################################popd该怎么消化这套所谓的Loop Engineering呢其实没有这么复杂核心和要点就是切记一上来从“脚本很复杂”入手。你应该按责任拆ghprlist# 负责发现任务。triage agent# 负责判断能不能自动处理。gitworktree# 负责隔离环境。minimal mysql fix agent# 负责修改 SQL。mysql 本地测试库# 负责验证 SQL 能不能跑。verification query# 负责验证业务结果对不对最好用不同的modelverifier agent# 负责检查 AI 有没有越界最好用不同的modelgitpush ghprcomment# 负责把结果交给人。根据不同的场景切记一些原则性的控制点如1. 不连生产库2. 不自动 merge3. verifier 必须独立检查其他就都是工程细节了看到这里是不是觉得所谓的Loop Engineering理念和ReAct是惊人的相似核心都是执行后评估根据评估结果决定是否继续操作硬要说这个高维度的架构范式确实很像毕竟大道至简嘛简单的架构范式总是容易殊途同归就好像武学上容易天下武功出少林一个道理但是Loop Engineering这套框架骨骼上填充具体血肉的时候还是有很多自己的技术细节和讲究的这些也是决定了最终你的某个项目的Loop Engineering是否算成功的关键。5. 一些小建议不要一上来就做完整 Loop完整loop看起来很酷但直接上生产其实多半也是找事故永远记住好的产品是快速迭代出来的而不是生来就完美正确落地顺序应该是第一阶段Prompt Engineering先验证AI能不能修这类MySQL错误目标能解释 ERROR 1111 能写出 derived table 修复 能区分 MySQL 和 PostgreSQL 语法第二阶段Context Engineering加上这些文件AGENTS.md db/mysql-schema-map.md db/mysql-migration-rules.md db/mysql-verification.md db/mysql-risk-boundaries.md目标让 AI 每次都知道项目规则、业务语义、验证方法和危险边界第三阶段Loop Engineering L1只做报告不改SQL。检查 PR 读取 CI 判断风险 输出报告 不改文件 不建分支 不 merge第四阶段Loop Engineering L2只允许低风险修复只改一个 migration 文件 只跑本地 MySQL 只开 fix branch 只评论 PR 不自动 merge6. 三种方法的本质区别方法核心问题产物Prompt Engineering我怎么问 AI一个 prompt一次修复Context EngineeringAI 每次应该看到什么项目上下文文件、规则、验证命令Loop Engineering谁让 AI 持续工作、何时停止、如何验证状态文件、技能、脚本、定时循环、verifier对于MySQL migration场景我的建议很明确个人临时修 SQLPrompt Engineering 足够 团队长期维护 SQL必须做 Context Engineering 高频 PR / CI 修复再考虑 Loop Engineering7. 最重要的安全红线SQL场景下AI 最大的风险不是语法错而是写出一个“看起来正确、实际危险”的migration。所以红线必须写死DROP人工审批 TRUNCATE人工审批 DELETE人工审批 生产连接禁止 大表 ALTER人工审批 没有 verification query不准通过 自动 merge禁止尤其是MySQL很多DDL会隐式提交不能天真地以为BEGIN / COMMIT能保护所有migration。结论Prompt Engineering解决的是一次性提问。Context Engineering解决的是稳定输入。Loop Engineering解决的是持续运行、状态管理、验证和人工接管。以MySQL Migration为例真正可落地的路径不是直接做一个“全自动 DBA Agent”而是先让 AI 会修 再让 AI 按项目上下文修 最后才让 AI 在安全边界内循环处理低风险问题把这三层分清楚AI 编程才不会停留在复制粘贴报错给模型的阶段也不会贸然跳到让 AI 自动改库的危险区间也希望通过这个简单的例子方便读者们更好的理解什么是从Prompt Engineering、Context Engineering到Loop Engineering的真正转变。真正成熟的做法是让 AI 做它擅长的低风险重复劳动同时把验证、边界和最终决策权牢牢握在人和系统手里毕竟现阶段还没有公司给硅基的各种Harness/Agent/LLM上过保险理赔真出了产线P0事故还是得碳基猴子背锅当然也不能怕风险就裹足不前毕竟如果游泳时鲨鱼来了你为必要游过鲨鱼嘿嘿游得比别人快也行所以尝试新事物还是建议小步快跑能进能退就好。