我最早用大模型写代码的方式很蠢。遇到一个不熟悉的函数,把整个文件复制到网页聊天框,注明“帮我改这里”,等它吐出几百行代码,再复制回来,手动定位差异,经常粘错位置。更麻烦的是,模型只看到你贴给它的那一段,看不到项目的目录结构、依赖关系、其他模块的调用方式,所以它给你的代码经常和现有代码“打架”——要么变量名不一致,要么引用了不存在的函数,要么风格跟整个项目脱节。这条工作流的核心痛点恰恰在这里:聊天式 AI 的上下文被截断,而编码这件事强烈依赖完整的项目上下文。
后来我接触到 Cursor,第一反应是“这不就是个套壳编辑器吗”。真正用下来才发现,它的核心价值不在“编辑器”,而在“让模型看到你的整个代码库”。你再也不用复制粘贴了,模型可以直接读取文件树、检索关键词、查看某个符号的定义和引用,甚至跨多个文件同时修改。这种模式我称它为“代理式编程”:
- 聊天式编程:你提供上下文,模型给你代码片段,你再自己集成。
- 代理式编程:你给模型一个任务和项目访问权,模型自己读代码、自己改、自己跑测试,最后交给你验证。
从聊天式到代理式,差的不是一点半点,而是整个工作的组织方式。Cursor 天然支持这种工作流,但要让它稳定、可控、成本可接受,就必须把它和“大模型 API”这条管道搭好。这里的“大模型 API”包括 OpenAI、Anthropic、DeepSeek、通义千问等云端接口,也包括你用 Ollama 在本地起的一个 OpenAI 兼容服务。
这篇文章适合已经会基础 Git 操作、用过任意一种大模型聊天工具的开发者。你不需要懂很深的机器学习知识,但最好对 Python 或 TypeScript 这类主流语言有一定了解。接下来我会从为什么需要工作流讲起,再逐步展开模型选型、实战流程、踩坑记录,以及最后的批量化和团队化扩展。
1. 从聊天式编程到代理式编程:为什么需要一条完整的 AI 编码工作流
1.1 复制粘贴模式的死穴
我见过不少开发者对 AI 编码的第一印象来自网页版 ChatGPT。用法很简单:贴代码、问问题、复制答案、回编辑器粘贴。这套流程在“写一个独立函数”的场景下勉强够用,一旦进入真实项目,问题就全面暴露。
首先是上下文断裂。聊天工具只认识你贴给它的代码片段,不认识你项目的整体结构。你想让 AI 理解“这个函数会被 controller 层调用,数据库模型里有 status 字段,错误码规则是 4xx 开头”,就必须把所有信息塞进提示词里。可提示词越长,越容易出现琐碎错误,尤其是当你手动复制时漏掉某个关键定义。
其次是修改不可追踪。网页聊天框不会给你生成 diff,不会告诉你在哪个文件哪个位置改动。即便是用 GitHub Copilot 一类的插件,很多时候也只是一个“内联建议”,改完就没了,代码风格、依赖冲突、测试覆盖全都要靠人肉再检查一遍。
第三是验证闭环缺失。你让 AI 改完一段代码后,它不会帮你跑测试,不会检查 lint,更不会告诉你它改了哪些相关文件。你得自己写一遍测试命令,然后祈祷它没有引入新的问题。出了问题,又要回到聊天框重新描述一遍,循环往复。
这些痛点的根源在于:聊天式 AI 没有把“代码库”这个最重要的上下文交给模型。而 Cursor 这类工具的出现,正是为了打破这个瓶颈——让模型直接面对项目,而不是面对粘贴板。
1.2 Cursor 的真正价值:让模型看到整个代码库
Cursor 本质上是一个基于 VS Code 的编辑器,但它内置了深度定制的 AI 交互层。很多没用过的人会把它当作“带个聊天框的编辑器”,实际上它最核心的能力是:模型可以主动去读取和检索你的代码库。
具体来说,Cursor 提供了四种交互方式,价值各不相同:
- Tab 补全:适合简单重复的样板代码,效率很高,但能力有限。
- Ctrl+K 编辑:选中代码块,用自然语言指令修改,适合局部重构。
- Composer/Chat 对话:以聊天方式提问,模型回答时给你 diff 建议,适合探索方案、理解代码。
- Agent 模式:模型可以自己搜索代码、读取文件、修改多个文件、执行命令。这是代理式编程的核心。
其中 Agent 模式是我现在最常用的。它改变了任务的交付方式:以前是你给模型“一段代码”,现在是给模型“一个目标”,让它自己在项目里找到需要改的位置,然后动手。比如我让它“把订单模块的所有金额字段从浮点改为 Decimal,并同步修改关联的测试”,它真的会先去搜索哪些文件引用了这些字段,再逐个修改,最后告诉我改了哪些地方,并建议我运行哪些测试。
这就是为什么说工作流比工具本身更重要。Cursor 只是把你和模型之间的“信息通道”打通了,如果你不把项目结构、规则文件、测试方式告诉它,它依然是瞎猜。因此我在后面的章节里会重点讲:怎么搭一套能让 Cursor 稳定发挥的 AI 编码工作流。
1.3 工作流里必须包含的四个环节
根据我这大半年的实践,一条可用的 AI 编码工作流至少要包含四个环节:
- 上下文准备:把项目的编码规范、技术栈、目录结构、关键约束告诉模型(通过 .cursorrules、README、项目文件)。
- 任务拆解:把大功能拆成小任务,每个任务有明确的验收点,让模型一次只干一件事。
- 执行与验证:让模型改代码后,必须让它自己运行测试、静态检查或者至少给出验证方式,而不是“改完就跑”。
- 人工审查:AI 生成的代码必须过一遍人的眼睛,尤其是涉及数据安全、支付、并发、事务的模块。
这套工作流不是一步到位的,需要根据项目和模型的能力不断调优。接下来我会先讲怎么搭底层的 API 接入,再讲实战流程和踩坑经验。
2. 地基搭建:模型选型、API Key 管理与成本控制
2.1 核心模型选型:Claude、GPT 还是本地模型
Cursor 默认会绑定它自己的订阅套餐,比如 Cursor Pro 里包含一定的快速请求额度,但很多人用的是“Bring Your Own Key”(BYOK)模式:在设置里填你自己的大模型 API Key,让 Cursor 直接调用你选择的模型。这样做的好处是灵活,你可以选择更便宜的模型,或者在内部网络里接入私有模型。
先说我个人对模型选择的看法:
| 需求场景 | 推荐模型 | 理由 |
|---|---|---|
| 日常补全、简单重构 | Claude 系列或 GPT 系列的最小可用模型 | 响应快,费用可控 |
| 复杂多文件重构 | Claude 最新版大模型 | 长上下文和跨文件理解强 |
| 涉敏数据、完全离线 | 本地模型(Ollama + Qwen / Llama) | 数据不出内网 |
| 高并发自动化脚本 | DeepSeek / 通义千问等便宜 API | 成本低,批量场景划算 |
不要只看“谁最强”。大模型 API 的选择要综合上下文长度、输出质量、API 价格、限流、延迟。以我的经验,最好的组合是“重活用好模型,轻活用便宜模型”,在 Cursor 里可以配置多个模型,按任务切换。
我在日常项目里的默认组合是:复杂重构和跨文件修改用 Claude 最新模型,因为它对长上下文的把握和代码生成质量要比许多开源模型好很多;简单补全和聊天解释用价格更低的模型,比如 DeepSeek 或本地 Qwen,省下来的费用能积少成多。
2.2 API Key 的管理姿势:环境变量、统一网关与多 Key 轮询
经常有人问:为什么我把 Key 写在 Cursor 设置里还是报 401?大概率是 Key 配错、权限不足或者额度用完了。我建议遵循几个基础原则:
- 不要把 Key 写死在项目代码或 .cursorrules 里。那些文件会被提交到 Git 仓库,一旦仓库泄露,Key 就没了。
- 通过环境变量传递 Key。在 Cursor 中,你可以在启动前 export 环境变量,然后在设置里用
${MY_API_KEY}引用。 - 如果你有多个 Key(比如多个账号或多个供应商),用一个统一的 API 网关管理,比如 one-api、new-api 这类开源项目。它们提供统一的 OpenAI 兼容接口,还能做负载均衡、额度控制和日志审计。
这里给一个 .env 的示例:
ANTHROPIC_API_KEY=sk-ant-xxxx OPENAI_API_KEY=sk-proj-xxxx DEEPSEEK_API_KEY=sk-xxxx LOCAL_MODEL_BASE=http://localhost:11434/v1然后在外层运行 Cursor 时,让环境变量直接注入进程。很多 CI 场景下,环境变量的方式比配置界面更可靠,也更容易切换环境。
如果你在一个团队里,我强烈建议用统一网关管理 Key。这样某个成员误改配置,或者某个账号额度耗尽,都不会影响其他人。网关的日志还能帮你看到每天到底消耗了多少 token、哪些代码文件最烧钱,后面做成本优化就有据可依。
2.3 成本控制:请求量、缓存和模型的性价比博弈
AI 编码看起来只是按 token 计费,但真正跑起来,一个功能迭代能烧掉几百上千次请求。我踩过几个成本坑,分享一些控制手段:
- 优先用缓存。Cursor 的请求会带上项目上下文,如果你反复问同一个问题,或者模型读取同一个文件,可以用缓存命中来降低成本。很多 API 支持 prompt caching,开启后重复前缀按缓存价计费,能省 50% 以上。
- 把任务拆小。一次让模型修改 5 个文件,和分 5 次让它各改 1 个文件,后者的上下文更清晰,虽然请求次数变多,但总 token 更少,结果也更可控。
- 设置月度预算和限流。在 API 控制台设置限额,防止某次测试忘了关循环导致账单爆炸。
- 长文本任务考虑“分块处理”。比如要审查一个 5000 行的大文件,先让模型列出函数清单,再逐段审查,别一把梭。
这些看起来都是细节,但叠加起来,一个月能从“烧掉大几百”降到“几十块”。我现在的主项目大概两万行代码,日常用 Cursor 配合 API,一个月的费用基本控制在 100 元以内,前提是始终优先用便宜模型做补全,只在关键重构时切到高级模型。
3. 实战流程:从空白项目到多文件功能交付
3.1 初始化项目:规则文件、Git 分支和任务拆分
AI 编码不是把需求丢给模型就万事大吉。我在开始一个新项目或新功能时,会先完成三件“准备工作”。
第一件事:写.cursorrules文件。这个文件放在项目根目录,Cursor 会自动读取它作为系统提示词。我的.cursorrules一般包含:
- 技术栈和框架版本(比如 Python 3.12、FastAPI、SQLAlchemy)。
- 项目目录结构和分层规范(api / service / repository / models)。
- 命名约定(变量用 snake_case,类名用 PascalCase,禁止拼音变量名)。
- 禁止事项(不要修改 migrations 目录之外的旧逻辑,不要在 service 层直接操作数据库)。
- 验证命令(运行
pytest tests/test_xxx.py)。
下面是一个简化的示例:
# .cursorrules You are a senior Python developer working on FastAPI project. ## Constraints - Always use SQLAlchemy 2.0 style. - Use `pydantic` for request/response models. - Never modify files under `alembic/versions/` without explicit user request. - Follow existing project directory structure: api/, service/, repository/, models/. - Run `pytest tests/` after major changes.第二件事:创建独立的 Git 分支。AI 改完代码后,即使有错误,你也可以随时 diff、回滚。千万不要让 AI 直接在 main 分支上乱改。
第三件事:把需求拆成一个一个可验收的小任务。我通常会在需求文档里列出:
1. 新增订单查询接口 GET /api/v1/orders/{id} 2. 实现 service 层订单查询逻辑 3. 补充单元测试,覆盖“订单不存在”和“订单属于其他用户”两个用例每个任务尽量控制在 1 小时内能完成并验收。拆得越细,模型越不容易“迷茫”,也越容易在出问题时定位。
3.2 用 Agent 模式实现首个功能:完整操作链路
假设我们要实现一个“返回当前用户订单详情”的接口。我会在 Cursor 的 Agent 面板里输入类似这样的提示词:
请帮我实现订单详情查询接口: 1. 在 api/v1/orders.py 中新增 GET /v1/orders/{order_id} 路由 2. 从请求的 header 中读取 user_id,校验该订单归属当前用户 3. 在 service 层新增 get_order_detail(order_id, user_id) 方法 4. 在 repository 层用 SQLAlchemy 查询订单,并预加载订单项 5. 在 tests/test_orders.py 中补充两个用例:正常查询、越权查询 6. 修改完成后运行 pytest,确保相关测试通过然后开启 Agent 模式,让它自己动手。这里关键的是:不要只给一句话“帮我写订单查询接口”,因为这句话缺了太多上下文。而上面的提示词中,我指定了路由位置、service 层和 repository 层的职责、测试要求,模型就有能力自己读代码、自己找文件,然后动手改。
在 Agent 执行过程中,它会向你展示读改了哪些文件、执行了什么命令。我通常每隔几秒看一眼,发现它跑错方向就马上叫停,重新修正指令。这个“随时打断”的能力,是 Cursor 工作流比纯脚本调用 API 更舒服的地方。
3.3 多文件重构:跨文件改动时如何引导模型
代理式编程最难的部分不是让模型写一个新文件,而是让它改一个被很多地方引用的旧逻辑。比如我要把订单金额字段从 float 改为 Decimal。这种重构涉及模型定义、序列化器、数据库迁移、前端 API 返回值、测试用例,一个文件漏改就全线崩坏。
我的做法是:先把重构目标和范围写清楚,再给模型“探索时间”。
在 CurrencyAmount 相关的所有实体中,把金额字段改为 Decimal 类型: - 先搜索所有 .py 文件中使用 float 表示金额的位置 - 列出文件清单,先不要修改,等我确认 - 确认后再批量修改,并用 pytest 和 mypy 验证让 Agent 先“运行搜索并汇报清单”是一个非常好的控制点。它不会一头扎进去乱改,而是先让你了解影响面。确认后,再让它分两次提交:第一次只改模型层和序列化层,第二次改测试和调用方。这样即使出错,你也可以在 Git 里轻松对比。
如果模型在重构过程中卡住了,我一般会在对话里补充一句:“你可以在项目里搜索amount字段的所有引用,我建议先看 repository/orders.py 的调用方式。”这种提示给模型指了一个方向,但又不至于替它写代码。
3.4 测试与人工 Review:AI 编码的最后一道防线
不管模型多强,我都坚持一条铁律:AI 生成的代码必须经过测试和人工 Review。不是不信任模型,而是模型容易在某些边界条件下产生幻觉,尤其是并发、锁、事务、权限校验这些敏感逻辑。
我在工作流里加了三道检查:
- 自动检查:让模型自己运行
pytest或ruff check,把报错信息反馈回来并修复。 - 差异审计:在 Cursor 的 Diff 视图里,重点审查新增代码中与安全相关的点,比如 SQL 拼接、用户输入校验、越权判断。
- 最小验证:在本地起服务,手动调用新接口,验证返回结构符合预期。
人工审查时我问自己三个问题:这个修改会影响哪些现有功能?有没有过度设计?有没有隐藏的副作用?如果答案不确定,就继续追问模型“你为什么这样写”,让它在对话里解释。很多时候模型一解释,问题就暴露了。
4. 真实项目中的高频坑位:五类问题的排查过程
4.1 上下文超限:模型“失忆”后的连锁反应
Agent 模式默认会携带大量项目上下文,但长对话或超大文件还是会超过模型的上下文窗口。一旦超限,Cursor 通常会提示“context length exceeded”,或者模型突然忘记了你之前约定的规则,开始写不符合项目风格的代码。
遇到这种情况,我建议:
- 开启一个全新的 Composer 对话,把关键规则重新粘贴进去。
- 不要在一个会话里连续让模型改 10 个文件,拆成多个短会话。
- 如果项目文件本身就很大,考虑拆成模块,用
.cursorrules里的@file引用局部文件。
有一次我让 Agent 重构一个包含 8000 行代码的单体文件,做到第 3 步时它突然把另一个无关模块的代码也改了,而且日志里没有任何报错。排查下来就是上下文窗口挤爆后,模型“看到”的文件内容不完整,导致它基于幻觉做修改。从那以后,我遇到超大文件都会先做拆分,或者用“先搜索后汇报”的方式,尽量缩短单次请求的有效上下文。
4.2 API 参数幻觉:模型自信地写错接口
AI 很容易写出看起来正确、但实际不存在的 API。比如它可能把 FastAPI 的Body参数写成Form,把 SQLAlchemy 的session.execute(text())写成session.query,或者记错某个第三方库的函数名。这种事在小模型和本地模型身上特别明显。
应对手段有三个:
- 提示词里明确写“版本和约束”,例如“使用 Python 3.12 + FastAPI 0.115 + SQLAlchemy 2.0,不要引入新依赖”。
- 让模型在改动后跑类型检查和测试,用编译器“打脸”它。
- 在 Agent 模式里要求它“先找项目里已有的同类 API 用法,再仿写”。比如让它参考
repository/user_repository.py的写法去写订单仓库类。
记住,模型写错 API 不可怕,可怕的是它“自信满满”地给了你一个根本不存在的函数,而你刚好没加类型检查,代码直到运行到那一行才崩溃。所以,运行前先跑mypy或pyright,能拦截八成这类问题。
4.3 上下文污染:旧代码干扰新需求
上下文污染指的是,Agent 在读取项目时,把与当前任务无关的旧代码、废弃配置也划进来,结果新代码受到旧风格或旧逻辑的影响。比如你想新加一个 Redis 缓存,但项目里曾经有一套已经废弃的缓存工具类,模型读到了就沿用旧的 API,导致你的新代码一上线就报错。
我惯用的隔离方法:
- 在
.cursorrules里用exclude或直接写明“不要参考 legacy/ 和 deprecated/ 目录下的实现”。 - 对新任务用新对话,不要保留之前的上下文。
- 如果模型总往旧方向走,就在提示词里加一句:“忽略所有旧缓存相关代码,使用
app/cache/client.py中新的接口。”
这类问题很难完全避免,因为你不可能让模型完全不受旧代码影响。但只要你在规则文件里控制了“参考范围”,出错率会大幅下降。
4.4 提示词与 API Key 的安全边界
我见过不少项目把.cursorrules里的提示词写得极其详细,连公司内部架构、数据库连接串、API Key 都写在里面,然后整个仓库被推到公共平台。这是非常危险的。Cursor 的提示词泄露问题曾经上过热搜,尤其当规则文件里包含敏感信息时,等于把后门钥匙交给了全世界。
我给朋友和团队的建议:
- 所有密钥一律走环境变量,不要进规则文件。
.cursorrules里只放技术规范和约束,不放业务敏感细节。- 定期检查仓库里是否有误提交的
.env或.cursorrules文件,用.gitignore排除。 - 如果必须引用内部服务地址,用占位符(比如
https://internal-api.example.com)。
其实不只是 Cursor,任何 AI 编码工具都可能不经意间把上下文中的敏感信息发送给云端模型。所以“什么能写进规则文件”和“什么不能写”,需要在一开始就立好规矩。
4.5 网络波动与连接超时的兜底策略
Cursor 调用大模型 API 走的是标准 HTTPS 请求,网络不稳定会导致请求失败、超时甚至静默中断。我在国内网络环境和企业内网里都遇到过类似问题。我的处理方式不涉及任何非常规手段,只做工程层面的兜底:
- 在 API 网关层配置重试和超时(比如 30 秒超时,最多重试 3 次,指数退避)。
- 重要任务先在本地用脚本验证 API 连通性,再进 Cursor 操作。
- 如果是企业内网,先确认网络策略允许访问目标域名,必要时和运维同学协调出口白名单。
- 避免在弱网环境下跑长文本批量任务,改成小批量多轮次。
重点是不要让“网络错误”白屏。Cursor 一般会把 API 错误信息展示在一个对话框里,这时候要区分 401(Key 错)、429(限流)、503(服务不可用)等状态码,再对症处理。有条件的话,在网关层记录日志,方便回看不稳定的具体服务商。
5. 进阶操作:把工作流扩展到本地模型、批量审查和团队协作
5.1 接入本地大模型 API:Ollama 与兼容接口
本地大模型的价值在于数据不出内网、离线可用、不产生 API 费用。我选择 Ollama 作为本地推理服务,因为它对 OpenAI 兼容接口的支持比较成熟。在 Cursor 里自定义模型时,只要把 Base URL 填成:
http://localhost:11434/v1模型名填入你在 Ollama 里拉取的模型,比如:
ollama run qwen2.5-coder:14b这样 Cursor 就能像调用云端 API 一样调用本地模型。注意,本地模型的编码能力通常弱于云端大模型,所以我一般只把本地模型用在敏感代码的局部补全、简单重构和离线环境下的辅助,而不是默认主力模型。
如果要用本地模型跑批量任务,我会用 OpenAI SDK 写脚本,把 Base URL 指向本地地址:
from openai import OpenAI client = OpenAI( base_url="http://localhost:11434/v1", api_key="ollama", ) response = client.chat.completions.create( model="qwen2.5-coder:14b", messages=[{"role": "user", "content": "Explain this code..."}], temperature=0.2, ) print(response.choices[0].message.content)这样的好处是,你在本地验证过的脚本,以后切到云端 API 时只需要改base_url和api_key,逻辑完全复用。
5.2 用 Python 脚本构建批量代码审查流水线
Cursor 适合交互式编码,但如果你需要批量审查一个旧项目的代码风格、找出潜在 bug,或者统一修改几十个文件的 import 方式,写脚本直接调 API 会更高效。我把这套脚本命名为“批量审查流水线”。
核心思路是:遍历项目文件,过滤掉无需关注的文件(如生成文件、依赖目录),用大模型 API 对每个文件生成审查意见,再把意见写到 Markdown 报告里。
import os import glob from openai import OpenAI client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) EXCLUDE_DIRS = {".git", "node_modules", "dist", "build", "venv"} EXTENSIONS = {".py", ".ts", ".js"} def iter_source_files(root): for path in glob.glob(f"{root}/**/*", recursive=True): if any(ex in path.split(os.sep) for ex in EXCLUDE_DIRS): continue ext = os.path.splitext(path)[1] if ext in EXTENSIONS: yield path def review_file(path): with open(path, "r", encoding="utf-8") as f: content = f.read()[:8000] resp = client.chat.completions.create( model="gpt-4o-mini", messages=[ {"role": "system", "content": "You are a code reviewer. Report only real issues: security, bug, maintainability."}, {"role": "user", "content": f"Review this file:\n```\n{content}\n```"} ], temperature=0.0, ) return resp.choices[0].message.content for f in iter_source_files("src"): print(f"Reviewing {f}...") comment = review_file(f) print(comment[:500])这个脚本运行一次,能快速得到全项目的审查意见。但我要强调,审查结果只能当“参考索引”,不能直接当结论。你需要人工二次确认每一个“疑似问题”,否则一定会被幻觉报告淹没。
5.3 团队标准化:共享规则文件与提示词规范
一个人用 Cursor 很爽,但到了团队里,如果没有统一规范,AI 生成代码的风格会五花八门:有人用单引号,有人用双引号;有人写 service 层,有人直接在路由里写 SQL;有人要求必须加类型注解,有人完全不管。所以团队层面必须做两件事。
第一,把.cursorrules纳入版本库。大家在同一套技术规范下使用 AI,生成的代码风格才能基本一致。你可以把.cursorrules放在项目根目录,并在 Code Review 时把“是否遵守规则”作为一项检查标准。
第二,建立提示词模板库。团队里高频任务都可以固化成模板,比如“新增一个分页查询接口”“修复单元测试”“优化慢查询”。把模板放在一个docs/prompts目录里,新同事直接用模板生成任务描述,质量下限就不会太低。
除此之外,强烈建议团队定期复盘“AI 引发的线上 bug”。我们团队这么做了之后,很快收敛出一份“AI 代码避坑清单”,包含了模型容易犯的十个问题,以及对应的审查要求。这些东西比任何工具都值钱。
我个人在实际使用中最大的体会是:AI 编码工作流不是把代码交给 AI 就完了,它更像是一套“人机协作的工程流程”。你越早想清楚模型边界、规则边界和验证边界,越能把 AI 变成真正的生产力,而不是一个偶尔能写点代码的玩具。如果你正准备搭自己的 Cursor + 大模型 API 工作流,建议从一个小项目开始,先把规则文件写好,再逐步试 Agent 模式的各种操作,最后再加入批量脚本和团队模板。这套流程跑顺之后,回到以前那种复制粘贴的模式,你真的会不想回去。