一聚教程网:一个值得你收藏的教程网站

热门教程

使用Next.js构建AI Agent前端编排:从Plan到SSE Trace的完整实践

时间:2026-07-27 09:25:49 编辑:袖梨 来源:一聚教程网

用 Next.js 搭建 AI Agent 前端编排:从 Plan 到 SSE Trace 的完整实践

前言:为什么需要「前端编排」视角的 Agent 项目?

过去两年,AI Agent 的讨论大多集中在后端:LangChain、AutoGPT、Function Calling……但当你真正做一个面向用户的 Agent 产品时,前端才是用户感知 Agent「在思考、在行动」的地方。

用户并不关心你的 Planner 用了哪个模型,他们关心的是:

  • Agent 现在在干什么?(规划中?调工具?生成答案?)
  • 调了哪些工具?参数是什么?返回了什么?
  • 整个过程花了多少步、多少毫秒?

Home Agent 就是一个专门回答这些问题的 学习型 Next.js 项目。它不追求生产级 Agent 框架的完备性,而是把 Agent 循环设计、SSE 流式协议、编排 UI 状态机 三件事拆得足够清晰,方便阅读和二次扩展。

项目概览

维度说明
定位AI Agent 前端编排学习项目
核心页面/agents/ 自动跳转)
核心 APIPOST /api/agent(SSE trace 流)
内置工具search_notes · calculate · current_time
技术栈Next.js 16 · React 19 · TypeScript · Tailwind CSS 4 · Prisma · PostgreSQL

能力一览

工具说明
search_notes检索知识库笔记(PostgreSQL + pg_trgm 模糊搜索,无 DB 时内存回退)
calculate安全数学表达式求值
current_time返回服务器本地时间

架构总览

flowchart LRUI["/agents 页面"] --> API["POST /api/agent"]API --> Loop["runAgentLoop"]Loop --> Plan["planAgentStep"]Plan -->|tool| Tools["executeAgentTool"]Tools --> LoopPlan -->|answer| SSE["SSE events"]SSE --> UI

一句话总结数据流:用户输入 → Agent 循环规划 → 按需调用工具 → 每步产出 trace 事件 → SSE 推流 → 前端 Hook 解析 → 编排 UI 实时更新。

快速上手

