AI Agent 进入生产环境后,系统工程需要重做哪些功课

2026-10-02 34 预计阅读时间: 1 分钟
来源: infoq.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:11 分钟

QCon San Francisco 2026 将邀请来自 Airbnb、OpenAI、Netflix、Honeycomb 等工程组织的实践者,讨论当 AI Agent 承担更多任务后,生产系统该如何构建、运行与持续演进。值得关注的并不只是模型能力,而是一个更现实的问题:当软件从“接收请求并返回结果”变成“理解目标、选择工具、执行动作并反复修正”时,原有的可靠性边界也随之改变。

来源摘要没有披露具体演讲内容或厂商方案,因此下面不预测各家公司会发布什么,而是围绕这一主题,整理一套可以直接用于工程评审的生产化框架。

从确定性调用,转向受约束的行动循环

传统服务通常有相对清晰的调用链:客户端发起请求,服务验证参数,执行业务逻辑,再返回响应。Agent 系统则可能包含多个动态步骤:

  1. 接收用户目标与上下文;
  2. 由模型生成计划;
  3. 选择并调用搜索、数据库、工单或支付工具;
  4. 根据工具结果修改计划;
  5. 达到目标、触发审批,或者因预算耗尽而停止。

这意味着生产系统不能只监控一次 HTTP 请求是否成功,还要回答更多问题:Agent 为什么选择了这个工具?读取了哪些数据?一次任务执行了多少步?是否重复触发了有副作用的操作?模型或提示词升级后,成功率和成本发生了什么变化?

一个实用的设计原则是:把模型当作不稳定的决策组件,而不是拥有完整权限的业务后端。 模型可以提出动作,但真正执行动作的代码仍应经过权限、参数、预算和业务策略检查。

生产架构通常需要明确分开以下几层:

  • 规划层:模型把目标转化为下一步动作;
  • 工具层:对数据库、内部 API 和第三方服务提供结构化接口;
  • 策略层:判断动作是否允许,必要时要求人工确认;
  • 执行层:处理超时、重试、幂等和补偿;
  • 观测层:记录任务、模型调用、工具调用、成本与最终结果。

可观测性不能停留在日志和 Token 数量

Agent 任务可能返回了正确答案,却走了一条危险或昂贵的路径;也可能业务动作执行成功,但最终文本回复失败。因此,只统计状态码、延迟和 Token 消耗并不足够。

可以为每次任务建立一个 run_id,并把完整过程拆成多个 span:

agent.run
├── model.plan
├── policy.check
├── tool.get_order
├── model.replan
├── policy.check
└── tool.create_refund

每个 span 至少可以记录:

  • 模型、提示词和工具定义的版本;
  • 输入与输出的摘要或脱敏内容;
  • 工具名称、参数、耗时和错误类型;
  • 重试次数、Token 数量与估算成本;
  • 策略判断结果和人工审批状态;
  • 任务最终是成功、失败、中止还是部分完成。

敏感数据不能为了调试而无条件写入追踪系统。生产环境应对身份信息、支付数据和密钥进行脱敏,并配置保留周期与访问权限。对于高风险动作,审计记录还应与普通应用日志分开保存。

除了线上指标,还要建立固定评测集。每次修改模型、系统提示词、工具描述或检索逻辑时,重新运行同一批任务,比较任务完成率、错误工具调用率、平均步骤数、P95 延迟和单任务成本。这样才能把“模型感觉更聪明”转化为可回归的工程指标。

一个可运行的受限 Agent 工作流

下面是一个不依赖第三方库的最小示例。由于来源摘要没有提供具体 API,这段代码使用确定性的模拟规划器代替真实 LLM,重点展示工具白名单、步数限制、策略检查、幂等键、默认试运行和结构化审计。保存为 agent_demo.py 后即可运行。

import hashlib
import json
import sys
import time
import uuid

ORDERS = {
    "ORD-100": {"status": "paid", "amount": 39.90}
}
ALLOWED_TOOLS = {"get_order", "create_refund"}
MAX_STEPS = 4
PROCESSED_KEYS = set()

SYSTEM_PROMPT = """
You are an order-support planner.
Return structured tool calls only.
Never invent an order ID or refund amount.
Refunds require a paid order and must not exceed 50 USD.
Stop when the objective is complete or when a tool returns an error.
""".strip()


def audit(run_id, event, **fields):
    record = {
        "timestamp": round(time.time(), 3),
        "run_id": run_id,
        "event": event,
        **fields,
    }
    print(json.dumps(record, ensure_ascii=False))


