技术领导力 · 2025年12月9日 · 4 分钟

AI Agent 与企业微服务的融合之道

Agent 作为智能编排层如何与存量微服务体系握手——Agent Router、适配层、权限继承、事务补偿、灰度与熔断。

前面说了 Agent 系统的各种设计模式。现在的问题来了:这些 Agent 怎么和现有的企业微服务集成?

这不是理论问题。如果你在 B 端公司工作,你面对的是一套已经跑了好几年、几十个微服务、几百个 API 的系统。不能推倒重来,但要让 AI Agent 能"理解"和"操作"这套系统。

这篇文章讲的是——Agent 作为智能编排层,如何与存量微服务体系握手。

核心矛盾

Agent 和微服务的本质差异:

微服务:
  ┌─ 确定性:同一个输入永远产生同一个输出
  ├─ 同步/异步:明确的调用模式
  ├─ 强类型:接口契约严格
  └─ 状态:应用层管理状态(分布式缓存/数据库)

AI Agent:
  ┌─ 概率性:同样的问题可能产生不同的工具调用
  ├─ 多轮交互:一个任务可能产生 N 次服务调用
  ├─ 弱类型:输出是自然语言或半结构化 JSON
  └─ 状态:在上下文窗口中管理状态

把概率性的 Agent 接入确定性的微服务,这就是最大的挑战。不能简单地"把 Agent 当成另一个微服务"。

Agent Router vs API Gateway

传统微服务的入口是 API Gateway。Agent 接入后,Agent 的 Router 和原有 Gateway 怎么共存?

方案 A:Agent 直接调 Gateway(简单但不灵活)
  Agent → 调 Gateway → 转发到微服务
  问题:Agent 的输出不一定符合 Gateway 的输入格式
  问题:Agent 可能需要在多个服务间协调,Gateway 只管单一请求

方案 B:Agent Router 在 Gateway 之上(推荐)
  Agent Router → 适配层 → Gateway → 微服务
                    ↓
               Agent 直接读数据源(只读查询用直连)

方案 C:Agent Router 取代部分 Gateway 功能
  Agent Router 自带 Service Discovery + 负载均衡
  Agent 直接把工具映射到后端服务

方案 B 是现实中最常见的。Agent Router 不取代 Gateway,而是在它之上加一层适配。

用户消息
    │
    ▼
┌─────────────────────────┐
│    Agent Router          │
│  意图分析 → 任务分解     │
│                         │
│  ┌───────────────────┐  │
│  │  适配层            │  │
│  │  · 工具 → API 映射 │  │
│  │  · 参数转换         │  │
│  │  · 结果格式化       │  │
│  │  · 鉴权信息注入     │  │
│  └───────────────────┘  │
└──────────┬──────────────┘
           │
           ▼
   ┌───────────────┐
   │  API Gateway  │
   └───────┬───────┘
           │
     ┌─────┼─────┐
     ▼     ▼     ▼
   SvcA   SvcB  SvcC

适配层的核心工作是把 Agent 的"工具调用意图"转换为"微服务 API 调用"。

# 适配层示例:把 Agent 工具调用翻译为微服务 API 调用
class AdapterLayer:
    def __init__(self, gateway_url: str, auth_token: str):
        self.gateway = ApiGatewayClient(gateway_url, auth_token)
    
    async def execute(self, tool_call: ToolCall) -> ToolResult:
        """执行 Agent 的工具调用,背后映射到微服务 API"""
        mapping = self.tool_to_api.get(tool_call.name)
        if not mapping:
            return ToolResult.error(f"未找到工具映射: {tool_call.name}")
        
        # 1. 参数映射和转换
        api_params = self.map_params(
            source=tool_call.params,
            mapping=mapping.param_map
        )
        
        # 2. 鉴权信息注入
        api_params["x-auth-context"] = self.auth_token
        
        # 3. 调用微服务 API
        response = await self.gateway.call(
            method=mapping.http_method,
            path=mapping.http_path,
            params=api_params
        )
        
        # 4. 结果格式化为 Agent 可读的格式
        return ToolResult.success(
            self.format_result(response, mapping.format_type)
        )