环境要求

  • Node.js 22(见 .nvmrc
  • pnpm 9
  • Docker(用于 PostgreSQL)

启动步骤

pnpm installcp .env.example .envdocker compose up -d dbpnpm db:setuppnpm dev

浏览器访问 http://localhost:3000/agents。

可选:接入 Ollama

ollama pull llama3.2ollama serve

.env 默认已配置 Ollama 的 OpenAI 兼容接口。若未配置 LLM 或设置 LLM_DISABLED=1,系统会自动回退到规则规划器——这在 CI 和离线学习场景下非常实用。

核心设计:Agent 主循环

Agent 的心脏在 src/lib/agent/run-loop.ts。它实现了一个 async generator,每推进一步就 yield 一个 trace 事件:

export async function* runAgentLoop(message: string,options: { signal?: AbortSignal } = {},): AsyncGenerator<AgentTraceEvent> {// ...while (steps < maxSteps) {const { plan, mock } = await planAgentStep(message, prior);yield { type: "plan", plan };if (plan.action === "answer") {yield { type: "answer", text: plan.answer, mock };yield { type: "done", steps, toolCalls, totalMs };return;}yield { type: "tool_call", tool: plan.tool, args: plan.args };const result = await executeAgentTool(plan.tool, plan.args);yield { type: "tool_result", tool: plan.tool, output: result.output };}}

循环的关键设计决策

  1. 步数上限:通过 AGENT_MAX_STEPS 控制(默认 4,上限 12),防止无限循环。
  2. AbortSignal 支持:请求中断时立刻抛出,前端「停止」按钮可生效。
  3. 步数耗尽兜底:达到上限时,基于已有工具结果合成最终回答,而不是直接报错。
  4. 性能埋点:每步产出 step_metric 事件,记录 planMstoolMstotalMs

这种 generator + yield 事件 的模式,比「先跑完再返回 JSON」更适合流式 UI——后端每推进一步,前端就能更新一次。

规划器:LLM 与规则回退的双轨设计

src/lib/agent/planner.ts 负责「这一步该调工具还是直接回答」。

LLM 规划路径

当 Ollama 或 OpenAI 兼容 API 可用时,规划器要求模型输出结构化 JSON:

const response = await client.chat.completions.create({model,temperature: 0.1,response_format: { type: "json_object" },messages: [{ role: "system", content: getPlannerSystem() },{ role: "user", content: JSON.stringify(userPayload) },],});

System Prompt 明确约束输出格式——要么 { action: "tool", tool, args, reasoning },要么 { action: "answer", answer, reasoning }。LLM 返回的 JSON 还会经过 Zod 校验(planner-schema.ts),无效则回退。

规则规划器(Mock Planner)

src/lib/agent/planner-mock.ts 用关键词匹配实现零依赖规划:

  • 含「笔记 / 搜索 / 架构」→ 调 search_notes
  • 含算式 → 调 calculate
  • 含「几点 / 时间」→ 调 current_time
  • 已有工具结果 → 合成最终回答

if (wantsSearch && !hasTool("search_notes")) {return {action: "tool",tool: "search_notes",args: { query: "..." },reasoning: "问题涉及知识库,先检索笔记",};}

为什么需要双轨?

  • 本地学习时不必装 LLM,打开页面就能跑通全流程
  • CI 流水线不依赖外部 API,测试稳定可重复
  • 对比 LLM 规划与规则规划的行为差异,是学习 Agent 设计的捷径

SSE 流式协议:前后端的契约

POST /api/agent 返回 Content-Type: text/event-stream。每个事件块格式:

event: plandata: {"type":"plan","plan":{"action":"tool","tool":"search_notes",...}}

事件类型

type说明
trace循环阶段日志(start / plan / limit
plan规划器输出
tool_call即将执行的工具及参数
tool_result工具返回文本
step_metric单步耗时(planMs / toolMs / totalMs)
answer最终回答(mock: true 表示规则回退)
done循环结束统计
error错误信息

API Route 实现

src/app/api/agent/route.ts 把 async generator 桥接到 Web Streams API:

const stream = new ReadableStream({async start(controller) {for await (const trace of runAgentLoop(body.message, {signal: request.signal,})) {controller.enqueue(encoder.encode(encodeSseEvent(trace.type, trace)));}controller.close();},});return new Response(stream, {headers: {"Content-Type": "text/event-stream; charset=utf-8","Cache-Control": "no-cache, no-transform",Connection: "keep-alive",},});

SSE 编码/解码被抽成独立模块 src/lib/sse.ts,前后端共用同一套解析逻辑,避免协议漂移。

curl 调试

无需打开浏览器,直接用 curl 观察事件流:

curl -N -X POST http://localhost:3000/api/agent -H "Content-Type: application/json" -d '{"message":"计算 1+2"}'

前端编排 UI:Hook + 状态机

useAgentStream Hook

src/hooks/use-agent-sse.ts 是前端消费 SSE 的核心。它用 fetch + ReadableStreamnn 分块解析,维护以下状态:

状态用途
linesTrace 面板的事件行
phase工作流阶段(idle / planning / tool / answering / done / error)
finalAnswer最终回答文本
stepMetrics每步耗时数据
stats总结(步数、工具调用次数、总耗时)
isMock是否使用了规则规划器

const { run, stop, running, lines, finalAnswer, stats, stepMetrics } =useAgentStream({onEvent: (event) => console.log(event),});await run("现在几点?");

Hook 内部把原始 SSE 事件映射为人类可读的 Trace 行,例如:

  • plan调用 search_notes · 问题涉及知识库,先检索笔记
  • tool_call→ calculate({"expression":"1+2"})
  • tool_result → 工具输出(检索结果还会标注命中条数)

编排 UI 组件

src/components/agent-orchestrator.tsx 把 Hook 状态组装成完整的编排界面:

组件职责
AgentWorkflowBar工作流进度条(规划 → 工具 → 回答)
AgentTracePanel逐步展开的 trace 日志
AgentStepMetrics每步耗时可视化
AgentFinalAnswer最终回答展示(含 mock 标记)
IntelligenceLearningPanel进阶:编排偏好与学习面板

快捷 Prompt 与工具目录

页面内置快捷按钮(agent-quick-prompts.ts)和工具目录展示(tool-catalog.ts),降低首次体验门槛。用户点一下「计算 100 * 0.15 + 20」或「现在几点?」,就能立刻看到 Agent 循环的完整 trace。

工具层:从声明到实现

每个 Agent 工具需要保持四处一致(详见 docs/add-a-tool.md):

  1. types.ts — 工具名类型
  2. tool-catalog.ts — UI 展示文档
  3. tools.ts — 执行逻辑
  4. planner.ts + planner-schema.ts — 告诉规划器工具存在

search_notes 为例,底层调用 src/lib/note-search.ts

  • 有 PostgreSQL 时,使用 pg_trgm 扩展做模糊搜索
  • 无 DB 连接时,回退到内存中的种子数据

calculate 工具则通过字符白名单 + new Function 做受限求值——学习项目可以这么写,生产环境需要沙箱方案。

进阶模块:编排偏好与学习面板

src/lib/front-intelligence-preferences.ts 演示如何把用户偏好注入 prompt,并通过 localStorage 持久化:

  • 风格:风险优先 / 代码优先 / 步骤优先
  • 深度:简短 / 完整
  • 指标:是否在回答中补充量化指标

这是可选进阶模块,不影响 Agent 核心循环。但它展示了真实产品中常见的模式——前端偏好 → prompt 增强 → Agent 行为微调。

数据层:Prisma + PostgreSQL

项目使用 Prisma 管理数据模型,Docker Compose 一键启动 PostgreSQL 16:

services:db:image: postgres:16-alpineenvironment:POSTGRES_DB: home_agentPOSTGRES_USER: postgresPOSTGRES_PASSWORD: postgresports:- "5432:5432"

pnpm db:setup 会执行 prisma db push + prisma db seed,写入示例笔记供 search_notes 检索。

健康检查端点 GET /api/health 会报告 DB 连接、LLM 配置、pg_trgm 扩展是否可用——前端 Header 的 Badge 就是消费这个接口。

测试与 CI:无 LLM 也能跑通

Home Agent 的测试策略值得借鉴:

层级工具说明
单元测试Vitest规划器 schema、SSE 解析、工具逻辑、run-loop
API 冒烟pnpm smoke对运行中的 dev server 发 SSE 请求
E2EPlaywright完整页面交互流程

CI 中设置 LLM_DISABLED=1,确保流水线不依赖外部 LLM 服务。规则规划器让「Agent 循环 → SSE → 前端 UI」这条链路在每次 PR 中都被验证。

扩展指南:添加你自己的 Tool

假设要添加一个 echo 工具(回显用户输入),按以下清单操作:

  • types.ts — 加入 "echo" 工具名
  • tool-catalog.ts — 注册 UI 文档
  • tools.ts — 实现 case "echo"
  • planner-schema.ts — Zod 枚举加入 "echo"
  • planner.ts — system prompt 描述新工具
  • (可选)planner-mock.ts — 关键词规则
  • (可选)agent-quick-prompts.ts — 快捷按钮

验证:

pnpm typecheck && pnpm testpnpm dev # 另一终端pnpm smoke

/agents 输入「请 echo 你好」,观察 trace 是否出现 tool_call → echo → tool_result

安全说明(学习项目 vs 生产环境)

Home Agent 刻意保持简单,以下限制请在生产使用前知晓:

项目现状生产建议
API 鉴权/api/agent 无鉴权加 API Key / Session / Rate Limit
calculate 工具new Function 受限求值独立沙箱(VM / WASM)
LLM 输出Zod 校验 + 回退加重试、超时、内容过滤
SSE 连接无心跳加 keep-alive / reconnect 策略

推荐阅读顺序

如果你想深入源码,建议按此顺序阅读:

  1. src/lib/agent/types.ts — 事件与规划类型定义
  2. src/lib/agent/run-loop.ts — Agent 主循环
  3. src/lib/agent/planner.ts + planner-mock.ts — LLM / 规则双轨规划
  4. src/app/api/agent/route.ts — SSE 出口
  5. src/hooks/use-agent-sse.ts — 前端消费 Hook
  6. src/components/agent-orchestrator.tsx — 编排 UI 组装

配套文档:

  • 架构说明
  • SSE 协议
  • 如何新增 Tool

总结

Home Agent 用约 80 个源文件,演示了 AI Agent 前端编排的核心链路:

几个值得带走的实践:

  1. Async Generator 驱动 SSE — 后端每推进一步,前端就能更新 UI,用户体验远好于「等全部跑完」。
  2. LLM + 规则双轨规划 — 开发、测试、演示不绑死外部 API,降低学习和 CI 成本。
  3. Hook 封装 SSE 消费 — 把协议解析、状态映射、Abort 控制集中在一处,UI 组件只关心展示。
  4. 类型 + Zod 双保险 — 规划器输出、SSE 事件、API 入参全链路类型安全。

如果你正在学习 Agent 或准备做一个带编排 UI 的 AI 产品,不妨 clone 这个项目,从添加一个新 Tool 开始动手。

git clone https://github.com/jiaxiantao/home-agent.gitcd home-agentpnpm install && cp .env.example .envdocker compose up -d db && pnpm db:setup && pnpm dev

项目地址

项目链接
GitHub 仓库github.com/jiaxiantao/…
Issue / 讨论github.com/jiaxiantao/…
CI 状态github.com/jiaxiantao/…

git clone https://github.com/jiaxiantao/home-agent.git

参考文章

AI Agent 与工具调用

  • ReAct: Synergizing Reasoning and Acting in Language Models — Agent「推理 + 行动」循环的经典论文,Plan → Tool → Answer 的思想来源之一
  • OpenAI — Function calling — 结构化工具调用的官方指南,与项目中 Planner 输出 JSON 的模式一脉相承
  • Anthropic — Tool use — Claude 工具调用文档,对比不同厂商的 Function Calling 设计
  • LangChain — Agents — Agent 抽象与 Tool Loop 的概念说明(Python 生态,但循环模型通用)

流式输出与 SSE

  • MDN — Server-sent events — SSE 标准与浏览器 EventSource API 说明
  • MDN — Using server-sent events — SSE 事件格式、重连与实战要点
  • Next.js — Route Handlers — App Router 下的 API Route 与 Response 流式返回
  • Next.js — Streaming — Next.js 流式渲染与 Suspense 概念(与 SSE trace 推送互补)

前端与工程实践

  • React — useEffect — Hook 副作用与清理(AbortController 模式参考)
  • Prisma — Getting started — 本项目 ORM 与数据库迁移
  • PostgreSQL — pg_trgm — search_notes 模糊检索依赖的扩展文档

参考书籍

书名作者与本项目的关联
AI EngineeringChip HuyenLLM 应用架构、RAG、Agent 编排与工程化落地
Building LLM AppsValentina Alto从零构建 LLM 应用,涵盖 Tool Calling 与对话流程设计
Designing Data-Intensive ApplicationsMartin Kleppmann流式传输、事件驱动、数据一致性——理解 SSE 推送的底层视角
Designing Machine Learning SystemsChip HuyenML 系统工程思维,对 Agent 监控、回退策略有启发
JavaScript: The Definitive GuideDavid FlanaganAsync Generator、ReadableStream 等 JavaScript 异步机制参考

热门栏目