从GPT到AI Agent:提示词工程驱动大模型执行力的实战指南
1. 从“会回答”到“会执行”的一步之遥前几天有位朋友跑来问我一个问题他已经把某大模型接到自己的业务里了提示词也写得挺规矩角色设定、输出格式、少样本示例全都有可让这个聊天机器人去帮他查一下库存、算一下补货量、再更新一下内部的进货表它死活做不到最后还是得人工复制粘贴。这事我太熟了。过去一年大家喊的“提示词工程”大多数时候是在解决“如何让模型把话说对”——把答案写得更规范、更像人话、更有条理。但到了真实工作流里光是“把话说对”远远不够。你需要的是一个能拆解任务、按步骤调用系统、并对每一步结果负责的智能体。这就是标题里说的那句“执行力升级”从GPT这类对话模型到能跑通流程的AI Agent中间真正变掉的不是模型的“智商”而是提示词工程的设计方式。OpenCSG在做相关实践时我们最常被问的问题其实就三个任务到底怎么拆工具到底怎么调安全边界到底划在哪这篇博客把这三件事一次讲透送给正在把大模型从“聊天窗”往“干活系统”里搬的人。1.1 大家都在说的“提示词工程”其实分两个时代如果你拆开看提示词工程这两年其实经历了两次完全不同的考卷。第一次考卷是“单向生成”模型接收到一段文字输出一段文字任务边界清晰评价标准是“答得对不对、好不好”。这时候的提示词大量使用角色扮演、语气限制、输出模板本质是在指导一个表达能力很强但没有行动能力的文员写报告。第二次考卷是“多轮执行”模型接收目标自己规划步骤选择合适的工具观察工具返回结果再决定下一步动作。这时候的提示词不再是静止的“台词脚本”而是一份动态的“任务说明书”它要能被同一个主循环反复读取、更新、校验。问题也随之而来——说明书写得太粗模型不知道从哪里下手写得太细又很快烧光上下文额度。很多团队把第一代经验直接搬到第二代结果就是朋友遇到的那种状况模型在“说”的部分表现完美在“做”的部分完全拉胯。1.2 智能体不是一个产品形态而是一种执行逻辑所以要理解从GPT到智能体的升级关键不是“换一个更聪明的模型”而是“换一套执行框架”。GPT时代的提示词工程对象是模型的输出分布——怎么让生成结果落在你想要的区间里。智能体时代的提示词工程对象是“模型工具状态”的闭环——模型负责决策工具负责落地状态负责告诉模型“上一步到底发生了什么”。这个闭环通常包含三个组件记忆让智能体知道上下文和历史规划让智能体把大目标拆成小步骤执行让智能体通过调用外部工具真正改变系统状态。提示词在其中的作用是把这个闭环里的每一步都约束在可控范围内。说到底提示词依然是灵魂只是它的工作方式从“写一篇作文的要求”变成了“指挥一个团队运行的流程文档”。2. GPT的“高分作文”与智能体的“干活逻辑”差在哪你要想清楚一个事GPT本质上是一个“静态知识发生器”。它从训练数据里学到的世界是凝固的——你问它“今天天气怎么样”它能给你写一篇关于天气系统如何运作的千字科普但它不知道窗户外面现在下没下雨。因为训练数据停在某个时间点模型没有实时传感器。这不叫“蠢”这是架构天生的边界。大模型的强项是语言理解、知识检索、逻辑推理、内容生成它的弱项是所有涉及“当前状态”和“物理世界动作”的环节。而智能体要干的事恰恰是补上这两个缺口实时状态的获取以及对外部系统的影响。2.1 静态知识与实时状态之间的断层举个非常具体的例子。让GPT直接回答“我们仓库A类物料的库存还剩多少”它会给你一段“仓库管理需要注意……”的建议这不是它不配合而是它的训练数据里根本没有你们公司的库存表。你可以在提示词里把库存数字写进去但它没法保证数字是最新的更没法在每次变化后自动更新自己。于是你想到了工具调用让模型去查数据库。这个思路完全正确但只是第一步。因为查完之后呢如果库存低于安全阈值模型要不要自动生成采购申请采购申请走哪条审批流审批通过后要不要更新预测模型这一连串动作靠一次“问答”永远答不完。这中间的断层在于模型理解世界的单位是“事实和概念”业务系统运转的单位是“事件和状态变更”。提示词工程要做的就是搭一座桥让模型的理解能力能被拆成一系列事件把“理解”变成“动作”。2.2 模型缺的不是智商是记忆、规划、执行三块拼图所以你看那些跑起来的智能体项目背后几乎都是同一类架构一个规划循环在反复运转。第一步模型根据用户目标生成一个计划。第二步系统按计划选择一个工具模型抽取参数、发起调用。第三步工具执行完返回结果模型观察结果判断计划是否需要调整。第四步循环继续直到目标达成或达到终止条件。这个循环里提示词工程干的活不是“写一段漂亮的话”而是设计三个东西怎么让模型把计划拆得足够可执行怎么让工具列表对模型来说是“可理解、可选择、可调用的”怎么确保这个循环在任何一步出错时都能安全收住。我见过不少团队在产品原型阶段犯同一个错误他们把注意力全放在“选个聪明的模型”上结果模型推理能力强了但工具调用一塌糊涂。因为工具调用不是模型“顺手就会”的它是工程问题是提示词、接口、数据格式、错误处理合在一起的结果。3. 拆分步骤把“目标”翻译成模型能逐步走完的走查单智能体时代的第一课是任务分解。别急着写工具、调接口先把“目标”拆成“步骤”。拆得对不对直接决定后面的稳定程度。这里的拆不是让模型随便想想“先做什么后做什么”而是要拆成一个带依赖关系、可验证、可回滚的任务序列。你可以把它理解成给新人写的SOP不能写“把项目搞定”要写“先读配置、再拉数据、再跑校验、最后出报告每一步的输出是什么卡住了找谁”。3.1 两步拆分法目标树 依赖关系我自己常用的方法分两步。第一步先画目标树把最终目标往下拆直到每个叶节点都能对应一个“动作 可验证结果”。第二步做依赖分析哪些任务必须串行哪些可以并行哪些失败了必须中止整个流程。举个例子目标是“汇总本周各组项目状态并发出周报邮件”。拆开以后大概是拉取各组进度数据 - 汇总成统一格式 - 生成周报正文 - 调用邮件工具发送。这里面拉取数据和生成正文可以并行但生成正文依赖拉取结果发送又依赖生成完成。如果一个环节的数据源挂了你是继续用缓存生成还是直接终止应该提前定义好而不是让模型临场发挥。这种拆分最大的价值是“可观测”。每一步的输入输出都是明确的你可以在任意一步插入检查点确认数据没有跑偏。3.2 什么时候算“拆到位”可验证、可回退、可合并很多新手拆任务容易拆成两个极端。拆太粗一个任务里还是塞了一堆动作模型的规划能力反而成了瓶颈拆太细每一步都调用一次模型Token消耗和延迟双双爆炸。我自己的判断标准有三条可验证这步完成后有一个明确的结构化结果来判断成败可回退这步出错时能回到上一步不影响全局可合并相邻步骤如果能共享同一个数据源且不存在外部副作用就应该合成一步。拿“生成周报”来说“整理各组数据”和“按模板生成文字段落”可以分开但“生成文字段落”和“在本地临时文件里存一份”就没必要分。前者是决策步骤需要模型参与后者是纯机械动作可以直接由代码完成。智能体的每一步未必都要经过大模型能在工程代码里硬编码的就别浪费模型的推理。3.3 与子任务配套的Prompt写法任务拆完之后还要给每个子任务写一段“独立的小提示词”。这段提示词的职责很单一解释这个子任务的目标、输入数据的格式、输出结果的预期结构以及遇到异常情况时怎么办。这跟传统的“一段prompt走天下”完全不同。子任务提示词不需要讲背景故事不需要预设角色只需要说清楚“你手头有什么、你要产出什么、什么情况下算失败”。比如拉取数据那段提示词只需要说明数据接口的路径、鉴权方式、失败重试次数以及返回JSON的写入位置。段落越短越好因为上下文窗口终究有限把最重要的执行信息放在最显眼的位置模型理解的准确率才会高。我见过不少团队把任务拆好了但给每个子任务配的提示词还沿用“你是资深专家”那一套不仅没用还浪费上下文。子任务提示词是“操作指令”不是“角色设定”。4. 工具调用把大模型“对话能力”引到外部系统的工程细节任务拆好了接下来就是让模型真正“使用工具”。工具调用的成熟方案现在很多主流的大模型API基本都支持Function Calling机制。其原理并不复杂你在请求里声明一批“工具”每个工具包含名称、功能描述和参数结构模型根据对话上下文决定“要不要调用某个工具、参数填什么”系统收到调用指令后去执行真实代码再把结果回传给模型。这套机制看似简单但工程细节极其容易翻车尤其是工具描述本身的质量问题。4.1 工具描述本身就是一种提示词很多人没意识到Function Calling里的“工具描述”本质上就是一种提示词。它是模型唯一能用来判断“何时调用、调用哪个、参数怎么填”的依据。如果你把工具描述当成API文档来写全是准确但冷峻的技术术语模型经常会在“该用哪个”上犹豫。比如你给两个工具“查询订单信息”和“查询退款信息”。模型面对用户说“帮我看看我上个月那笔订单”它很可能拿不准该查哪个于是随便选一个结果数据对不上。如果你把描述写成“当用户提到订单、购买记录、物流等场景时使用”模型的选择准确率会高很多。参数结构也一样。每个参数都要写明含义、类型、取值范围、是否必填能加默认值的加默认值。别把参数设计成“让模型猜”模型不是特别擅长猜你的内部字段命名习惯。4.2 一次工具调用的完整生命周期一个标准的工具调用生命周期长这样模型输出一个工具调用请求 - 系统校验请求格式、检查参数合法性 - 系统执行真实工具函数 - 拿到返回结果 - 将结果作为“观察消息”重新塞回对话 - 模型根据结果继续生成下一步。这里最核心的坑在“系统校验”这一步。我建议所有工具调用都先做一次参数白名单校验把不符合schema要求的请求直接拦截而不是贸然执行。因为模型偶尔会生成一些“似是而非”的参数比如日期格式写错、枚举值越界、字符串里混入多余字符。如果直接把这种参数丢给业务接口轻则报错重则写入脏数据。另外工具返回结果也要设计得适合模型阅读。别把数据库原始记录整包丢回去字段一多模型很快晕掉。最好做一次“压平”处理只保留当前任务需要的字段并格式化好枚举值的中文含义让模型一眼能看懂结果意味着什么。4.3 工具调用最容易翻车的三个地方第一个翻车点是工具名和描述里的“歧义”。“获取用户信息”和“获取用户详情”字面上几乎一样模型根本分不清。解决办法是给工具加场景前缀比如“CRM_获取用户核心资料”“订单_查询用户近期订单”让工具名自带分类信息。第二个翻车点是参数冲突。你有一个工具接收“日期范围”比如start_date和end_date模型很可能把两个参数的顺序填反。这时候你可以在参数描述里写清楚“开始日期不能晚于结束日期”并且在系统校验阶段加一个自动校正逻辑发现start_date比end_date晚就自动交换而不是直接报错。第三个翻车点更隐蔽上下文污染。工具调用好几次之后对话历史里塞满了观察结果模型看到后面前面关键信息被冲淡。解决办法是定期压缩历史保留用户核心目标、最近两轮的工具结果以及当前未完成的子任务状态不需要把全部工具返回都堆在提示词里。5. 安全边界执行力越强越要管住“最后一公里”智能体跟聊天机器人的本质区别是它会“动作”。能动作就必然带来风险。你让聊天机器人胡说八道顶多是被用户骂两句你让智能体误删数据、误发邮件、误转账那就是真事故了。所以安全边界的核心原则是在智能体的执行链路上防系统性风险而不是只防单点错误。5.1 最小权限与工具白名单我的第一个建议给智能体开放的工具集永远走“最小权限”原则。能只读的不要给写权限能查当前组织数据的不要给全平台数据查询权限能返回汇总数据的不要给原始库表接口。工具白名单设计同样重要。不要把所有接口一股脑注册成Function而是按场景划分工具包。比如“查询场景”只注册三个只读接口“执行场景”单独注册一个带审批钩子的写接口。模型每次可选的工具范围是有限的这会直接减少误选概率。有一个真实的教训某团队把所有内部系统的接口都注册成了工具包括“删除用户”“修改订单金额”这种高危接口。然后在测试时让智能体去“模拟一次越权访问”模型竟然真的调用了删除接口虽然最后因为环境权限拦截住了但把运维吓出一身冷汗。高危操作必须需要审批不能再靠“模型应该知道不能做”。5.2 操作确认与人工闸门对高影响操作我强烈建议加一个“人工确认闸门”。具体做法是把工具分成两级一级工具模型可以直接调用通常是只读、低风险操作二级工具模型只能“申请调用”调用请求会进入一个待确认队列真实执行要等人工点了确认按钮。这样设计的理由很简单模型对后果的感知是极其有限的。它能推理“删除用户是会伤害用户的行为”但它理解不了“这个用户关联了一百条业务记录、十张工单、五条审批流删了会连锁报错”。人工确认闸门把这个理解成本转移给了更靠谱的人。你可以在产品上做成弹窗形式智能体执行到高危步骤时界面弹出“将执行以下操作发送邮件给张三内容为……”人工点“允许”或“拒绝”。实测下来这个设计不仅降低了事故率还明显提升了用户对智能体的信任感因为用户觉得“它是我的助手不是我失控的代理”。5.3 提示注入与越权指令的防护思路提示注入是智能体特有的安全威胁。攻击者把恶意指令藏在文本里比如商品评论、用户输入、文档内容让模型去执行不该执行的操作。防注入没法百分百做到但可以从三个层面降低风险。第一层是输入侧过滤对进入对话系统的外部文本做大模型安全分类识别明显的恶意指令模式。第二层是工具侧校验就算模型被诱导工具调用层也要校验参数是否越权高危操作必须有二次确认攻击者没法通过“语言引导”绕过工程权限。第三层是结果侧审计所有工具调用留痕谁发起的调用、模型说了什么、返回了什么全部进日志。说白了安全边界不能只依赖模型的“道德判断”要在工程链路上设置硬闸门。语言模型可以被诱导但权限系统和人工审批流不会被一段prompt骗过去。6. 一个最小可复现的“跨系统执行”示例讲了这么多原理上点实战。我选一个最常见的场景让智能体根据邮件内容去系统里查询项目信息再生成一封周报回复并且在最终发送前要人工确认。整个示例尽可能简单但足以覆盖“任务拆解、工具调用、安全边界”三个主题。6.1 场景设定与工具清单假设业务场景是这样的用户给智能体发一段原始邮件文本内容是“请帮我看一下某项目的当前进度整理成进度摘要然后以邮件草稿的形式回复给我”。我给它注册三个工具刚好对应三级安全策略fetch_project_progress(project_id)只读工具查询项目进度供模型直接调用。generate_draft_email(project_id, summary, recipient)写操作生成邮件草稿但不真正发送可供模型直接调用。send_email(draft_id, recipient)高危操作真正发送邮件必须经过人工确认。工具描述我写成下面这样注意描述里的场景引导词[ { name: fetch_project_progress, description: 当用户询问项目进度、交付状态、里程碑完成情况时使用。返回项目各阶段的最新进度、风险点和负责人。, parameters: { project_id: { type: string, description: 项目唯一标识 } } }, { name: generate_draft_email, description: 基于进度数据生成回复客户或内部团队的邮件草稿。不发送仅保存草稿后返回草稿ID。, parameters: { project_id: { type: string, description: 项目标识 }, summary: { type: string, description: 邮件正文的核心摘要 }, recipient: { type: string, description: 收件人邮箱 } } }, { name: send_email, description: 最终发送指定邮件草稿。此操作不可逆执行后邮件将真实发出。, parameters: { draft_id: { type: string, description: 要发送的草稿ID } } } ]注意看工具描述本身把“什么时候该用这个工具”的逻辑写进去了不是干巴巴的接口文档。模型看到“当用户询问项目进度……”就更容易把输入文本匹配到第一个工具。6.2 主循环与安全阀代码示意简化版的主循环逻辑可以写成这样只展示核心过程每行都给了注释def agent_loop(user_input, max_steps6, confirm_funcNone): messages [{role: user, content: user_input}] for step in range(max_steps): # 第一层让模型决定下一步动作传入工具定义 resp llm.call(messages, toolsTOOLS) msg resp.choices[0].message # 模型没有发起工具调用说明任务可能已完成或需要提问 if not msg.tool_calls: return msg.content messages.append(msg.model_dump()) for call in msg.tool_calls: tool_name call.function.name args json.loads(call.function.arguments) # 第二层参数白名单校验 if not validate_tool_params(tool_name, args): messages.append(gen_tool_error(tool_name, 参数校验失败)) continue # 第三层高危操作走人工确认闸门 if tool_name send_email: allow confirm_func(args) if not allow: messages.append(gen_tool_result(操作被用户取消)) continue # 执行真实工具 result exec_tool(tool_name, args) messages.append(gen_tool_result(tool_name, result)) raise RuntimeError(超过最大执行步数)这段代码里的三层机制就是这部博文反复强调的模型负责决定但系统负责校验、拦截和执行。run到“send_email”时refuse允许就是靠confirm_func人工确认否则模型再聪明也不能把邮件发出去。6.3 实测验证与常见失败模式我把这个Demo跑过不下五十轮常见的几个失败模式非常有代表性。第一类是模型把项目ID填错。用户邮件里写的内容往往不是标准ID模型经常把“RF-2024-15”这种编号里的数字提取错。解决办法是在参数校验里加上“ID必须匹配正则 ^RF-\d{4}-\d{2}$”不匹配就反馈给模型重新提取。第二类是模型生成摘要时过度发挥。明明查询结果只有三条更新它却编出一些“预计下月完成”的推测。这种幻觉单靠工具调用链路拦不住需要在“生成摘要”的提示词里加约束只能引用工具返回数据不得额外推断。如果还是出现就再让工具返回结果里带上“更新时间戳”由系统校验摘要里是否内部一致。第三类最值得注意模型在这个任务里反复调用fetch_project_progress因为用户原始邮件里提到了多个项目。模型可能分不清“主要询问的是哪个”于是每个都查一遍。这本身没坏处但会拖慢响应。处理办法是在提示词里加一句“如果用户未明确指定项目先询问澄清不要批量查询”让模型学会停住。7. 我在实战里踩过的几个坑写给正在搭建Agent的人最后分享几个比较碎但很实用的心得基本都来自我在OpenCSG社区里看到的共性问题。7.1 “工具描述全是精确术语”并不好理解早期我给工具写描述时喜欢用特别学究的说法“Call create_disputeAPI-3B发起售后争议流程。”结果模型经常不调用它因为用户不会说“售后争议流程”用户只会说“我要退款”“这单有问题”“把钱退给我”。后来我把描述改成“当用户对订单不满、要求退款、抱怨货物有问题或提出售后相关诉求时可以调用本工具发起争议处理流程。”模型的理解准确率立刻上来了。这就是“工具描述是用给模型看的不是用给文档评审看的”含义。7.2 温度参数不是越高越好调很多人调Agent时习惯把temperature调到比较高觉得“生成内容更丰富”。但在工具调用场景这是大忌。温度一旦调高模型输出JSON时格式不稳定的概率显著增大参数值也会出现无意义的偏移。我目前的做法是涉及工具调用的推理环节temptature固定在0.1以内只有“生成文案”这种创意型子任务才把温度调到0.7以上。也就是同一个Agent内不同子任务用不同的温度参数而不是全局一套设置。7.3 先拦截动作再拦截输出最后一条经验来自一次差点出事的事故。某个内部工具可以删除项目附件模型在生成回复时提到“用户要求删除附件已处理”。但实际上模型根本没有调用删除工具它只是在“输出层面”编造了一个结果。幸好当时有动作审计日志一查发现没有对应调用记录才没让用户以为真的删了。从此我养成了一个习惯所有输出给用户的结果必须能跟工具调用记录一一对应。模型可以说“已处理”但如果处理记录里没有动作那就说明它撒谎了。先拦住“动作”再去纠正“输出”。这也是安全边界的最后一环——审计追踪。搭智能体跟搭传统服务不一样你要同时面对模型的创造性、系统状态的复杂性、以及用户预期的错位。但只要把任务拆明白、把工具描述写清楚再把安全边界划到执行链路里这件事就会从一个“玩具”变成“生产力”。剩下的就是多跑几轮让异常样本帮你打磨系统的每一个判断分支。