all articles
dev · ZH

AI 开发工程师必须要懂的 AI 开发基础

May 21, 2026·44 min read·by Mr Panda·2 阅读

AI 开发工程师必须要懂的 AI 开发基础

大模型的能力边界在快速扩张,但真正决定一个 AI 应用能不能用、好不好用的,往往是围绕模型的那一整套工程体系。

这篇文章系统梳理 AI 开发中的核心概念和技术原理:从 LLM API 到 KV Cache,从 Agent Loop 到 Tool Use,从 Prompt Engineering 到 Context Engineering 再到 Harness Engineering。目标是让你建立起一张完整的知识地图,知道每个概念在整个体系中处于什么位置、解决什么问题、与其他概念如何关联。

LLM API:一切的起点

所有 AI 应用的底层都是一次 LLM API 调用。理解 API 的工作机制是 AI 开发的第一步。

Chat Completion 接口

目前主流的 LLM API 都采用 Chat Completion 的接口范式。你发送一组消息(messages),模型返回一条回复。每条消息有一个角色标记——system、user、assistant——模型根据这些角色和内容来决定如何回复。

一个最基本的调用长这样:

response = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    system="你是一个专业的技术顾问。",
    messages=[
        {"role": "user", "content": "什么是 KV Cache?"}
    ]
)

看似简单,但这个接口背后有几个关键概念需要理解。

Token

模型不处理文字,处理 token。一个中文字通常是 1-2 个 token,一个英文单词通常是 1-3 个 token。token 是计费单位,也是上下文窗口的度量单位。理解 token 才能理解成本和约束。

上下文窗口(Context Window)

每个模型有一个上下文窗口上限,比如 Claude 的 200K tokens、GPT-4o 的 128K tokens。这个窗口装的是你发给模型的全部内容加上模型的全部回复。窗口用完了,要么截断历史消息,要么做摘要压缩。

一个常见的误解:上下文窗口越大越好。实际上,模型在长上下文中的注意力会衰减。研究表明,信息放在上下文的开头和结尾,被模型关注到的概率最高;放在中间则容易被忽略。这就是所谓的"Lost in the Middle"现象。上下文窗口是一种有限资源,需要精心管理,而非简单堆砌。

Streaming(流式输出)

模型逐 token 生成文本。如果等全部生成完再返回,用户要盯着空白屏幕好几秒。Streaming 让模型一边生成一边返回,用户看到的是文字"逐字打出来"的效果,体验大幅提升。

with client.messages.stream(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    messages=[{"role": "user", "content": "解释 Transformer 架构"}]
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)

Streaming 同时也降低了首 token 延迟(Time to First Token,TTFT),这在面向用户的应用中至关重要。

结构化输出(Structured Output)

在很多场景下,你需要模型返回结构化数据而非自然语言。比如,你要模型分析一段文本的情感,返回 JSON 格式的结果。主流 API 都支持通过 JSON Schema 约束模型的输出格式,确保返回的数据能被程序直接解析。

response = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    messages=[{"role": "user", "content": "分析这段文本的情感..."}],
    # 通过工具定义约束输出格式
    tools=[{
        "name": "sentiment_analysis",
        "description": "输出情感分析结果",
        "input_schema": {
            "type": "object",
            "properties": {
                "sentiment": {"type": "string", "enum": ["positive", "negative", "neutral"]},
                "confidence": {"type": "number"},
                "reasoning": {"type": "string"}
            },
            "required": ["sentiment", "confidence", "reasoning"]
        }
    }]
)

掌握这四个基本机制——消息接口、token 计量、流式输出、结构化输出——你就具备了调用 LLM 的完整基础。

KV Cache:理解推理性能的关键

KV Cache 是大多数 AI 开发者知道但没真正理解的概念。它直接影响推理速度和成本,是优化 AI 应用性能的关键知识。

为什么需要 KV Cache

Transformer 模型的核心是自注意力机制(Self-Attention)。简单说,模型在生成每一个新 token 时,需要"回头看"前面所有的 token,计算当前 token 和每个历史 token 之间的关联程度。这个"回头看"的过程需要用到两组矩阵——Key 和 Value(简称 KV)。

问题在于:如果模型已经生成了 1000 个 token,生成第 1001 个时需要重新计算前面 1000 个 token 的 Key 和 Value 吗?不需要。前面 token 的 KV 值在整个生成过程中不会变化,可以缓存下来复用。这就是 KV Cache。

KV Cache 的工作原理

