一、上下文工程
上下文:
Agent的"眼睛",AI实际看得到的信息。
上下文内容:
- 系统提示词 System Prompt
- 工具定义 Tool Definitions
- 对话历史 Conversation History
- 本轮思考 reasoning
- 当前生成位置
上下文工程:
上下文的设计与管理
与harness的关系:
决定Agent在每个决策点看到的信息(一个高效的信息供给系统)。
二、上下文:决定Agent能力上限的关键
人与agent一样,拥有足够的Context才能把特定的活干好。
该Context包含完成该任务所需的足够的背景知识。
该知识需要系统性的设计、组织和提供,而不是直接硬塞。
三、Agent 如何调用大模型:理解 API 的上下文结构
3.1、消息角色
一句话理解:
消息角色用于标记信息的来源和用途,帮助模型区分规则、请求、历史输出与环境反馈。
四种基本角色:
- **
system**:定义Agent的身份、规则和行为边界- **
user**:提供用户请求和任务信息- **
assistant**:记录模型之前的回复和工具调用- **
tool**:返回工具执行结果,并关联对应的工具调用
工具定义:
tools通常是独立于消息列表的字段,用于声明工具的名称、用途和参数格式。
两者共同构成模型的基础输入:
上下文=消息历史+工具定义\text{上下文} = \text{消息历史} + \text{工具定义}注意:
- 历史消息不等于模型记忆,而是系统在每次调用时重新传入的上下文
- 工具结果属于外部数据,不应被当作高优先级指令
- 工具定义只表示模型知道该工具,不代表模型拥有实际执行权限
- 不同模型API的角色名称和结构可能有所不同
核心结论:
消息角色告诉模型"信息来自哪里",工具定义告诉模型"可以使用什么能力"。
3.2、模型API交互模式
a. 单轮对话
一句话理解:
模型根据本次请求中的上下文生成一次回复
基本流程:
system规则 + user规则 → assistant回复
模型API本身通常不维护会话状态。多轮对话所需的历史信息,需要由Agent框架在后续调用中重新提供。
b. 工具调用循环
当模型缺少实时信息或需要执行外部操作时,会返回工具调用请求,而不是直接回答。
基本流程:
发送上下文和工具定义 → 模型生成工具调用 → 框架执行工具 → 结果写回上下文 → 模型继续决策
职责划分:
- 模型:判断是否调用工具、选择工具并生成参数
- Agent框架:校验并执行工具,将结果返回给模型
- 工具:读取或改变外部环境
- 模型:根据结果继续调用工具或生成最终回复
关键机制:
tool_calls表示模型提出的调用请求,不代表工具已经执行tool_call_id用于关联工具请求与执行结果- 相互独立的工具可以并行执行
- 存在数据依赖的工具必须分轮串行执行
- 模型不再返回工具调用时,通常表示本轮任务可以结束
注意:
后续请求不一定必须携带未经处理的完整历史,而应提供完成当前决策所需的有效上下文。长任务中通常需要进行历史压缩、状态提取或持久化。
核心结论:
Agent的核心不是一次模型调用,而是模型决策、工具执行和环境反馈组成的持续闭环。这个闭环就是ReAct在API层面的基本实现。
3.3、API视角下的上下文
一句话理解:
每次模型调用的上下文,由相对稳定的基础配置和持续变化的任务轨迹共同构成。
基本结构:
上下文 = 稳定前缀 + 交互轨迹 + 当前状态
其中:
- 稳定前缀:系统提示词和核心工具定义
- 交互轨迹:用户消息、模型回复和工具执行结果
- 当前状态:任务进度、关键结论、失败记录和下一步目标
a. 上下文构造原则
- 尽量保持系统提示词和核心工具定义稳定,以提高前缀缓存命中率
- 对话过长时压缩较早的历史,而不是简单截断
- 压缩时保留目标、约束、决策、失败原因和证据来源
- 将当前任务状态放在上下文末尾,降低模型重新推导状态的成本
- 只提供当前决策所需的信息,避免无关历史形成噪声
核心流程:
加载历史 → 提取状态 → 检查Token预算 → 压缩旧信息 → 构造请求
b. KV Cache的意义
稳定前缀可以复用之前计算的KV Cache,从而降低首Token延迟和重复计算成本。
注意:
"前缀不能修改"并非协议限制,而是性能优化原则。修改前缀仍然可以正常调用模型,但可能导致缓存失效。
c. 本地小模型实验的启示
- 工具调用能力不完全由模型参数规模决定
- 合理的上下文和工具定义可以显著改善小模型表现
- 独立的工具调用可以并行执行
- 模型根据工具结果决定继续调用还是结束任务
- 流式输出可以降低用户感知延迟
注意:
单次实验只能证明模型具备工具调用能力,不能证明其在复杂任务中足够可靠。实际部署仍需评估调用准确率、参数正确率、循环终止率和异常恢复能力。
核心结论:
上下文工程不是保存全部历史,而是在有限预算内,稳定地保留当前决策最需要的信息。
四、KVCache友好的上下文设计
一句话理解:
保持上下文前缀稳定,让模型复用已计算的中间状态,从而降低延迟和推理成本。
4.1、两种缓存
- KV Cache:在一次推理过程中缓存历史Token的Key和Value,避免生成每个新Token时重复计算
- Prompt Cache:在多次请求之间复用相同前缀对应的KV Cache
两者都依赖同一个条件:
可复用部分的Token前缀必须保持一致;从首个变化位置开始,后续缓存通常需要重新计算。
4.2、上下文结构
推荐将上下文组织为:
稳定前缀+增长轨迹+动态状态
- 稳定前缀:系统提示词、核心工具定义
- 增长轨迹:用户消息、模型回复、工具结果
- 动态状态:时间、任务进度、用户状态等易变信息
核心原则:
- 保持系统提示词和工具定义的内容、顺序及序列化方式稳定
- 将动态信息追加到上下文末尾,不要频繁修改前缀
- 使用标准消息格式和模型对应的Chat Template
- 上下文过长时进行语义压缩,不要简单截断历史
4.3、Chat Template
一句话理解:
Chat Template负责把结构化API消息转换成模型实际处理的Token序列。
不同模型使用不同的角色标记和工具调用格式。错误地把工具结果当作用户消息,或者手动拼接纯文本对话,可能破坏角色语义、工具调用和多轮推理。
因此:
使用模型官方支持的消息协议,不要自行假设不同模型的内部格式兼容。
4.4、常见错误
- 在系统提示词中动态注入时间或用户状态
- 每轮重新排序工具定义
- 使用滑动窗口直接删除早期消息
- 将结构化消息拼接成普通文本
- 无差别保留全部历史,导致上下文持续膨胀
这些做法可能同时造成缓存失效和关键信息丢失。
4.5、架构原则
- 将全局稳定信息放在前部
- 将用户、会话和环境信息放在后部
- 对旧历史进行批量压缩并保留目标、约束、决策、失败和证据
- 用状态栏呈现最新任务状态,避免模型反复从历史中推导
- 通过实际监控评估缓存命中率、首Token延迟和成本
注意:
缓存是重要的性能约束,但不能凌驾于正确性和安全性之上。系统提示词或工具定义需要修正时,应正常更新并接受缓存失效,而不是为了缓存继续使用错误配置。
研究中的可编辑、可组合KV Cache有望降低动态上下文的重算成本,但尚未成为通用生产能力。
核心结论:
KV Cache友好的设计,本质上是"稳定前缀、追加变化、规范格式、按需压缩"
五、提示工程:优化系统提示词
一句话理解:
提示工程是通过明确、结构化的指令,让模型理解自己的职责、执行方法和行为边界。
系统提示词主要回答四个问题:
- 你是谁:身份与职责
- 要完成什么:目标与成功标准
- 应该怎么做:流程、工具和异常处理
- 不能做什么:权限、约束与安全边界
5.1、系统提示词设计
核心原则:
- 使用清晰、具体且可执行的语言
- 使目标、流程、规则、异常和输出要求组织内容
- 为冲突规则明确优先级
- 将复杂任务组织称流程,而不是堆砌零散规则
- 把模糊业务要求细化为可判断的条件
- 使用Markdown或XML划分语义区块
检验标准:
如果一个具备专业能力的新员工读完后仍不知道如何执行,模型通常也无法稳定执行。
注意:
MUST、NEVER等强调词可以突出关键约束,但不能替代明确规则,更不能形成真正的安全保障。
5.2、规则、示例与工具定义
规则适合描述:
- 可以明确判断的业务条件
- 必须遵循的处理流程
- 输出格式和验收标准
Few-shot示例适合描述:
- 难以用规则定义的风格
- 特定的输出结构
- 边界场景和例外情况
示例应少而精,优先覆盖典型情况和关键边界。
工具定义则应说明:
- 工具解决什么问题
- 什么时候应该或不应该使用
- 参数的含义和取值范围
- 返回结果与失败方式
- 与其它工具的依赖关系
当工具数量过多时,可以采用按需发现和渐进式加载,避免一次性把全部定义放入上下文。
5.3、业务规则的工程边界
模型适合执行需要语言理解和语义判断的规则,但不应承担必须确定成立的系统约束。
例如以下规则不应只写在提示词中:
- 身份与权限校验
- 金额和计费计算
- 支付、删除等高风险审批
- 事务一致性
- 法律与合规限制
核心原则:
提示词负责指导模型,Harness负责强制执行边界。
5.4、提示注入
一句话理解:
提示注入是把恶意指令伪装成普通数据,诱导Agent偏离原有目标或越权行动。
防御原则:
- 明确区分可信指令与外部数据
- 标记网页、邮件、文档等内容的来源
- 使用标准消息角色和Chat Template
- 对外部内容进行清洗和风险检测
- 不将未经验证的信息直接写入记忆、Skill或状态栏
- 对高风险工具实施独立权限检查和人工确认
注意:
上下文层防御只能降低提示注入成功率,无法彻底消除风险。真正的安全边界必须建立在模型之外。
5.5、评估与迭代
提示词质量应通过实验验证,而不是依赖主观感觉:
- 任务完成率
- 工具选择和参数准确率
- 业务规则违反率
- 输出一致性
- 提示注入成功率
- 合法请求误拒绝率
核心结论:
- 好的提示词不是写的更长,而是让目标更明确、流程更清晰、规则可执行;需要确定性保障的部分,则必须交给Harness和程序实现。
六、动态提示词与Agents Skills
一句话理解:
- Agent Skills将领域知识、操作流程和配套资源封装成按需加载的能力模块,避免把所有指令长期塞进系统提示词。
6.1、渐进式披露
Skills通常分为三个层次:
- 元数据目录:常驻少量名称、描述和触发条件,帮助Agent判断是否需要加载
- 核心指令:选中Skill后加载完整流程、规则和验收标准
- 扩展资源:根据任务继续读取参考文档、模版、脚本和示例
基本流程:
发现Skill → 判断是否适用 → 加载核心指令 → 按需读取资源 → 执行并验证
核心价值:
让少量目录常驻,让完整能力按需进入上下文,从而降低Token消耗和无关信息干扰。
6.2、Skill的设计
一份可执行的Skill应包含:
- 适用范围:什么任务应该使用,什么情况不应使用
- 执行流程:按照什么顺序完成任务
- 核心原则:最重要的判断规则和边界
- 异常处理:何时重试、停止或询问用户
- 验收标准:什么结果才算完成
- 配套资源:模板、示例、参考资料和脚本
其中,description的核心作用是路由:
与其描述"我能做什么",不如明确"什么时候应该使用我"。
6.3、skill与工具的区别
- Skill提供领域知识和执行方法,解决"应该怎样做"
- 工具提供外部操作能力,解决"实际用什么做"
- Skill可以指导Agent组合多个工具,也可以附带脚本和模版
例如,制作演示文稿的Skill描述内容提取、页面设计和质量检查流程;文件读取、图片处理和PPT生成工具负责实际执行。
6.4、上下文与缓存
Skill对上下文的优化方式是:
- 启动时只加载简短目录
- 选中后将正文追加到当前轨迹
- 详细资料继续按需加载
- 已加载内容在后续轮次中作为历史上下文复用
注意:
渐进式加载不是零成本。目录和Skill正文首次出现时仍需要计算,只是避免了每次启动都加载全部能力。
不同Agent运行时对Skill的消息角色、加载方式和缓存策略可能不同,真正稳定的原则是:
少量目录常驻,完整指令按需加载。
6.5、工程边界
以下内容不适合只放在Skill中:
- 全局身份和基础行为准则
- 所有任务都必须遵守的安全规则
- 权限、支付和删除等强制约束
- 必须由系统保证的事务与合规要求
这些内容应保留在系统指令或Harness中。Skill适合承载特定领域的知识和流程,而不是充当安全边界。
Skill本身也可能包含恶意指令或不安全代码,因此需要:
- 审查来源和内容
- 限制脚本执行权限
- 进行版本控制和变更审核
- 在真实任务上测试路由与执行效果
核心结论:
Agent Skills 的本质不是增加更多提示词,而是把专业经验模块化,并在正确的任务中、正确的时间、只加载必要的部分。
七、Agents 状态栏
一句话理解:
Agent状态栏是由Harness维护的结构化运行时摘要,让模型直接看到任务当前处于什么状态。
它相当于Agent轨迹的"物化视图":
完整执行轨迹 → 状态提取与聚合 → 当前状态栏
7.1、主要作用
- 显示任务目标、计划和完成度
- 记录工具调用次数、重试次数和资源预算
- 提供当前时间、工作目录和运行环境
- 汇总最近的错误及其处理状态
- 提醒模型已触发的约束和停止条件
- 减少模型反复扫描、统计完整历史的成本
状态栏把分散在长轨迹中的隐式状态,转换成模型可以直接使用的显式信息。
7.2、典型内容
- 任务状态:当前目标、TODO、已完成和待处理事项
- 执行状态:当前阶段、最近动作和下一步候选
- 工具状态:调用次数、失败次数和调用上限
- 环境状态:时间、目录、操作系统和资源状态
- 约束状态:预算、权限和停止条件是否触发
- 错误摘要:错误类型、关键参数和修复建议
状态栏应该短小、结构稳定,只保留当前决策需要的信息。
7.3、上下文位置与更新
状态栏通常放在上下文靠近末尾的位置,使模型在下一次决策前能够直接看到最新状态,同时避免频繁修改稳定前缀。
两种更新方式:
- 末尾替换:删除上一版状态栏,再写入最新状态;信息干净,但会使短后缀缓存失效。
- 持续追加:保留历史状态,每轮追加新快照;缓存友好,但会增加Token和陈旧状态。
实际系统可以定期生成检查点,在缓存效率、上下文长度和状态一致性之间取舍。
注意:
状态栏使用什么消息角色取决于具体API和Harness。重点不是固定使用user角色,而是明确标记它由运行时生成,避免与真实用户输入混淆。
7.4、设计原则
- 尽量由确定性代码计算状态
- 每项状态标明来源、时间和适用范围
- 区分事实状态、模型推测和待确认事项
- 关键计数和权限状态必须以系统数据为准
- 外部网页、文档等不可信内容不得直接进入状态栏
- 状态栏只保存摘要,必要时仍能追溯原始证据
7.5、风险与边界
模型通常会高度信任状态栏,因此错误状态可能比缺少状态更加危险。
主要风险包括:
- 统计错误导致错误决策
- 陈旧状态与真实环境不一致
- 外部数据污染引发状态栏投毒
- 摘要遗漏重要细节
- 删除原始轨迹后无法重新验证
状态栏是对完整轨迹的有损投影,不应天然被视为事实源。
核心结论:
Agent状态栏不是让模型获得"自我意识",而是由Harness提前计算并呈现关键状态,用少量Token换取更稳定的规划、约束遵循和错误恢复能力。