原文链接​:AI 小老六

在 AI 领域,每隔一段时间总会涌现出一些新名词:​Prompt Engineering​、​ReAct​、​Memory​、​Function Calling​、​MCP​、​Skill​、Harness Engineering 等等。很多开发者面对层出不穷的概念,难免会产生技术焦虑:“旧的还没学完,新的又来了,它们到底是在取代还是在补充?”

其实,如果我们抛开这些光鲜的词汇,从零开始亲手构建一个 ​**Agent(智能体)**​,就会发现它们的出现有着极强的内在逻辑和必然性。整个 Agent 工程的演进,本质上是在回答三个递进的问题:怎么和 LLM(大语言模型) 说话?让 LLM 看到什么?以及如何保障 LLM 稳定完成任务?

第一层:怎么和 LLM 说话(Prompt Engineering)

图:通过角色设定与指令设计,为 LLM 赋予特定能力

要利用大模型的能力,最基础的方式就是调用 API 发起一次网络请求。但在实际业务场景中(比如构建一个视频创作助手),单纯的闲聊毫无意义。我们需要为模型设定身份边界和能力范围,这正是 System Prompt 的用武之地。

通过在对话上下文中注入特定的角色设定,模型就能从一个“通用知识库”变成一个“专业助手”。这其实就是 Prompt Engineering 的核心工作——它解决的是“如何用自然语言为 LLM 编程”的问题。从角色设定、指令设计到输出格式约束,高质量的 Prompt 是 Agent 能否胜任特定场景的基石。

第二层:让 LLM 看到什么(Context Engineering)

仅仅能听懂话的 Agent 是没有记忆和行动能力的。为了让 Agent 能够持续产出并与外部世界交互,我们需要管理并扩展它的上下文,这就是 ​Context Engineering​。

赋予长期与短期记忆(Memory)

大模型的 API 接口是无状态的。要实现多轮对话,必须在工程层面对历史消息进行缓存和管理,并在每次请求时将相关上下文打包发给模型。

在工程实现中,这不仅是简单地将所有历史对话塞进请求里。随着对话的深入,我们需要考虑上下文窗口的限制,这就衍生出了短期记忆与长期记忆的划分,以及更复杂的上下文检索策略。

为 LLM 安装手脚(Tool)

图:为 Agent 配备工具,使其能够与外部世界交互

为了让 Agent 执行实际任务(如读写文件、执行脚本),我们需要为其配备“工具”。目前主流的做法是遵循 Function Calling 范式。

首先,在系统中定义好可用工具的 Schema:

```json
[
  {
    "name": "file_write",
    "description": "向指定路径写入文件内容",
    "parameters": {
      "type": "object",
      "properties": {
        "file": { "type": "string", "description": "目标文件路径" },
        "content": { "type": "string", "description": "要写入的内容" }
      },
      "required": ["file", "content"]
    }
  }
]

在调用大模型时,我们将这些工具定义一并传入。LLM 会自主判断是否需要调用某个工具,并返回标准的工具调用指令。随后,我们在工程代码中解析这些指令,执行对应的本地逻辑,再将执行结果反馈给 LLM。

自主循环思考(ReAct)

当 Agent 拥有了工具后,完成复杂任务往往需要多次试错和交互。这种“思考(Reason)- 行动(Act)- 观察 - 再思考”的交替循环,被称为 ​ReAct 模式​。

在代码层面,这表现为一个不断与 LLM 交互的循环结构,直到 LLM 判断任务已完成不再输出 Tool Call 为止:

```go
// 伪代码:ReAct 核心执行循环
for continueThinking {
    respMessage := CallLLM(messages, tools)
    toolCalls := respMessage.ToolCalls
    
    if len(toolCalls) > 0 {
        for _, call := range toolCalls {
            // 执行本地工具逻辑
            result := executeTool(call)
            // 将结果拼接入上下文,继续下一轮思考
            messages = append(messages, result)
        }
    } else {
        // 无需调用工具,任务完成
        continueThinking = false
    }
}

应对 Prompt 膨胀(Skill)

随着可用工具的增多,如果我们把所有工具的调用逻辑和使用规范都写在 System Prompt 里,会导致上下文严重膨胀,模型也极易出现“幻觉”或意图冲突。

为了解决这个问题,Skill 机制应运而生。它类似于分布式的 System Prompt:每个 Skill 都是一个独立的单元,包含特定场景的详细指令甚至工作流。