想象一个简化的场景。模型要逐字生成"今天天气真好"这五个字:

  1. 生成"今"时,没有历史,不需要缓存
  2. 生成"天"时,需要看"今"的 KV,同时把"今"的 KV 存入缓存
  3. 生成第二个"天"时,直接从缓存读取"今""天"的 KV,只需要计算新 token 自己的 KV
  4. 以此类推,每生成一个新 token,只需计算一个新的 KV 对,其余全部从缓存读取

没有 KV Cache,生成第 N 个 token 需要计算 N 次 KV;有了 KV Cache,只需计算 1 次。这把推理的时间复杂度从 O(N²) 降到了 O(N)。

Prompt Caching:KV Cache 的工程延伸

KV Cache 是模型推理层面的优化,对开发者来说通常是透明的。但有一个直接可用的工程特性与之相关——Prompt Caching。

很多 AI 应用有大量重复的上下文。比如你的系统提示词有 5000 个 token,每次用户提问都要带上。Prompt Caching 允许 API 提供商缓存这些不变的前缀部分的 KV 值,后续请求直接复用,不再重复计算。

实际效果:Anthropic 的 Prompt Caching 可以将重复前缀部分的处理速度提升约 85%,成本降低约 90%。对于有长系统提示词的应用来说,这是一个显著的优化手段。

三大 API 提供商的 Prompt Caching 对比

主流 LLM API 都已经支持 Prompt Caching,但实现方式和计费策略差异不小:

特性 OpenAI Anthropic Google
激活方式 全自动,无需改代码 显式标记 cache_control 隐式自动 + 显式手动两种
最小 token 数 1,024 1,024 - 4,096(因模型而异) 1,024(隐式)/ 32,768(显式)
缓存读取折扣 ~90% 90% 75%-90%
写入附加费 1.25x(5 分钟 TTL)或 2.0x(1 小时 TTL) 无(隐式)/ 按存储计费(显式)
TTL 5-60 分钟自动管理 5 分钟或 1 小时可选 可配置,默认 1 小时

OpenAI 最省心——全自动,不需要改代码,没有写入附加费。Anthropic 控制力最强——开发者精确指定缓存哪些内容,90% 读取折扣,但写入有额外成本。Google 最灵活——隐式和显式两条路都支持,显式模式适合反复引用大型静态上下文(文档、代码库)。

KV Cache 优化的主流框架

对于调用 API 的开发者来说,KV Cache 优化是透明的。但如果你需要自己部署和运维开源模型,推理引擎的 KV Cache 管理能力就成了核心选型依据。当前四个一线推理引擎:

vLLM——社区最大、硬件兼容性最广的推理引擎。核心技术是 PagedAttention:将 KV Cache 拆分为固定大小的块,以非连续方式存储在 GPU 显存中,将内存浪费从 60%-80% 降低到 4% 以下。同时支持 FP8 KV Cache 量化、前缀缓存和连续批处理。如果你不确定选哪个引擎,vLLM 是最安全的起点。

SGLang——在 vLLM 的分页内存管理基础上增加了 RadixAttention:用 LRU 基数树持久化复用 KV Cache。请求完成后不丢弃 KV Cache,当新请求共享相同前缀时直接复用。在前缀密集的场景下(Agent 循环、多轮对话、共享系统提示词),SGLang 比 vLLM 吞吐量高约 29%,并且峰值显存占用最低。

TensorRT-LLM——NVIDIA 的推理引擎,在 H100/H200 上有最深的硬件级优化,官方声称吞吐量比 vLLM 高 2-4 倍。代价是只支持 NVIDIA 硬件,灵活性较差。

DeepSeek FlashMLA——DeepSeek 开源的高效 MLA(多头潜在注意力)CUDA 内核。MLA 架构用低秩投影替代完整的 K/V 张量,实现 7-14 倍的 KV Cache 压缩。在 H800 上解码阶段可达 410 TFLOPS。如果你部署 DeepSeek 系列模型,FlashMLA 是必备组件。

关键优化技术总结

当前 KV Cache 优化的技术栈已经趋于成熟,形成了清晰的分层:

  • 底层基座:PagedAttention——非连续分页存储,消除内存碎片,几乎所有现代推理引擎都已集成
  • 应用层高杠杆:前缀缓存(Prefix Caching)——复用共享前缀的 KV 状态,Agent 循环和多租户场景下缓存命中率可达 60%-85%,单次调用成本降低 5-12 倍
  • 架构层压缩:GQA / MLA——在模型架构层面减少 KV Cache 体积。GQA(Grouped-Query Attention)让多个查询头共享一组 KV 头,被 Llama 3、Mistral 等模型采用;MLA 更激进,压缩比达 7-14 倍,是 DeepSeek 能经济地支撑超长上下文的架构基础
  • 内存优化标配:FP8 量化——将 KV Cache 从 FP16 压缩到 FP8,显存减半,精度损失低于 1%,吞吐量提升 30%-50%。2026 年的行业共识是"每个团队都应该开启 FP8 KV Cache"

