Agentic Application Stack
Agentic 应用的技术栈分层:从用户界面到 Agent 引擎,每一层的职责、选型和工程边界。
#synthesis
#evergreen
#ai
#architecture
[!info] related notes
- 所属 MOC: AI Agent Application MOC
- 核心概念: AI Agent Application
- 各层入口: Chat UI, Backend For Frontend, AI Service
Agentic Application Stack
一句话定义
本文用 React + Go + Python 说明交互、业务编排、Agent 执行和基础设施的分工。这是一种可选组合,不是构建 Agent 的最低依赖,也不是本仓库的已部署架构。通用职责与演进取舍见 agent-project-system-architecture。
它解决什么问题
很多团队在构建 AI Agent 应用时遇到的问题不是”能不能调通 API”,而是:
- 前端和后端的职责怎么划分?谁管 SSE?
- Python AI Service 需要直接查业务数据库吗?
- 工具注册和执行放在哪一层?
- 上下文组装在 Go 端还是 Python 端?
- 流式事件的协议怎么定义?
技术栈分层不清晰,会导致代码散落、职责混乱、难以维护。
核心原理
四层架构
┌─────────────────────────────────────────────────────┐
│ Layer 1: 用户交互层 (React) │
│ Chat UI · Tool Call UI · Approval UI · Artifact UI │
├─────────────────────────────────────────────────────┤
│ Layer 2: 业务编排层 (Go) │
│ Session · Message · Context Builder · SSE Gateway │
├─────────────────────────────────────────────────────┤
│ Layer 3: Agent 引擎层 (Python) │
│ Agent Runtime · Tool Registry · RAG · Memory │
├─────────────────────────────────────────────────────┤
│ Layer 4: 基础设施层 │
│ LLM Provider · Vector DB · Database · Object Store │
└─────────────────────────────────────────────────────┘
各层职责边界
| 层 | 核心职责 | 不该做的事 |
|---|---|---|
| React 前端 | 渲染、交互、客户端状态与校验 | 不承载唯一业务授权,不暴露服务端模型凭据 |
| Go 后端 | 此方案中负责业务状态、上下文和授权 | 不把模型输出直接当成获准业务结果;语言本身不禁止检索或编排 |
| Python AI Service | 此方案中负责推理、工具执行、RAG、记忆 | 校验服务身份与资源授权,不绕过业务拥有方直接改写其数据 |
| 基础设施 | 提供模型调用、存储与计算能力 | 不替代应用定义的事实与授权边界 |
层间通信协议
React ←→ Go: HTTP REST + SSE (流式)
Go ←→ Python: gRPC 或 HTTP + SSE (流式)
Python ←→ LLM: 各 provider 的 HTTP API,经适配器处理格式与能力差异
典型工程实现
一个请求的完整数据流
用户输入 "分析最近的销售趋势"
│
▼
[React] POST /api/chat/message
│
▼
[Go] Auth → Create Turn → ContextBuilder.Build()
│
▼
[Go] POST /ai-service/chat (携带 Context Bundle)
│
▼
[Python] AgentRuntime.start_run(context)
│
├── LLM 推理 → 决定调用 query_database
├── ToolExecutor → 经授权的业务查询接口/只读数据视图
├── 结果回传 LLM
├── LLM 推理 → 决定调用 create_chart
├── ToolExecutor.execute(create_chart)
├── LLM 生成最终回复
│
▼
[Python] SSE stream → Go → React
│
▼
[React] 渲染: 文本 + 图表 + 工具调用状态
技术选型参考
| 层 | 推荐技术栈 | 替代方案 |
|---|---|---|
| 前端 | React + Vercel AI SDK / assistant-ui | Next.js、Vue |
| 后端 | Go (Gin/Echo) + SSE | Node.js (Express/Fastify) |
| AI Service | Python (FastAPI) + LangGraph | TypeScript (Vercel AI SDK) |
| LLM | OpenAI API / Anthropic API | 自部署模型 |
| 向量检索 | pgvector 或 Qdrant/Milvus | 按数据量、过滤条件、运维成本与基准测试选择 |
| 数据库 | PostgreSQL | MySQL、MongoDB |
| 对象存储 | S3 / MinIO | 本地文件系统 |
| 可观测性 | OpenTelemetry + LangSmith/Langfuse | 自建 |
常见设计模式
1. BFF 模式 (Backend For Frontend)
Go 后端作为前端的专用后端,负责协议转换和上下文组装,不暴露 AI Service 的内部细节。
2. AI Service 独立部署
Python AI Service 作为独立服务,通过内部 API 与 Go 通信。好处是独立扩缩容、独立发布。
3. LLM Provider 抽象
AI Service 内部通过抽象层对接多个 LLM Provider,支持模型切换和 Fallback。
4. 事件驱动的流式架构
此方案可使用 Python → Go → React 的 SSE 流式链路。对外事件需做权限过滤与协议转换,不能直接暴露内部工具参数或 raw proposal;不同服务边界的事件 schema 可以不同,但映射必须明确。
常见坑
- Go 后端变成纯转发层: Go 不该只是透传请求,应该负责上下文组装、权限、审计
- 绕过数据所有权: AI Service 直接改写其他模块的业务表会耦合规则;经授权的只读查询与单体内模块调用需按实际边界设计
- 未经授权的直连: 无论是否经过 Go,公开的 AI 接口都需认证、资源授权、限流与审计
- 没有统一的事件协议: 每层各自定义事件格式,对接困难
- 过度工程化: MVP 阶段不需要微服务,单体 + 模块化就够了
和其他概念的关系
- vs AI Agent Application: Application 是产品,Stack 是技术选型
- vs Backend For Frontend: BFF 是 Stack 中 Go 层的设计模式
- vs AI Service: AI Service 是 Stack 中的 Agent 引擎层
极简示例
一个较小的部署组合可以是:
前端: React + fetch 消费响应流
后端: 一个 Python 服务,内部按 API / 业务 / Agent 模块组织
状态: 根据恢复与并发需求选择持久存储
检索: 只有任务需要时再加入向量索引
需要 Go 与 Python 独立扩缩容或不同发布节奏时再拆服务。原生 EventSource 适用于 GET 订阅;POST 返回的 SSE 流可用 fetch 读取,二者不能直接互换。
取舍
逻辑职责与进程边界是两回事。单体模块可以共享数据库,但应明确业务表的写入所有权;分成多个服务后,也不自动得到权限隔离和可靠交付。