在执行时,业界通常有三种做法:

  • 共享上下文​:直接将 Skill 内容塞入主上下文,容易导致污染。
  • 隔离推理,部分共享​:拉起新实例独立推理 Skill,只将结果返回给主 Agent。
  • 完全隔离推理​:环境完全干净,Skill 无法访问主对话背景。

在多数复杂场景中,我们倾向于第二种方案。主 Agent 决定调用某个 Skill 时,系统会拉起一个独立的推理环境,仅加载该 Skill 的专属 Prompt 和必要的历史上下文,执行完毕后再将最终结果返回给主 Agent。

```go
// 伪代码:Skill 隔离执行逻辑
func ExecuteSkill(skillName string, history []Message) string {
    // 仅加载当前 Skill 的专属配置
    skillPrompt := loadSkillConfig(skillName)
    messages := append(history, skillPrompt)
    
    // 在独立沙箱中进行 ReAct 推理
    return runReActLoop(messages)
}

这大大降低了主 Agent 的心智负担,也让复杂任务的编排变得更加模块化。

第三层:保障稳定执行(Harness Engineering)

当我们把 Agent 投入到真实的生产环境中时,新的问题出现了:如何防止它执行高危命令(比如 rm -rf /)?如何保证在遇到网络抖动或工具报错时能够自动重试和恢复?

这就引出了 ​Harness Engineering​。它不是某项单一技术,而是指在 LLM 之外,所有为了保障 Agent 能够稳定、安全完成任务的系统性工程工作。

比如,针对执行环境的安全性,我们需要引入 Sandbox(沙箱) 机制,通过目录隔离或容器化技术,限制 Agent 对文件系统、网络和底层调用的访问权限。

图:通过沙箱隔离等机制保障 Agent 的安全与稳定执行

```go
// 伪代码:简单的路径沙箱隔离
func executeInSandbox(cmd string, rootPath string) Result {
    // 校验命令执行路径是否在允许的工作区内
    if !isPathAllowed(cmd.TargetDir, rootPath) {
        return Error("Permission Denied: 越权访问")
    }
    return runCommand(cmd)
}

工程定义的演进脉络

我们可以用一个生活化的例子来串联这几个阶段:

遇到的问题 解决方案示例 对应的工程阶段
如何与一个脾气古怪的老教授有效对话? 设定角色:让他扮演一位大厨,分享煮泡面的步骤。 Prompt Engineering
教授给的步骤需要煤气灶,但我家只有电磁炉。 提供上下文:递上一份“我家厨房物资清单”,让他因地制宜出方案。 Context Engineering
方案没问题,但我操作时忘了按电磁炉开关。 保障执行:提供一份防呆的 To-Do List,打勾确认每一步,并确保电磁炉不会漏电。 Harness Engineering

这些名词的演进,绝不是单纯的新技术替代旧技术,而是随着应用场景的深入,我们对 Agent 工程边界的不断扩展和重新定义。

结语:寻找 Agent 时代的“操作系统”

如果我们将眼光放得更长远一些,当前的 Agent 发展历程与计算机操作系统的演进惊人地相似。

图:Agent 工程向着类似操作系统的架构演进

计算机体系 Agent 体系
硬件资源 (CPU, 内存等) LLM 算力资源
操作系统 (OS) Agent 工程
应用软件 (Application) 工具 (Tool) / 技能 (Skill) / 工作流 (Workflow)

将 Agent 的现状与成熟的操作系统进行对比,从而发现当前 Agent 工程尚存的差距,也许 Agent 工程的下一步就在其中。

操作系统核心模块 Agent 工程现状
底层资源调度 (CPU 调度) 对 LLM 的调用缺乏标准的调度方案
内存管理 Memory 管理 (上下文管理)
进程模型 多任务、多会话之间缺乏标准的隔离与协作方案
系统调用 (Syscall) 工具调用 (Tool Call)
权限系统 仅有局部的权限管理 (Sandbox)
文件系统 文件系统访问
中断机制 缺乏系统性的中断、重试与恢复机制
可观测性 缺乏系统性的日志、追踪与调试方案

LLM 提供了底层的“算力”,而 Agent 工程正是为了将这种“概率性智能”转化为“确定性的程序交付”。未来的 Agent 工程,必然会向着包含标准资源调度、进程隔离、系统中断与恢复机制的完整 Agent Runtime 演进。

在这个将智能落地为生产力的过程中,我们还会听到更多既熟悉又陌生的“概念词”,但这正是技术浪潮向前推进的真实回响。只要把握住工程保障的本质,就能在纷繁的概念中看清未来的方向。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