开发者需要关心什么

  1. 消息顺序很重要:Prompt Caching 缓存的是从头开始的连续前缀。如果你把系统提示词放在消息序列的中间而非开头,缓存就失效了。
  2. KV Cache 大小影响并发:在部署自托管模型时,KV Cache 占用 GPU 显存。上下文越长、并发用户越多,显存消耗越大。这是部署规划必须考虑的因素。
  3. 理解缓存命中率:如果你的 API 调用返回中有 cache hit 的指标,关注它。高缓存命中率意味着更低的延迟和成本。
  4. 选择推理引擎时关注 KV Cache 策略:如果你的场景是前缀密集型(Agent、多轮对话),优先考虑 SGLang;如果追求最广的硬件兼容性,选 vLLM;如果全部是 NVIDIA 硬件且追求极致性能,TensorRT-LLM 值得评估。

Agent Loop:从"问答"到"自主执行"

LLM API 本质上是一个"你问我答"的接口——输入一次,输出一次,交互结束。Agent Loop 是让模型从"被动回答"升级为"主动执行"的核心机制。

基本原理

Agent Loop 的逻辑极其简单:

while True:
    response = llm.generate(context)
    if response.wants_to_use_tool:
        result = execute_tool(response.tool_call)
        context.append(result)
    else:
        return response.text  # 模型认为任务完成,退出循环

整个过程就三步:模型思考并决定下一步行动→执行行动并获取结果→将结果加入上下文,进入下一轮思考。循环持续进行,直到模型判断任务已完成(不再调用工具,直接给出最终答案)。

为什么这很重要

传统的 LLM 调用是单轮的:给一个问题,拿一个答案。但现实中的任务很少能一步完成。比如"帮我修复这个 bug",模型需要先读代码、定位问题、设计修复方案、写代码、运行测试、查看结果——这是一连串的决策和行动。Agent Loop 让模型能够自主完成这样的多步任务。

Agent Loop 的关键设计决策

  1. 退出条件:模型什么时候该停下来?最基本的方式是"模型不再调用工具时视为完成"。但在生产环境中,你通常还需要设置最大循环次数、超时时间等硬性限制,防止模型陷入死循环。

  2. 上下文管理:每轮循环都会往上下文中追加内容(工具调用和返回结果)。经过几十轮循环后,上下文可能会膨胀到窗口上限。这时需要摘要压缩、选择性遗忘等策略来保持上下文的可用性。

  3. 错误处理:工具执行失败了怎么办?好的 Agent Loop 会把错误信息反馈给模型,让模型决定是重试、换一种方式、还是放弃并告知用户。

Agent Loop 是 Agent 架构的骨架。后面讲到的 Tool Use、Reasoning、Planning 等能力,全部运行在这个循环之内。

Tool Use:让模型与真实世界交互

模型的训练数据是静态的,它无法访问你的文件系统、查询你的数据库、调用你的 API。Tool Use(工具调用)弥合了这个鸿沟——通过定义一组工具,让模型能够"动手做事"。

工作机制

Tool Use 的流程分为三步:

第一步,定义工具。你用 JSON Schema 描述每个工具的名称、功能和参数格式:

{
  "name": "read_file",
  "description": "读取指定路径的文件内容",
  "input_schema": {
    "type": "object",
    "properties": {
      "path": {"type": "string", "description": "文件的绝对路径"}
    },
    "required": ["path"]
  }
}

第二步,模型在生成过程中决定调用某个工具,并输出结构化的调用请求:

{
  "type": "tool_use",
  "name": "read_file",
  "input": {"path": "/src/main.py"}
}

第三步,你的程序执行这个工具调用,将结果返回给模型:

{
  "type": "tool_result",
  "content": "import os\ndef main():\n    ..."
}

模型拿到结果后,继续思考下一步该做什么——可能再调用另一个工具,也可能直接给出最终回答。这就是 Agent Loop 的一次迭代。

工具设计的原则

