一、引言:范式跃迁的内在逻辑

引言

2022年至2026年间,大语言模型应用开发经历了一场从“提示工程”到“上下文工程”再到“Harness工程”的三阶段演进。这场演进的本质,是从优化单次模型调用的输入,升级为设计模型外围的工程化运行框架——包括执行环境、工具接口、上下文管理、任务编排、可观测性与治理。

如果说提示工程阶段,开发者扮演的是“咒语师”——通过精雕细琢每一行指令来引导模型输出;那么Agent编排阶段,开发者则升级为“指挥官”——需要设计系统架构、编排工具调用、管理多Agent协作。本文将聚焦这一演进的核心命题:如何将单轮对话扩展为可执行、可控制、可追踪的复杂任务流程,并通过代码示例展示具体的工程实践。

二、从静态提示到结构化提示工程

2.1 提示工程的局限

传统提示工程的核心问题是“一次性输入-输出”:开发者将所有任务描述、约束条件、示例一次性塞入上下文窗口,模型在单次推理中完成全部输出。这种模式在简单问答场景中尚可胜任,但面对需要多步推理、工具调用、动态决策的复杂任务时,暴露出三大缺陷:上下文窗口限制导致信息丢失、单次推理缺乏修正机制、静态提示难以应对动态需求。

2.2 结构化提示词设计

进入Agent编排时代,提示词本身也需要结构化。核心思路是将提示词拆解为三个层次:

  1. 系统提示词:角色定位、任务描述、输出格式约束
  2. 工具定义:可用工具的语义契约(名称、描述、参数Schema)
  3. 动态上下文:检索到的外部知识、对话记忆、任务状态

以下是一个结构化提示词模板的示例,用于指导Agent进行多工具调用:

SYSTEM_PROMPT_TEMPLATE = """
你是一个智能助手,可以通过调用工具完成复杂任务。

## 可用工具
{tools_description}

## 输出格式
你必须以JSON格式输出,包含以下字段之一:
- 如果需要调用工具:{{"action": "工具名称", "args": {{"参数名": "参数值"}}}}
- 如果任务已完成:{{"final": "最终回答"}}

## 任务
{user_query}

## 约束
1. 每次只能调用一个工具
2. 调用工具后,根据观察结果决定下一步
3. 不要编造信息,所有事实必须来自工具返回结果
"""

结构化提示词的价值在于:它为模型提供了明确的“行为契约”,使输出可解析、可验证,为后续的工具调用循环奠定基础。

三、核心架构:工具调用循环与ReAct模式

3.1 ReAct:推理与行动的闭环

ReAct(Reason + Act)是Agent编排最基础的执行模式。其核心循环为:思考(Thought)→ 行动(Action)→ 观察(Observation)→ 思考…… 。模型不再是“一次性输出答案”,而是在每一步中决定是调用工具还是给出最终回答。
3.1

以下是一个ReAct Agent的简化实现(Python),展示了工具调用循环的核心逻辑:

import json
from typing import List, Dict, Any
from openai import OpenAI

class ReActAgent:
    def __init__(self, tools: List[Dict[str, Any]], system_prompt: str):
        self.tools = tools
        self.system_prompt = system_prompt
        self.client = OpenAI()
        self.max_steps = 10

    def run(self, query: str) -> str:
        messages = [
            {"role": "system", "content": self.system_prompt},
            {"role": "user", "content": query}
        ]
        
        for step in range(self.max_steps):
            response = self.client.chat.completions.create(
                model="gpt-4o-mini",
                messages=messages,
                response_format={"type": "json_object"}
            )
            
            output = json.loads(response.choices[0].message.content)
            
            # 检查是否完成
            if "final" in output:
                return output["final"]
            
            # 执行工具调用
            if "action" in output:
                tool_name = output["action"]
                tool_args = output.get("args", {})
                
                # 查找并执行工具
                tool_result = self._call_tool(tool_name, tool_args)
                
                # 将观察结果追加到对话历史
                messages.append({"role": "assistant", "content": response.choices[0].message.content})
                messages.append({"role": "user", "content": f"Observation: {tool_result}"})
        
        return "任务超出最大步数限制"

    def _call_tool(self, name: str, args: Dict) -> str:
        # 根据工具名称路由到具体实现
        for tool in self.tools:
            if tool["name"] == name:
                return tool["handler"](**args)
        return f"Error: 未找到工具 {name}"

3.2 工具定义的标准化

为了让模型正确调用工具,需要将工具以“语义契约”的形式告知模型。OpenAI Agents SDK和MCP协议都采用了类似的工具描述方式:

