让 AI 前端跟着任务变化:用 AG-UI、智能体群与 Nova Act 打通 AWS 工作流

2026-09-29 36 预计阅读时间: 1 分钟
来源: aws.amazon.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 分钟

传统聊天界面假设模型最终会返回一段文本,但真实的智能体任务并没有如此规整:一次运行可能生成表格,下一次可能要求用户确认,再下一次又会调用多个专业智能体,甚至进入没有 API 的旧系统完成操作。固定的消息气泡很快就会成为瓶颈。

一种更实用的设计,是把智能体运行过程转换成前端可消费的事件流:AG-UI 负责界面与智能体之间的协议边界,Strands Agents SDK 的 swarm 模式组织多智能体协作,Amazon Nova Act 则负责处理只能通过网页界面访问的遗留系统。三者解决的是不同问题,不应被揉成一个不可拆分的“大代理”。

界面不再等待一段最终答案

自适应 AI 界面的关键,不是让模型直接输出 HTML,而是让后端发布结构化事件。前端根据事件类型选择安全、可测试的组件,例如:

  • RUN_STARTED:创建新的任务运行视图;
  • STEP_STARTED:显示当前由哪个智能体处理什么工作;
  • UI_COMPONENT:渲染表格、指标卡、审批框或引用列表;
  • STEP_FINISHED:记录步骤结果和证据;
  • RUN_FINISHED:关闭流并展示最终状态。

这里的核心边界是:智能体决定表达意图,前端决定如何渲染。后端可以要求展示一张订单表,但不应发送任意 JavaScript。这样既能适应可变输出,也能保留浏览器端的安全控制、设计规范和无障碍能力。

AG-UI 可以承担这个事件边界。接入真实实现时,应使用对应 SDK 定义的标准事件和状态同步机制,而不是自行长期维护一套相似但不兼容的协议。

三层协作,各自保留清晰职责

可以把完整链路拆成三层:

  1. 交互层:AG-UI 事件连接前端和智能体运行时,持续传递状态、消息、工具结果与界面更新。
  2. 推理层:Strands Agents SDK 的 swarm 模式将任务交给多个专业智能体,例如规划、数据查询、风险审查和结果汇总。
  3. 执行层:当目标系统没有 API 时,由 Nova Act 在受控浏览器环境中完成必要的界面操作。

这种拆分对可解释性尤其重要。前端不应该只显示“智能体正在思考”,而应展示可审计的业务动作:

协调智能体:将订单核验任务拆为三个步骤
订单智能体:读取订单 1042,金额为 860 元
风控智能体:发现收货地址在下单后发生变更
审批步骤:等待人工确认是否继续退款

需要避免泄露模型的私有推理过程。可解释性应来自任务计划、代理交接、工具调用、数据来源和审批记录,而不是暴露完整思维链。

一个可运行的动态界面实验

下面的示例不依赖真实模型,可以直接运行,用来验证“事件驱动 UI”是否适合现有前端。它采用一个简化的、与 AG-UI 思路相近的事件信封;其中的事件名称只是演示约定,接入生产环境时需要替换为实际 AG-UI SDK 的类型。

先创建环境:

python -m venv .venv
source .venv/bin/activate
pip install fastapi 'uvicorn[standard]'

将以下内容保存为 app.py:

import asyncio
import json

from fastapi import FastAPI, Query
from fastapi.responses import HTMLResponse, StreamingResponse

app = FastAPI()


def encode_sse(event: dict) -> str:
    return f'data: {json.dumps(event, ensure_ascii=False)}\n\n'


@app.get('/events')
async def events(task: str = Query(default='检查订单 1042')):
    async def generate():
        yield encode_sse({
            'type': 'RUN_STARTED',
            'task': task,
        })
        await asyncio.sleep(0.4)

        yield encode_sse({
            'type': 'STEP_STARTED',
            'agent': 'coordinator',
            'label': '分析任务并选择专业智能体',
        })
        await asyncio.sleep(0.5)

        if '订单' in task:
            component = {
                'kind': 'table',
                'title': '订单核验结果',
                'columns': ['订单号', '状态', '金额'],
                'rows': [['1042', '等待审批', '¥860']],
            }
        else:
            component = {
                'kind': 'metric',
                'title': '任务处理进度',
                'value': '75%',
            }

        yield encode_sse({
            'type': 'UI_COMPONENT',
            'component': component,
        })
        await asyncio.sleep(0.4)

        yield encode_sse({
            'type': 'RUN_FINISHED',
            'status': 'completed',
        })

    return StreamingResponse(generate(), media_type='text/event-stream')