工具定义的质量直接决定 Agent 的表现。几个核心原则:

  • 命名清晰search_codebasesearch 好,模型能更准确地判断何时使用。
  • 描述精确:不仅要说工具做什么,还要说什么时候该用、什么时候不该用。
  • 参数约束明确:用 enum 限定取值范围,用 required 标明必填字段,减少模型犯错的概率。
  • 返回值精简:不要返回巨量原始数据。如果数据库查询返回了 10000 行,做分页或摘要后再返回给模型。过多的返回内容会迅速填满上下文窗口,降低模型后续推理的质量。

并行工具调用(Parallel Tool Use)

一些 API 支持模型在单次响应中发起多个工具调用。比如模型需要同时读取三个文件来理解一段代码,它可以一次性发出三个 read_file 请求,而非一个接一个地串行调用。这大幅减少了 Agent Loop 的迭代次数,提升执行效率。

Reasoning:模型如何"思考"

直接让模型给出答案和让模型"想清楚再回答",效果天差地别。Reasoning 能力是 LLM 从"文本补全器"进化为"问题求解器"的关键。

Chain of Thought(思维链)

最基础的 Reasoning 技术。通过在提示词中要求模型"一步一步思考",或者给出一个分步推理的示例,模型会在输出最终答案之前先生成中间推理步骤。这个简单的技巧能显著提升模型在数学、逻辑、代码等需要多步推理的任务上的表现。

Extended Thinking(扩展思考)

更进一步,部分模型(如 Claude)支持 Extended Thinking 模式,模型在给出可见回复之前会进行一段较长的内部推理。这段推理过程对开发者是可见的(通过 API 返回),但对终端用户可以选择隐藏。

response = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=16000,
    thinking={
        "type": "enabled",
        "budget_tokens": 10000  # 给模型的"思考预算"
    },
    messages=[{"role": "user", "content": "这段代码为什么会导致死锁?"}]
)

# response.content 包含 thinking blocks 和 text blocks
for block in response.content:
    if block.type == "thinking":
        print(f"思考过程: {block.thinking}")
    elif block.type == "text":
        print(f"最终回答: {block.text}")

Extended Thinking 的核心优势在于:模型可以在"思考空间"中进行试错、自我纠正和方案比较,而这些中间过程不会污染最终输出。

ReAct:推理与行动的统一框架

前面分别讲了 Reasoning(怎么想)和 Tool Use(怎么做),ReAct(Reasoning + Acting)是把两者融合到一起的关键范式。它由 Yao 等人在 2022 年提出,论文标题直译过来就是"协同推理与行动的语言模型"。

ReAct 的核心思想很简单:模型在每一步先生成一段推理(Thought),基于推理决定一个行动(Action),执行行动后获得观察结果(Observation),再基于观察进行下一轮推理。整个过程形成一个 Thought → Action → Observation 的循环:

Thought: 用户要求修复登录失败的 bug,我需要先看看认证相关的代码
Action:  search_codebase("authentication login")
Observation: 找到 src/auth/login.ts,第 47 行有一个 token 过期检查...

Thought: token 过期检查的逻辑有问题,比较运算符用反了
Action:  read_file("src/auth/login.ts")
Observation: [文件内容...]

Thought: 确认了,第 47 行 `if (now < expiry)` 应该是 `if (now > expiry)`
Action:  edit_file("src/auth/login.ts", ...)
Observation: 文件已修改

Thought: 修改完成,需要运行测试验证
Action:  run_tests("src/auth/")
Observation: 12 tests passed

如果你对比前面讲的 Agent Loop 代码,会发现 ReAct 就是 Agent Loop 的理论基础。Agent Loop 提供了工程上的循环机制,ReAct 定义了循环内部的认知模式——每次迭代中模型应该先想再做,做完再看结果,看完再想。

ReAct 之前也有人尝试过让模型使用工具,但那些方案中"推理"和"行动"是分离的——要么先一口气想完所有步骤再执行,要么直接行动不做推理。ReAct 的贡献在于证明了交替进行推理和行动的效果远优于两者分离。推理帮助模型决定下一步该做什么、该调用什么工具;行动的结果反过来为推理提供新的信息,纠正错误的假设。两者互相增强。

今天几乎所有生产级 Agent 系统——Claude Code、ChatGPT、Cursor——底层都在用 ReAct 模式,只是不一定显式地在输出中标注 Thought / Action / Observation 这三个标签。模型已经通过训练内化了这个模式:先在内部推理(或通过 Extended Thinking 显式推理),然后决定调用工具,拿到结果后继续推理。

Reasoning 对 Agent 的意义