这个适配层解决了三个问题:

  1. 参数隔离——Agent 看到的字段名可以跟微服务 API 的字段名不同
  2. 鉴权透明——Agent 不需要关心怎么鉴权,适配层统一注入
  3. 结果格式化——微服务返回的复杂 JSON 被格式化为 Agent 容易理解的文本

身份与权限继承

Agent 调用微服务时,权限怎么处理?Agent 应该使用用户的身份,而不是一个固定的"机器人账号"。

❌ 坏的实践:Agent 使用统一的机器人账号
  Agent(机器人账号)→ 查数据 → 即使无关也能查到
  → 用户能看到本不属于 TA 的数据
  
✅ 好的实践:Agent 冒充用户身份
  Agent(用户 A 的上下文)→ 携带用户 A 的 token
  → 微服务按用户 A 的权限返回数据
  → 用户只能看到 TA 有权限的数据

身份传递的实现:

class AgentIdentity:
    """Agent 调用时的身份上下文"""
    def __init__(self, user_id: str, roles: list[str], token: str):
        self.user_id = user_id
        self.roles = roles
        self.token = token

async def agent_handler(request: Request, user_input: str):
    # 从请求中获取用户身份
    identity = AgentIdentity(
        user_id=request.user.id,
        roles=request.user.roles,
        token=request.headers["authorization"]
    )
    
    # 把身份注入到 Agent 上下文
    agent = SmartAgent(identity=identity)
    response = await agent.chat(user_input)
    return response

这样做的好处:所有权限逻辑都在微服务层处理,Agent 不需要理解"这个角色能不能做这个操作"——它只需要在权限不足时,向用户解释为什么不能做。

服务的"声明"设计

在 Agent 接入微服务的过程中,最容易出现的问题是工具定义和实际 API 脱节——工具描述的"下单"接口和实际的下单接口参数不一样。

解决方案:让微服务自声明自己的 Agent 能力。

# 在每个微服务中增加一个 agent-manifest.yaml
service: order-service
version: v2

agent_capabilities:
  - name: query_order
    description: "查询订单状态和详情"
    http:
      method: GET
      path: /api/v2/orders/{order_id}
    parameters:
      order_id:
        type: string
        description: "订单号(格式: ORD-xxxxxxxx)"
    authentication: user_token
    risk_level: low

  - name: create_order
    description: "创建新订单"
    http:
      method: POST
      path: /api/v2/orders
    parameters:
      items:
        type: array
        description: "商品列表,每项包含 product_id 和 quantity"
      shipping_address:
        type: string
        description: "收货地址"
    authentication: user_token
    risk_level: high
    confirmation_required: true  # Agent 调用前需要用户确认

Agent 启动时扫描所有微服务的 manifest,自动注册工具。新增或修改服务时,不需要改 Agent 代码——改 manifest 就行。

这本质上是把 MCP 的"工具注册"概念应用到微服务治理中。微服务声明 Agent 能力,Agent 自动发现和注册,两边的维护解耦。

Agent 的事务补偿

Agent 调用多个微服务时,如果中间某个调用失败,需要做事务补偿。

Agent 的"事务":
  1. 创建订单(成功)
  2. 扣减库存(成功)
  3. 发送确认邮件(失败)
  
  恢复:第 3 步失败 → 给用户报错,标记订单为"待确认"
  → 不自动回滚 1 和 2(订单已生成,库存已扣)
  → 把异常留给人工处理

Agent 不适合做"强事务"(ACID 级别),因为 Agent 的状态管理基于上下文,而不是数据库事务。但可以通过可补偿操作来做"最终一致性"的事务管理:

class CompensationTracker:
    """Agent 调用微服务的补偿管理器"""
    def __init__(self):
        self.operations: list[Operation] = []
        self.compensations: list[Compensation] = []
    
    async def execute_with_compensation(self, tool_call, compensate_func):
        """执行一个可补偿的操作"""
        try:
            result = await tool_call.execute()
            self.operations.append(tool_call)
            self.compensations.append(compensate_func)
            return result
        except Exception as e:
            # 执行失败,回滚已成功的操作
            await self.rollback()
            raise e
    
    async def rollback(self):
        """按逆序执行补偿操作"""
        for comp in reversed(self.compensations):
            try:
                await comp()
            except Exception as e:
                # 补偿也失败了,记录到人工处理队列
                await self.manual_escalation(comp, e)