def mock_plan(objective):
    # 生产环境可在这里调用 LLM,并使用 JSON Schema 校验返回值。
    # 本示例只支持一个固定订单,避免把模拟器误认为真实智能体。
    if "ORD-100" not in objective:
        return []
    return [
        {"tool": "get_order", "arguments": {"order_id": "ORD-100"}},
        {
            "tool": "create_refund",
            "arguments": {"order_id": "ORD-100", "amount": 39.90},
        },
    ]


def get_order(order_id):
    order = ORDERS.get(order_id)
    if not order:
        raise ValueError("order not found")
    return {"order_id": order_id, **order}


def create_refund(order_id, amount, idempotency_key, dry_run=True):
    order = ORDERS.get(order_id)
    if not order or order["status"] != "paid":
        raise ValueError("only paid orders can be refunded")
    if amount <= 0 or amount > order["amount"] or amount > 50:
        raise ValueError("refund rejected by policy")
    if idempotency_key in PROCESSED_KEYS:
        return {"status": "duplicate_ignored", "order_id": order_id}
    if dry_run:
        return {"status": "would_refund", "order_id": order_id, "amount": amount}
    PROCESSED_KEYS.add(idempotency_key)
    return {"status": "refunded", "order_id": order_id, "amount": amount}


def run_agent(objective, dry_run=True):
    run_id = str(uuid.uuid4())
    audit(run_id, "run_started", objective=objective, dry_run=dry_run)
    plan = mock_plan(objective)

    if not plan:
        audit(run_id, "run_stopped", reason="unsupported_objective")
        return

    for index, step in enumerate(plan, start=1):
        if index > MAX_STEPS:
            audit(run_id, "run_stopped", reason="step_budget_exceeded")
            return

        tool = step["tool"]
        arguments = step["arguments"]
        if tool not in ALLOWED_TOOLS:
            audit(run_id, "tool_blocked", tool=tool)
            return

        key_source = json.dumps(
            {"run_id": run_id, "tool": tool, "arguments": arguments},
            sort_keys=True,
        )
        idempotency_key = hashlib.sha256(key_source.encode()).hexdigest()
        audit(run_id, "tool_started", step=index, tool=tool, arguments=arguments)

        try:
            if tool == "get_order":
                result = get_order(**arguments)
            else:
                result = create_refund(
                    **arguments,
                    idempotency_key=idempotency_key,
                    dry_run=dry_run,
                )
            audit(run_id, "tool_finished", step=index, tool=tool, result=result)
        except Exception as exc:
            audit(run_id, "tool_failed", step=index, tool=tool, error=str(exc))
            return

    audit(run_id, "run_finished", status="completed")


if __name__ == "__main__":
    objective = " ".join(sys.argv[1:]) or "Check ORD-100 and refund it"
    run_agent(objective, dry_run=True)

运行命令:

python agent_demo.py "Check ORD-100 and refund it"

默认的 dry_run=True 不会真正改变状态。接入真实系统时,应把 mock_plan() 替换为带结构化输出约束的模型调用,把订单和退款函数替换为内部 API,同时保留策略校验。还应将幂等键写入持久化存储,而不是进程内集合;否则服务重启或水平扩容后无法阻止重复操作。

上线前应重点审查的边界

Agent 获得的工具越多,潜在故障组合就越多。上线前可以逐项检查:

  • 权限是否最小化:读取订单的工具不应自动获得退款权限;
  • 高风险动作是否分级:付款、删除、发布和权限变更应要求人工确认;
  • 是否限制循环:设置最大步骤数、总超时、Token 预算和工具调用预算;
  • 是否默认幂等:所有写操作都携带稳定的幂等键;
  • 是否防御提示注入:网页、邮件和文档中的文字只能作为数据,不能覆盖系统策略;
  • 是否支持回放:保存版本号与结构化事件,使失败任务能够离线复现;
  • 是否准备降级路径:模型不可用时转人工、返回只读结果,或使用确定性流程;
  • 是否单独评估成本:除了平均值,还要关注长尾任务与失控循环。

采用策略:先让 Agent 建议,再让它执行

更稳妥的落地顺序不是一次性开放所有业务能力,而是逐步扩大自主范围。第一阶段让 Agent 只生成建议;第二阶段允许调用只读工具;第三阶段开放可撤销、低金额或低影响的写操作;只有在评测、审计和人工审批机制成熟后,才考虑更高风险的自动执行。

QCon San Francisco 2026 所聚焦的“构建、运行和演进”恰好揭示了 Agent 工程的核心:模型只是系统的一部分。真正决定它能否进入生产环境的,是权限边界、执行控制、可观测性、评测体系和故障恢复能力。把这些基础设施先搭起来,Agent 才能从演示中的聪明助手,变成可运营、可追责的生产组件。


相关推荐