在 Agent 场景中,Reasoning 能力决定了模型能否正确地分解任务、选择合适的工具、处理意外情况。一个缺乏 Reasoning 能力的模型,即使拥有再多的工具,也只能做简单的单步操作;而一个 Reasoning 能力强的模型,能在 Agent Loop 中做出一连串合理的决策。

Planning:先想清楚再动手

Planning 和 Reasoning 密切相关但侧重点不同。Reasoning 是"怎么想",Planning 是"先想好再做"。

为什么 Agent 需要 Planning

一个没有规划能力的 Agent 会"想到什么做什么"。比如你让它重构一个模块,它可能上来就改第一个看到的文件,改到一半发现依赖关系没理清,又回头改另一个文件,反复来回,效率极低甚至做不完。

有规划能力的 Agent 会在动手之前先分析任务:需要改哪些文件、改的顺序是什么、有哪些依赖关系、怎么验证修改正确。制定计划之后再逐步执行,遇到需要调整的情况再更新计划。

Planning 的实现方式

大多数 Agent 框架通过系统提示词引导模型在执行任务前先输出计划。更复杂的实现会将计划作为一种持久化状态,Agent 在每轮循环中参考计划、更新计划进度,确保长任务不会偏离方向。

实际工程中,Planning 通常有两种粒度:

  • 粗粒度计划:在任务开始时生成一个整体方案,Agent 在执行过程中参考这个方案。
  • 细粒度计划:Agent 在每一步行动前进行局部规划,决定接下来最合理的 1-2 步操作。

好的 Agent 两者都需要——粗粒度计划确保方向正确,细粒度计划确保每一步行动合理。

Skills:可复用的能力单元

Skill(技能)是对一组相关能力的封装,让 Agent 在特定场景下表现得更加专业。

Skill 与 Tool 的区别

Tool 是原子级操作——读文件、执行命令、发请求。Skill 比 Tool 高一个抽象层次,它包含了完成某类任务所需的提示词模板、工具组合和工作流程。

举例来说:

  • Toolread_filewrite_filerun_command
  • Skill:"代码审查"——知道要先读代码、运行测试、检查代码风格、关注安全漏洞、最后输出结构化的审查报告

Skill 本质上是一份"做某类任务的专业知识"的封装,它告诉 Agent 在面对特定类型的任务时,应该按什么思路、调用哪些工具、注意哪些事项。

Skill 的工程价值

在 Agent 开发中,Skill 解决的是"专业能力复用"的问题。与其每次都在系统提示词中写清楚"如何做代码审查"的全套指令,不如把这些知识封装成一个 Skill,需要时加载到上下文中。这让 Agent 在保持通用性的同时,在特定领域达到专家级表现。

MCP:连接模型与外部世界的标准协议

MCP(Model Context Protocol,模型上下文协议)是 Anthropic 在 2024 年底推出的开放标准。它要解决的问题很具体:如何让 LLM 以一种标准化的方式连接外部数据源和工具。

为什么需要 MCP

在 MCP 出现之前,每个 AI 应用接入外部工具都需要写定制的集成代码。你要接 GitHub?写一套。接 Slack?再写一套。接数据库?又写一套。每个 LLM 提供商的 Tool Use 接口还略有不同,进一步增加了适配成本。

这就像 USB 出现之前,每个外设都有自己独特的接口。MCP 的目标就是成为 AI 领域的 USB——一个通用的连接标准。

MCP 的架构

MCP 采用客户端-服务器架构:

  • MCP Server:封装了某个外部服务的能力。比如一个 GitHub MCP Server 提供"创建 PR""查看 Issue"等能力。任何人都可以开发 MCP Server。
  • MCP Client:嵌入在 AI 应用中,负责发现和连接可用的 MCP Server,将 Server 提供的能力转化为模型可调用的工具。
  • 传输层:Client 和 Server 之间通过标准化的 JSON-RPC 协议通信,支持本地进程通信(stdio)和远程 HTTP(Streamable HTTP)两种传输方式。

一个 MCP Server 可以提供三种能力:

  • Tools:可执行的操作(创建文件、发送消息)
  • Resources:可读取的数据(文档内容、数据库记录)
  • Prompts:预定义的提示词模板

MCP 对开发者的意义

MCP 最大的价值在于让 Agent 的能力变得"可插拔"。开发 Agent 时,你不需要为每个外部服务写集成代码,只需要连接对应的 MCP Server。社区已经有大量现成的 MCP Server 覆盖主流服务——GitHub、Slack、PostgreSQL、Google Drive 等。