@app.get('/', response_class=HTMLResponse)
def index():
    return '''
<!doctype html>
<html lang='zh-CN'>
<head>
  <meta charset='utf-8'>
  <title>Adaptive Agent UI</title>
  <style>
    body { font-family: sans-serif; max-width: 760px; margin: 40px auto; }
    section { border: 1px solid #ddd; border-radius: 10px; padding: 16px; margin: 12px 0; }
    pre { background: #f6f8fa; padding: 12px; overflow: auto; }
  </style>
</head>
<body>
  <h1>智能体任务</h1>
  <input id='task' value='检查订单 1042'>
  <button onclick='startRun()'>运行</button>
  <div id='output'></div>

  <script>
    function addCard(title, content) {
      const section = document.createElement('section');
      const heading = document.createElement('h2');
      const body = document.createElement('pre');
      heading.textContent = title;
      body.textContent = content;
      section.append(heading, body);
      document.querySelector('#output').append(section);
    }

    function startRun() {
      const output = document.querySelector('#output');
      output.replaceChildren();
      const task = document.querySelector('#task').value;
      const stream = new EventSource('/events?task=' + encodeURIComponent(task));

      stream.onmessage = message => {
        const event = JSON.parse(message.data);

        if (event.type === 'STEP_STARTED') {
          addCard(event.agent, event.label);
        }

        if (event.type === 'UI_COMPONENT') {
          const component = event.component;
          addCard(component.title, JSON.stringify(component, null, 2));
        }

        if (event.type === 'RUN_FINISHED') {
          addCard('运行状态', event.status);
          stream.close();
        }
      };

      stream.onerror = () => stream.close();
    }
  </script>
</body>
</html>
'''

启动服务:

uvicorn app:app --reload

打开 http://127.0.0.1:8000。输入包含“订单”的任务时,后端会要求前端展示表格;输入其他内容时,则会返回指标组件。虽然这是一个最小实验,但它验证了重要的架构选择:界面组件由事件数据驱动,而不是绑定某一种固定回答格式。

把 swarm 与旧系统执行接进来

进入真实项目后,可以让 swarm 中的协调智能体只负责分解和委派任务,由专业智能体产生结果。每次代理交接都映射成 AG-UI 事件,例如:

用户请求
  -> 协调智能体制定计划
  -> 数据智能体查询业务数据
  -> 风控智能体检查限制条件
  -> 审批组件等待用户确认
  -> Nova Act 操作无 API 的后台页面
  -> 汇总智能体生成结果与证据

Nova Act 更适合放在执行链路末端,而不是让它承担所有信息检索。浏览器自动化通常比正式 API 更容易受到页面布局、登录状态、弹窗和网络延迟影响。只有目标系统确实缺少稳定 API 时,才值得承担这部分成本。

可以为浏览器执行层增加一份独立策略。下面是可以改造的项目级配置示例,并非 Nova Act 的原生配置格式:

automation_policy:
  allowed_hosts:
    - legacy-admin.example.internal
  blocked_actions:
    - delete-account
    - export-all-customers
  require_human_approval:
    - issue-refund
    - change-payment-details
  redact_fields:
    - password
    - access_token
    - card_number
  limits:
    max_steps: 25
    timeout_seconds: 120

执行危险动作前,后端应发送审批事件并暂停工作流。用户确认后再签发一次性授权,而不是仅依赖提示词中的“请谨慎操作”。

上线前需要守住的边界

这套架构的价值来自解耦,但也引入了更多运行状态。落地时应重点检查:

  • 协议兼容性:用正式 AG-UI 类型替换实验事件,并对协议版本进行协商。
  • 可恢复性:为每次运行、步骤和工具调用分配稳定 ID,断线重连后能够恢复状态。
  • 可解释记录:保存代理交接、工具参数摘要、数据来源和审批人,不保存不必要的私有推理。
  • 组件白名单:前端只渲染已注册组件,所有文本都按不可信输入处理。
  • 浏览器隔离:Nova Act 使用独立会话、最小权限账号、域名白名单和完整审计日志。
  • 幂等控制:退款、提交和更新等动作必须带幂等键,避免重试造成重复执行。
  • 降级路径:swarm 或浏览器自动化失败时,应允许人工接管,而不是无限自主重试。

最稳妥的采用顺序,是先用 AG-UI 统一单智能体的事件输出,再引入可观察的 swarm 协作,最后只为确实没有 API 的少数步骤接入 Nova Act。这样每增加一层能力,都能单独度量它带来的收益、延迟和风险。


相关推荐