Agent 执行的事务补偿逻辑通常不是两阶段提交(2PC),而是Saga 模式——每步操作的补偿逻辑由业务代码定义。Agent 负责编排 Saga,不负责补偿的具体实现。

可观测性的打通

Agent 调用微服务后,链路追踪应该能贯穿两者。

传统微服务追踪:
  用户请求 → Gateway → SvcA → SvcB → 数据库
               ↑—— trace id: abc-123 ——↑

Agent 调用微服务追踪:
  用户消息 → Agent → 工具调用 → Gateway → SvcA → SvcB
               ↑—— trace id: xyz-789 ——↑

关键是把 Agent 的 trace id 传入微服务调用链:

class AgentTraceMiddleware:
    def __init__(self, agent_session_id: str):
        self.trace_id = f"agent_{agent_session_id}"
    
    def inject_to_api_call(self, headers: dict):
        """把 Agent trace id 注入到微服务调用的 header"""
        headers["x-trace-id"] = self.trace_id
        headers["x-caller-type"] = "ai-agent"
        return headers

这样当用户在 Agent 中问"昨天的报表怎么还没出来",如果 Agent 调用了报表服务,运维可以在 tracing 系统中看到完整的调用链路——从 Agent 到 Gateway 到具体哪个微服务。

灰度发布与熔断

Agent 调用微服务时,也要对 Agent 做灰度发布。

传统灰度:
  5% 的用户切到新版本 → 观察 → 切更多

Agent 灰度:
  5% 的 Agent 查询走新的工具定义 → 观察 → 扩大

熔断也类似——如果某个微服务不稳定,Agent 应该知道并切换策略:

class CircuitBreakerForAgent:
    def __init__(self, service_name: str):
        self.failures = 0
        self.threshold = 5
        self.state = "closed"
    
    async def call(self, tool_func):
        if self.state == "open":
            # 熔断已打开,告诉 Agent 换个方式
            return ToolResult.error(
                f"service_{tool_func.service}_unavailable",
                "该服务暂时不可用,请稍后再试或换一种查询方式"
            )
        
        try:
            result = await tool_func()
            self.failures = 0
            return result
        except Exception:
            self.failures += 1
            if self.failures >= self.threshold:
                self.state = "open"
            return ToolResult.error("service_error", "服务调用失败")

与传统熔断不同的是:Agent 收到"服务不可用"的错误后,应该尝试用其他工具或方式达成相同目标,而不是简单报错。

实施的演进路线

阶段 1:旁路(1-2 个月)
  Agent 只读查询微服务的数据
  不改写后端一行代码
  → 验证 Agent 与微服务集成的可行性

阶段 2:轻度集成(2-3 个月)
  Agent 可以调用部分只读接口
  引入适配层,Agent Router 旁路在 Gateway 之外
  → 验证适配层的稳定性和性能

阶段 3:核心操作(3-6 个月)
  Agent 可以调用写操作接口(下单、审批、配置变更)
  高风险操作加用户确认
  引入对应的补偿回滚机制
  → 验证事务一致性和安全性

阶段 4:深度集成(6-12 个月)
  微服务侧增加 agent-manifest.yaml
  自动化的工具注册和发现
  Agent trace 与微服务 trace 打通
  → 从"Agent 调微服务"进化到"Agent 和微服务共生"

两个关键点:

  1. 不要急着让 Agent 写数据。先读后写,先低风险后高风险。Agent 在只读模式下运行一个月,积累足够的性能数据和 bad case,再考虑开放写操作。

  2. 适配层是关键瓶颈。适配层做得好,Agent 和微服务各司其职;做得不好,Agent 频繁超时、参数错误、鉴权失败。花足够的时间做适配层的压力测试和边界测试,这个投入值得。

总结

Agent 与企业微服务的融合,不是把 Agent 当成"新型微服务",而是在 Agent 和微服务之间建立一个可靠的适配层。适配层负责:格式转换、鉴权传递、事务补偿、链路追踪、熔断降级。

技术本身已经有了——MCP 标准化工具,Agent Router 做路由,适配层做转换。真正的挑战在组织层面:后端团队需要接受 Agent 的"不确定性"——Agent 调 API 的方式可能不符合"标准用法",但它仍然需要第一线的支持。

这才是 AI Agent 落地中最容易被低估的问题。

继续阅读

评论