对于工具和服务的提供方来说,只需要开发一次 MCP Server,就能让所有支持 MCP 的 AI 应用使用自己的服务。这是一个双边网络效应的基础。

Memory:让 Agent 拥有记忆

LLM 的每次调用都是无状态的——模型不记得之前的对话。Memory 机制赋予 Agent 跨会话的记忆能力。

短期记忆:上下文内的记忆

最基本的记忆形式就是对话历史。在一次会话中,每一轮对话的内容都被保留在上下文中,模型可以引用前面说过的话。这种记忆的生命周期等于一次会话的长度,受限于上下文窗口大小。

当上下文快要溢出时,常用的处理策略包括:

  • 滑动窗口:丢弃最早的消息,保留最近的
  • 摘要压缩:用模型把历史对话压缩成摘要,用摘要替代原始消息
  • 选择性保留:保留重要消息(如用户的原始需求、关键决策),压缩或丢弃中间过程

长期记忆:跨会话的持久化

更复杂的 Agent 需要跨会话记忆——记住用户的偏好、过去做过的决策、项目的背景信息。实现方式通常有两种:

基于文件的记忆:将需要记住的信息写入本地文件(如 Markdown 文件),每次新会话开始时读取这些文件加载到上下文中。这种方式简单可靠,适合个人开发工具。Claude Code 的 Memory 机制就采用这种方式——将记忆存储在 .claude/ 目录下的 Markdown 文件中。

基于向量数据库的记忆:将信息转化为向量(embedding),存储在向量数据库中。需要回忆时,用当前上下文去做相似度检索,找出最相关的历史记忆。这种方式适合需要从大量历史信息中精准检索的场景。

记忆的工程挑战

记忆系统的核心挑战不是"怎么存",而是"存什么"和"什么时候取出来"。

  • 存什么:不是所有信息都值得记忆。代码的细节会频繁变化,记住"某个函数在第 42 行"这类信息只会产生过时的噪声。值得记忆的是那些不容易从当前状态推导出来的信息——用户的偏好、项目的背景决策、反复出现的工作模式。
  • 什么时候取:记忆加载到上下文中就会占用空间。全部加载显然不现实,关键是在正确的时机加载正确的记忆。这需要对用户当前的意图做判断,然后检索相关的记忆。

Subagent:分而治之

Subagent(子智能体)是一种 Agent 架构模式:一个主 Agent 将任务的一部分委派给专门的子 Agent 来完成。

为什么需要 Subagent

两个核心原因:

第一,上下文隔离。主 Agent 在处理一个大任务时,可能需要做一些辅助性的调查工作(比如搜索代码库中某个函数的所有调用者)。如果在主 Agent 的上下文中做这件事,搜索过程中产生的大量中间结果会污染主上下文,影响后续推理。派一个 Subagent 去做,只把最终结论带回来。

第二,专业化分工。不同类型的任务需要不同的工具集和提示词。代码搜索、代码审查、测试运行可以分别由不同的 Subagent 负责,每个 Subagent 有自己的专用工具和系统提示词,在各自的领域内表现更好。

Subagent 的工作模式

主 Agent
  ├── 分析任务,决定需要委派哪些子任务
  ├── 启动 Subagent A:搜索相关代码
  ├── 启动 Subagent B:查阅文档(可与 A 并行)
  ├── 收集 A 和 B 的结果
  └── 基于子任务结果,继续推进主任务

好的 Subagent 设计有几个关键点:

  • 任务描述要自包含:Subagent 看不到主 Agent 的上下文。分配任务时要把必要的背景信息一并给出,把 Subagent 当作一个刚进入项目的新同事来对待。
  • 结果要精炼:Subagent 返回的结果会进入主 Agent 的上下文。返回内容应该是结论和关键信息,而非原始数据。
  • 合理控制并行度:多个 Subagent 可以并行运行来提升效率,但也要注意资源消耗。

Multi-Agent:多智能体协作

Multi-Agent 是 Subagent 概念的扩展,强调的是多个 Agent 之间的平等协作,而非简单的上下级委派。

Multi-Agent 的典型模式

分工协作模式:不同 Agent 负责不同领域的工作。比如一个代码生成 Agent 和一个代码审查 Agent 配合工作——生成 Agent 写代码,审查 Agent 检查代码质量,发现问题后反馈给生成 Agent 修改。这种模式的优势在于每个 Agent 都能专注于自己的角色,各自有最优化的上下文配置。