# 工具定义示例:查询天气
weather_tool = {
    "name": "get_weather",
    "description": "查询指定城市的当前天气信息",
    "parameters": {
        "type": "object",
        "properties": {
            "city": {
                "type": "string",
                "description": "城市名称,如'北京'、'上海'"
            }
        },
        "required": ["city"]
    },
    "handler": lambda city: f"{city}今日天气:晴,25°C"  # 实际实现会调用API
}

工具定义的标准化使得模型与外部系统的交互变得可预测、可审计,是Agent编排从“Demo”走向“生产”的关键基础设施。

四、复杂任务编排:从单Agent到多Agent协作

4.1 提示链:单Agent的结构化推理

当任务具有明确的步骤依赖关系时,可以采用**提示链(Prompt Chaining)**模式:每一步的输出成为下一步的输入,通过结构化的进展建立分析深度。

以下是一个金融分析提示链的实现片段,展示了如何将“提取指标→基准分析→生成评论”三步串联:

from agent_framework.foundry import FoundryChatClient
import json

def execute_analysis_chain(financial_text: str):
    # Step 1: 提取关键财务指标
    extract_prompt = f"""
    从以下SEC文件中提取关键财务指标,返回JSON格式:
    {financial_text}
    输出格式: {{"revenue": xxx, "operating_margin": xxx, "debt_to_equity": xxx}}
    """
    metrics = json.loads(chat_client.complete(extract_prompt))
    
    # Step 2: 基准分析(依赖Step 1的输出)
    benchmark_prompt = f"""
    将以下指标与行业平均水平对比:
    {json.dumps(metrics)}
    返回百分位排名和行业上下文。
    """
    benchmark = chat_client.complete(benchmark_prompt)
    
    # Step 3: 生成投资评论(依赖Step 2的输出)
    comment_prompt = f"""
    基于以下基准分析,生成专业的投资评论:
    {benchmark}
    要求:客观、有数据支撑、包含风险提示。
    """
    return chat_client.complete(comment_prompt)

提示链的核心优势在于:每个步骤只需处理特定的上下文,降低了单次推理的复杂度,提高了输出的一致性。

4.2 多Agent协作:Agent-as-Tool模式

对于更复杂的任务,单个Agent难以同时掌握多个领域的专业知识。多Agent协作通过将任务分配给多个专家Agent,各自处理后再汇总结果,实现了“1+1>2”的效果。

OpenAI Agents SDK推荐的“Agent-as-Tool”模式,是由一个中心Agent将其他专家Agent作为工具调用,保持单一控制流的同时实现并行执行:

from agents import Agent, function_tool, Runner

# 定义三个专家Agent(简化为函数工具)
@function_tool
async def fundamental_analysis(company: str) -> str:
    """基本面分析:评估公司财务状况、管理层质量"""
    return f"{company}基本面分析结果:营收增长15%,利润率稳步提升..."

@function_tool
async def macro_analysis(query: str) -> str:
    """宏观经济分析:评估利率、通胀、政策环境"""
    return "当前宏观环境:利率处于下行周期,通胀可控..."

@function_tool
async def quantitative_analysis(symbol: str) -> str:
    """量化分析:技术指标、动量因子、估值模型"""
    return f"{symbol}量化信号:RSI=65,处于中性偏强区间..."

# 中心编排Agent
portfolio_manager = Agent(
    name="Portfolio Manager",
    instructions="""
    你是一位投资组合经理。接到用户的投资研究请求后:
    1. 并行调用三个专家工具:fundamental_analysis、macro_analysis、quantitative_analysis
    2. 综合三个专家的输出,生成一份完整的投资备忘录
    3. 备忘录需包含风险提示和投资建议
    """,
    tools=[fundamental_analysis, macro_analysis, quantitative_analysis],
    model_settings={"parallel_tool_calls": True}  # 关键:允许并行调用
)

# 执行
result = await Runner.run(portfolio_manager, "分析GOOGL的投资价值")

这种架构的核心优势在于模块化:每个专家Agent可以独立迭代优化,中心Agent只负责编排和综合,系统可扩展性极强。

4.3 分支链:基于条件路由的动态决策

在某些场景中,任务路径取决于中间步骤的输出。**分支链(Branching Chain)**模式允许根据前一步的结果动态选择后续执行路径:

def execute_branching_chain(financial_metrics: dict):
    # Step 1: 分类
    classification = classify_company(financial_metrics)
    
    # Step 2: 根据分类路由到不同分支
    if classification == "GROWTH_DRIVEN":
        return valuation_dcf_branch(financial_metrics)   # 折现现金流
    elif classification == "MATURE_EARNINGS":
        return valuation_multiples_branch(financial_metrics)  # 可比倍数
    else:
        return valuation_asset_branch(financial_metrics)  # 资产估值

分支链使得Agent编排能够适应输入数据的多样性,而不是对所有场景套用同一套流程。

五、工程实践:落地MCP与Skill驱动架构

5.1 MCP:工具接口标准化

MCP(Model Context Protocol)为Agent与外部工具之间的通信提供了标准协议。通过MCP,工具以统一的方式暴露给模型,模型无需关心工具的具体实现细节。

以下是一个MCP Server的简化实现,封装了公共假日查询API:

from mcp.server import Server, Tool
import httpx

@mcp.tool()
async def is_public_holiday(country_code: str, date: str) -> bool:
    """
    查询指定国家在指定日期是否为公共假日。
    
    Args:
        country_code: ISO国家代码,如'US'、'CN'
        date: 日期,格式'YYYY-MM-DD'
    
    Returns:
        是否为公共假日
    """
    async with httpx.AsyncClient() as client:
        response = await client.get(
            f"https://date.nager.at/api/v3/PublicHoliday/{date}/{country_code}"
        )
        return response.status_code == 200

MCP的核心价值在于解耦:工具开发者只需关注工具本身的实现,Agent开发者只需关注工具的语义契约,两者通过标准协议对接,互不干扰。

5.2 Skill:自然语言编写的“程序”

Skill是比普通提示词更高层次的抽象——它不是一次性的指令,而是用自然语言编写的、带执行逻辑的“程序”,明确告诉模型“按什么步骤组合哪些工具”。

以下是一个值班假日检查Skill的示例(Markdown格式):

# Skill: 值班假日检查

## 目的
判断当前值班工程师所在国家今天是否有公共假日,若有则列出其名下的高优先级问题。

## 可用工具
- get_current_oncall: 获取当前值班工程师信息
- is_public_holiday: 查询指定国家在指定日期是否为公共假日
- list_open_issues: 列出工程师名下的开放问题

## 执行步骤
1. 调用 get_current_oncall 获取值班工程师姓名和所在国家
2. 调用 is_public_holiday,传入国家代码和今天日期,判断是否为假日
3. 如果是假日,调用 list_open_issues,筛选P0/P1级别问题
4. 汇总结果,按指定模板输出

## 输出模板
值班正常/需备班:[姓名]([国家]),今天是[工作日/假日]。[若为假日,列出P0/P1问题]

Skill的本质是将Agent的“工作流”从代码中抽离出来,用自然语言编写,这使得非技术人员也能参与Agent行为的调优,同时也让Agent的行为更加透明、可审计。

六、效果优化与性能治理

6.1 上下文衰减的对抗策略

在长周期任务中,上下文信息会随交互轮次增加而“腐烂”——早期信息被遗忘,逻辑出现断裂。应对策略包括:

  • 结构化记忆管理:区分短期记忆(当前对话窗口)、长期记忆(向量数据库存储)、工作记忆(任务相关的知识图谱)
  • 里程碑检查点:在关键步骤固化阶段性成果到长期记忆
  • 主动澄清机制:当检测到上下文歧义时,Agent主动发起澄清对话

6.2 可观测性:Agent运行的“黑匣子”

Harness工程将“可观测性”视为独立架构层,要求捕获每一次工具调用、每一轮推理的轨迹、成本和失败信号。OpenAI Agents SDK提供了Traces功能,可实时监控Agent的每一步决策:

from agents import add_trace_processor, trace

# 开启链路追踪
add_trace_processor(BatchTraceProcessor(FileSpanExporter()))

with trace("investment_analysis"):
    result = await Runner.run(portfolio_manager, query)
    # 所有工具调用、Agent决策、耗时都会被记录

6.2

可观测性不仅是调试工具,更是持续优化的数据基础——通过分析失败模式,可以针对性地调整提示词、工具定义或编排逻辑。

七、结语

从提示工程到Agent编排的演进,本质上是AI应用从**“提示词调优”走向“系统工程”**的过程。开发者不再只是思考“怎么写提示词”,而是需要设计整个执行框架:工具如何定义和调用?上下文如何管理和注入?多Agent如何协作?任务如何追踪和验证?

这一转变也意味着开发者的角色升级——从“咒语师”变为“指挥官”,从“单次对话的设计者”变为“复杂任务系统的架构师”。掌握Agent编排能力,已成为AI应用开发者的核心竞争力。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