辩论与验证模式:多个 Agent 从不同角度分析同一个问题,互相质疑和验证。这在需要高可靠性的决策场景中特别有用——单个 Agent 容易陷入思维定式,多个 Agent 交叉验证能显著降低出错概率。

流水线模式:任务在多个 Agent 之间按顺序传递,每个 Agent 处理其中一个阶段。类似工厂的装配线——一个 Agent 负责需求分析,一个负责代码实现,一个负责测试,一个负责部署。

Multi-Agent 的工程挑战

  • 通信协议:Agent 之间如何传递信息?传递什么格式?这些需要精确定义。
  • 状态同步:当多个 Agent 并行工作时,如何确保它们对任务状态的理解一致?
  • 冲突解决:两个 Agent 给出了矛盾的建议,谁说了算?
  • 调试复杂度:单个 Agent 出了问题容易排查,多个 Agent 交互中出现的问题追踪起来难度呈指数增长。

Multi-Agent 架构的核心权衡是:增加了系统的能力上限,但也增加了系统的复杂度。在选择是否使用 Multi-Agent 之前,先确认单个 Agent 确实无法胜任任务。

Prompt Engineering:与模型沟通的基本功

Prompt Engineering 是最早被广泛讨论的 AI 工程实践,它关注的是如何编写有效的提示词来引导模型产生期望的输出。

核心技术

角色设定(Role Prompting):通过在系统提示词中设定模型的角色和专业背景,引导模型以特定的视角和风格回答问题。比如"你是一位资深后端工程师"和"你是一位安全审计专家",同一段代码喂给这两个角色,得到的分析重点截然不同。

少样本示例(Few-shot Examples):在提示词中给出几个输入-输出的示例,模型会模仿这些示例的模式来处理新的输入。这在格式转换、风格迁移、分类等任务中效果显著。

思维链引导(Chain of Thought Prompting):前面在 Reasoning 部分讲过,通过"一步一步思考"的指令或分步推理的示例来提升模型的推理能力。

指令层次(Instruction Hierarchy):当提示词变得复杂时,需要用清晰的结构来组织不同层次的指令。常用的方式是用 XML 标签或 Markdown 标题来分隔不同的区块——背景信息、任务指令、输出格式要求、约束条件。

Prompt Engineering 的局限

Prompt Engineering 在单轮交互场景中已经足够强大。但在 Agent 场景中,它只是冰山一角。Agent 运行在多轮循环中,上下文在不断变化,影响模型行为的因素远不止你写的提示词——还包括工具返回的结果、历史对话的累积、上下文的总体结构。

这就引出了下一个层次的工程实践——Context Engineering。

Context Engineering:管理模型的全部输入

Context Engineering(上下文工程)是 Prompt Engineering 的自然演进。如果说 Prompt Engineering 关注的是"怎么写提示词",那么 Context Engineering 关注的是"如何管理模型在推理时看到的全部 token"。

什么是上下文

上下文不仅仅是你写的系统提示词和用户消息。它是模型在一次推理中能看到的所有信息的总和:

  • 系统提示词
  • 工具定义(每个工具的名称、描述、参数 schema)
  • MCP Server 提供的资源
  • 对话历史(用户消息 + 模型回复 + 工具调用记录)
  • 动态注入的外部数据(检索到的文档、文件内容、API 返回结果)

这些内容全部被序列化为 token,塞进模型的上下文窗口中。Context Engineering 的核心任务是:在有限的窗口中,放入最能帮助模型做出正确决策的内容。

上下文工程的核心原则

最小高信号集合:找到能达成目标的最小 token 集合,而非越多越好。每多加一个 token,都在消耗模型的注意力预算。如果一个 2000 token 的上下文能达到 95% 的效果,那 20000 token 的上下文大概率不会给你 99%,反而可能因为注意力稀释降到 90%。

位置敏感:模型对上下文不同位置的信息关注度不同。重要的指令和约束应放在系统提示词(上下文的最开头)和最近的用户消息(上下文的最末尾)。中间部分适合放参考材料和历史记录。

动态裁剪:在 Agent 的多轮执行过程中,上下文持续增长。需要主动管理——压缩早期的对话历史、移除已经完成的中间步骤、只保留与当前子任务相关的工具结果。

上下文工程 vs. 提示词工程

两者的关系是包含而非替代。提示词工程是上下文工程的一个子集——如何写好系统提示词,依然是上下文工程的基本功。但上下文工程的视野更广:

维度 Prompt Engineering Context Engineering
关注范围 系统提示词、用户消息 全部上下文 token
典型场景 单轮交互 多轮 Agent 执行
时间维度 静态编写 动态管理
核心挑战 怎么写清楚 怎么在有限空间内放对信息

Harness Engineering:管控整个 Agent 系统

如果说 Context Engineering 管理的是"模型看到什么",那么 Harness Engineering 管理的是"模型在什么环境中运行"。

Harness 这个词来自传统软件工程中的 Test Harness(测试工具),意思是在受控环境中运行和验证代码的基础设施。在 Agent 语境中,Harness 指的是围绕模型的整套运行时系统——它决定了 Agent 能用什么工具、怎么管理状态、出了错如何恢复、怎样在多个会话之间保持连续性。

Harness 包含什么

一个完整的 Agent Harness 通常包括以下组件:

  • Agent Loop 管理:控制循环的启停、设置最大迭代次数和超时时间
  • 工具注册与权限控制:哪些工具可用、哪些操作需要用户确认
  • 上下文生命周期管理:上下文的初始化、增长、压缩、跨会话传递
  • 状态持久化:任务进度、检查点、记忆的存储与恢复
  • 错误恢复机制:工具失败、模型幻觉、网络中断时的应对策略
  • 安全边界:防止模型执行危险操作(删除生产数据、推送未审核的代码)
  • 可观测性:日志、追踪、性能指标,用于调试和优化

Harness Engineering 的核心理念

Harness Engineering 的核心思想是:模型的能力已经足够强,但如果运行环境设计得不好,再强的模型也发挥不出来。

一个类比:F1 赛车引擎再强大,如果底盘不稳、刹车不灵、变速箱延迟高,比赛照样跑不出好成绩。Harness 就是 Agent 的底盘、刹车和变速箱。

具体来说,好的 Harness 设计体现在几个方面:

  1. 让模型做它擅长的事:模型擅长推理和决策,不擅长精确计算和状态管理。把计算和状态管理交给确定性的代码,让模型专注于判断和规划。

  2. 提供丰富的反馈回路:模型做了一个操作,Harness 应该把操作结果、副作用、警告信息都反馈给模型,让它有足够的信息做下一步决策。

  3. 设置合理的约束:完全放开所有权限,模型可能做出不可逆的破坏性操作;限制太死,模型又无法完成复杂任务。好的 Harness 在两者之间找到平衡——默认安全,但允许授权升级。

  4. 支持长时间运行:真实的 Agent 任务可能需要数十分钟甚至数小时。Harness 需要支持状态持久化和恢复,让 Agent 在上下文窗口用尽后能够通过摘要和检查点继续工作。

三种工程范式的关系

Prompt Engineering、Context Engineering 和 Harness Engineering 是三个逐层扩大的同心圆:

┌───────────────────────────────────────┐
│  Harness Engineering                  │
│  运行环境、工具、权限、状态、恢复      │
│                                       │
│  ┌───────────────────────────────┐    │
│  │  Context Engineering          │    │
│  │  全部上下文 token 的管理       │    │
│  │                               │    │
│  │  ┌───────────────────────┐    │    │
│  │  │  Prompt Engineering   │    │    │
│  │  │  提示词的编写与优化    │    │    │
│  │  └───────────────────────┘    │    │
│  └───────────────────────────────┘    │
└───────────────────────────────────────┘

写好提示词是基本功,管好上下文是进阶能力,设计好 Harness 是系统工程。三者缺一不可。

知识地图:概念之间的关联

回顾全文,所有概念可以按"层次"来组织理解:

基础设施层:LLM API 提供原始的生成能力,KV Cache 优化推理性能。这是一切的底层。

能力层:Tool Use 让模型能做事,Reasoning 让模型能思考,Planning 让模型能规划。这三个能力在 Agent Loop 中被循环调用。

组织层:Skills 封装专业能力,MCP 标准化外部连接,Memory 提供持久化记忆。这些机制让 Agent 的能力可以累积和复用。

架构层:Subagent 实现任务分解,Multi-Agent 实现协作分工。这是应对复杂任务的扩展手段。

工程层:Prompt Engineering 管理指令质量,Context Engineering 管理信息密度,Harness Engineering 管理运行环境。这三种工程实践覆盖了 AI 开发的全部表面积。

这些概念之间互相依赖、互相增强。理解任何一个概念,都需要知道它在整个体系中的位置。而将它们融会贯通,就是一个 AI 开发工程师的基本功。

━━━ fin ━━━

If you read this far — thank you.
Come tell me what you thought on X.