Skip to content

部署 Agent Service

到此为止,前面所有页面都在讲"一个 Agent 怎么跑起来"——在 Python 进程里 await agent.reply_stream(),事件流直接消费。但在真实交付里,你面对的是多用户、多会话、浏览器与移动端并发订阅、定时任务与后台工具回调。AgentScope 2.x 用 Agent Service 把这一层收口:一个 create_app() 工厂返回的 FastAPI 应用,把 Agent 包成多租户、多会话的 HTTP/SSE 服务,开箱即得会话状态、持久化、调度与工具卸载。

版本基线:本文以 Python agentscope 2.0.4(PyPI,2026-07-07)为准,要求 Python >=3.11。导入路径为 from agentscope.app import create_app, SubAgentTemplate,配套模块 agentscope.app.storage / agentscope.app.message_bus / agentscope.app.workspace_manager / agentscope.app.middleware (源:src/agentscope/app/__init__.py 及各子包 __init__.py,已逐项核对)。2.x 文档站存在版本化陷阱: 非版本化的 /en/ URL 会 404,本页所有官方链接均使用 versions/2.0.4/en/ 形式。

为什么需要服务化

Agent.reply_stream() 解决的是"单进程内一次推理"的问题。一旦你把 Agent 对外提供,立刻会遇到四类 reply_stream 本身不处理的需求:

  1. 多租户隔离:不同用户的凭据、Agent、会话、消息必须互不可见。服务层把所有资源都挂在请求解析出的 user_id 下,并在路由层强制归属校验。
  2. 多会话并发:一个用户可能同时开多个会话,同一 Agent 模板驱动多个会话。服务层把"Agent 模板"与 "会话运行时状态"拆开——Agent 是可复用模板,Session 才是运行时状态单元。
  3. 外部触发回流:定时任务、后台工具完成、Agent Team 中队友发来的消息,都要能把一个"空闲"会话重新唤醒。 服务层用消息总线(inbox + wakeup)把这些外部事件统一送回会话。
  4. 前端友好:浏览器不能直接 await Python,需要 HTTP 触发 + SSE 订阅的标准接入,以及凭据表单、 模型卡片等 schema 驱动的 UI 渲染。

create_app() 就是这四件事的入口:它接收存储后端、消息总线、工作区管理器,注册全部内置路由,返回一个 可以直接 uvicorn.run 的 FastAPI 应用。

前端类比

如果你来自前端,可以把 Agent Service 类比为 BFF(Backend for Frontend)+ 后端微服务的组合:

  • create_app() 类比为 Next.js 的 API Route 工厂NestJS 的 bootstrap():一行调用把一组 路由装配成一个可运行的服务,差别在于这里装配的不是手写 controller,而是 Agent 运行时。
  • /chat + /sessions/{id}/stream 类比为 "提交任务 + SSE 订阅" 的异步模式——就像前端调一个 fetch('/api/chat') 拿到 job_id,再用 EventSource('/api/chat/stream') 订阅进度,而不是等一个 长轮询。
  • RedisStorage + RedisMessageBus 类比为 Redis 作为 Pub/Sub + 持久层 的经典后端组合:存储负责 落盘,消息总线负责跨进程事件分发,两者解耦。
  • extra_middlewares 类比为 Express / Koa 的 app.use():协议适配、CORS、鉴权都以 ASGI 中间件 形式包裹整个应用。

AgentScope 原生语义:Agent Service 不是一个"Web 框架包装",而是把 Agent 运行时服务化的完整层。 它的核心抽象是 资源模型——User、Credential、Agent、Session、Schedule、Workspace、MessageBus 七类 资源,全部按 user_id 隔离,由 ChatService 驱动单会话单运行(ChatRunRegistry 强制同一 session 同时 只有一个 /chat 运行,重复提交返回 409)。create_app() 的三个必填参数 (storage / message_bus / workspace_manager)分别对应"落盘在哪""事件怎么分发""工具在哪执行"三 个独立可替换的后端。和前端"API Route = 一组手写 handler"不同,这里你几乎不写路由——全部内置,你只配置 后端与扩展点。

Agent Service 架构

下面这张图说明一次 /chat 请求如何穿过服务层各管理器,最终通过消息总线回流到 SSE 流。注意消息总线是 所有外部触发(调度、后台工具、队友消息)汇聚到会话的唯一通道,这也是多进程部署能成立的关键。

关键节点:

  • create_app() 返回的 FastAPI 应用在 lifespan 里按顺序进入各资源(storage → message bus → workspace manager → background task manager → scheduler manager → chat run registry → 各 service → wakeup dispatcher),关闭时逆序释放;调度器在进入时恢复持久化的 cron 任务,所以重启不丢调度。
  • ChatService 是运行或中断一个会话的唯一入口:加载记录、装配 Toolkit、构建中间件、获取会话锁、 驱动 Agent.reply_stream()
  • SchedulerManager 基于 APScheduler,触发时只往目标会话 inbox 推 HintBlock 并 enqueue wakeup, 不直接调用 ChatService——所有触发都走消息总线统一回流。
  • BackgroundTaskManager 是纯 asyncio 任务注册表;ToolOffloadMiddleware 在工具超时时把调用挪到 这里,完成后结果经消息总线(inbox + wakeup)回到会话,而不是被这个管理器持有。
  • RedisMessageBus 提供会话锁、replay 日志、inbox 队列、wakeup 信号四类原语,是把"空闲会话"重新 唤醒的唯一通道,也是多进程部署的前提。
  • SSE 流 从消息总线消费事件,并对迟到的订阅者先回放缓冲历史,再发送实时事件。

构造与启动

create_app() 的三个必填参数对应三个可替换后端。最小可运行示例用 Redis 做存储与消息总线, LocalWorkspaceManager 做工作区管理(工具在宿主文件系统执行,无强隔离,仅适合开发):

python
import os

import uvicorn
from agentscope.app import create_app
from agentscope.app.storage import RedisStorage
from agentscope.app.message_bus import RedisMessageBus
from agentscope.app.workspace_manager import LocalWorkspaceManager

# 持久化层:agents / sessions / credentials / messages / schedules / teams。
# 连接池在 app 启动时打开、关闭时释放(lifespan 管理)。
# 生产环境务必通过环境变量注入 host / password,不要写进代码。
storage = RedisStorage(
    host=os.environ.get("REDIS_HOST", "localhost"),
    port=int(os.environ.get("REDIS_PORT", "6379")),
    password=os.environ.get("REDIS_PASSWORD", None),
)

# 消息总线:会话锁、replay 日志、inbox 队列、wakeup 信号。
# 它与 storage 解耦——持久化后端可以是 SQL,传输后端仍用 Redis。
message_bus = RedisMessageBus(
    host=os.environ.get("REDIS_HOST", "localhost"),
    port=int(os.environ.get("REDIS_PORT", "6379")),
    password=os.environ.get("REDIS_PASSWORD", None),
)

# 工作区生命周期:工作目录、MCP 客户端、Skills。
# 内置隔离粒度默认 per_agent(同一 agent 的会话共享一个工作区);
# 空闲工作区在 ttl 秒后驱逐。LocalWorkspaceManager 无强隔离,仅用于开发。
workspace_manager = LocalWorkspaceManager(
    basedir="/data/workspaces",
    ttl=3600.0,
)

app = create_app(
    storage=storage,
    message_bus=message_bus,
    workspace_manager=workspace_manager,
)

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

切换工作区后端只改一行——DockerWorkspaceManager(容器隔离)或 E2BWorkspaceManager(云沙箱隔离), 其余代码不动。E2B 的密钥通过环境变量 E2B_API_KEY 注入或构造时传入:

python
from agentscope.app.workspace_manager import DockerWorkspaceManager, E2BWorkspaceManager

# 容器隔离:每个工作区跑在独立 Docker 容器里,host 工作目录 bind-mount 进容器。
docker_wm = DockerWorkspaceManager(basedir="/data/docker-workspaces")

# 云沙箱隔离:每个工作区跑在远程 E2B 云 VM。api_key 留空时读取 E2B_API_KEY 环境变量。
e2b_wm = E2BWorkspaceManager()

create_app() 还接受若干可选扩展参数(源:src/agentscope/app/_app.py,已核对):extra_middlewares (ASGI 中间件,如协议适配、CORS、鉴权)、extra_credentials(注册自定义凭据类型)、 extra_agent_middlewares(按 (user_id, agent_id, session_id) 生产 Agent 级中间件的异步工厂)、 extra_agent_tools(按调用者生产额外工具的异步工厂)、custom_subagent_templates(Agent Team 用的子 Agent 模板,详见 Agent Team)、custom_agent_cls(替换内置 Agent 子类)、resource_access_policy(跨用户资源访问策略,默认 DenyAllResourceAccessPolicy 即归属隔离)。

REST API 速查

服务把资源模型暴露为 REST 端点,外加流式聊天端点。下表按类别列出核心端点;完整请求/响应形状见服务自带的 OpenAPI 文档(启动后访问 /docs)。所有端点都按请求解析出的 user_id 隔离。

端点方法作用
/agentGET / POST / PATCH / DELETE管理 Agent 记录:显示名、system prompt、运行时配置(context、ReAct)
/agent/schema/v2GET返回完整 AgentData JSON Schema,供前端渲染 Agent 表单
/credentialGET / POST / PATCH / DELETE管理各模型厂商的 API Key 与连接配置,可跨会话/Agent 复用
/credential/schemasGET发现所有已注册凭据类型及其 JSON 参数 Schema,供前端渲染凭据表单
/sessionsGET / POST / PATCH / DELETE创建与管理会话,含模型绑定与权限级别
/sessions/{id}/messagesGET分页查询会话消息记录(offset / limit
/sessions/{id}/statusGET探测统一会话状态:running / parked / idle / gone
/chatPOST触发一次会话运行,立即返回 {"status":"started","session_id":"..."}
/sessions/{id}/streamGET(SSE)订阅会话事件流,含缓冲回放与多订阅者扇出
/sessions/{id}/interruptPOST中断运行中或 HITL 挂起的会话,Agent 干净退出并等待下一次 /chat
/scheduleGET / POST / PATCH / DELETE管理 cron 定时执行,可选 stateless(每次新会话)或 stateful(累积上下文)
/workspace/mcpGET / POST / DELETE管理会话工作区的 MCP 客户端,响应含实时工具列表与健康状态
/workspace/skillGET / POST / DELETE管理会话工作区内可用的 Skills
/modelGET按 provider 列出候选聊天模型及其 ModelCard(能力、参数 Schema)
/knowledge_basesGET / POST / PATCH / DELETE知识库 CRUD,仅在 create_app 传入 knowledge_base_manager 时启用

典型的一次聊天流程是五步:POST /agent 注册 Agent → POST /credential 存 API Key → POST /sessions 建会话并绑定模型 → (可选)POST /workspace/mcpPOST /workspace/skill 配置工具 → POST /chat 触发运行,同时 GET /sessions/{id}/stream 订阅事件。/chat 立即返回,事件全部经 SSE 流外发。

后台工具卸载不是独立端点:当工具调用超过超时,ToolOffloadMiddleware 把它挪到 BackgroundTaskManager 的后台任务,完成后结果经消息总线回流到同一会话的 SSE 流——没有单独的 /background-tasks 端点,前端只需持续订阅 /sessions/{id}/stream 即可收到。

SSE 流与回放

GET /sessions/{id}/stream 是 Agent Service 的输出主干。它以 SSE 形式持续推送 AgentScope 原生的 AgentEvent(文本块、工具调用、工具结果、思考块、HITL 确认请求等,事件结构见 消息与事件)。两个关键能力让前端无需自己处理"断线"与"多端同步":

  • 缓冲回放:迟到的订阅者(刷新页面、新开 tab、重连)会先收到该会话已缓冲的历史事件,再接收实时 事件。多个客户端可以同时订阅同一会话,互相不干扰。
  • 跨触发统一:同一会话的 /chat 触发、cron 调度触发、后台工具完成、Agent Team 队友消息,全部 汇聚到这一条流。前端不需要为不同触发源分别建连。

流式事件的完整语义、HITL 中断恢复、事件到 Msg 的重建,见 流式事件(本文聚焦部署层,不展开事件类型)。中断一个运行中或 HITL 挂起的会话用 POST /sessions/{id}/interrupt,Agent 会干净退出并保持可立即接受下一次 /chat

协议扩展点

/sessions/{id}/stream 默认输出 AgentScope 原生 AgentEvent 流。若你的前端使用其他协议,可以通过 协议中间件拦截 SSE 响应、把每一帧 AgentEvent 转换成目标协议的格式。AgentScope 2.0.4 在 agentscope.app.middleware 中导出(源:src/agentscope/app/middleware/__init__.py,已核对):

  • ProtocolMiddlewareBase — 协议中间件抽象基类,子类实现 _convert_to_protocol(event) -> dict 即可。
  • AGUIProtocolMiddleware — 面向 AG-UI 协议的 shipped 适配器。

安装 shipped 的 AG-UI 适配器,把它作为 ASGI 中间件通过 extra_middlewares 传入:

python
from fastapi.middleware import Middleware
from agentscope.app import create_app
from agentscope.app.middleware import AGUIProtocolMiddleware

app = create_app(
    storage=storage,
    message_bus=message_bus,
    workspace_manager=workspace_manager,
    extra_middlewares=[
        Middleware(AGUIProtocolMiddleware),
    ],
)

新增一个协议适配,子类化 ProtocolMiddlewareBase 即可——中间件会自动拦截会话流端点的 StreamingResponse, 把每个 SSE 帧反序列化回 AgentEvent,调用你的 _convert_to_protocol() 转换后再重新序列化:

python
from agentscope.app.middleware import ProtocolMiddlewareBase
from agentscope.event import AgentEvent


class MyProtocolMiddleware(ProtocolMiddlewareBase):
    def _convert_to_protocol(self, event: AgentEvent) -> dict:
        # 把 AgentEvent 转成你的协议帧格式。
        return {"type": event.type, "data": event.model_dump()}

A2A 没有 shipped 适配器:官方文档把 AG-UI、A2A 等并列为"可适配协议",但 2.0.4 实际只随包发布了 AGUIProtocolMiddleware。A2A(Agent-to-Agent)当前仅作为扩展点存在——你需要自行子类化 ProtocolMiddlewareBase 实现,不要把它当成开箱即用的能力。官方 capabilities 表里提到的 "Protocol adaptation" 是框架能力,不等于每个协议都有现成适配器。

前端的 TypeScript SDK 消费 SSE 流、对接 Web UI 的方式,见 版本与生态

预览能力(2.0.5dev,API 可能变动)

下面两项不在 2.0.4 稳定版内,对应官方文档站的 deploy/sharingdeploy/workspace-manager 页面 随 main 分支(2.0.5dev)发布,可能领先 PyPI。接入前务必固定版本号并对照源码,API 可能在正式发布前 调整。本教程把它们标注为预览,仅作入口介绍,不展开稳定 API 示例。

  • Resource Sharing(资源分享):在多租户归属隔离之上,提供受控的跨用户资源访问策略 (ResourceAccessPolicyBase 的进阶用法)。2.0.4 的 create_app 已暴露 resource_access_policy 参数且默认 DenyAllResourceAccessPolicy,但完整的 sharing 文档页与配套策略实现属 dev 期。
  • Workspace Manager 部署页deploy/workspace-manager 页系统讲解工作区管理器的部署形态与隔离策略 切换。注意:构建块类LocalWorkspaceManager / DockerWorkspaceManager / E2BWorkspaceManagerWorkspaceManagerBase)在 2.0.4 已稳定可用(本文上一节示例即基于它们),dev-only 的只是那张 集中讲部署的文档页与其涉及的进阶配置。

如果你需要这两项,先在 版本与生态 确认当前安装版本,再 对照官方 2.0.5dev 文档与源码,不要把 dev 行为写进生产代码。

部署注意

  • Redis 是生产前提RedisStorageRedisMessageBus 是 shipped 的唯一稳定后端。存储与消息总线 故意解耦——持久化后端理论上可换成 SQL(实现 StorageBase 即可),但传输后端仍建议用 Redis,因为 wakeup / inbox / replay 依赖 Redis 的 Pub/Sub 与原语。
  • InMemoryMessageBus 仅开发agentscope.app.message_bus 同时导出 InMemoryMessageBus,它无需 Redis、单进程内嵌。但它无法跨进程,任何多 worker / 多节点部署都必须换回 RedisMessageBus。把它 用于生产会导致调度触发、后台工具完成、队友消息全部无法送达其他进程的会话。
  • 生产需独立 Redis:多 worker 部署时,所有进程共享同一 Redis 实例(storage + bus),这是 ChatRunRegistry 单会话单运行规则与 wakeup 跨进程分发能成立的前提。单进程内嵌消息总线仅适合本地 调试。
  • 鉴权是占位符:内置的 get_current_user_id 只从 X-User-ID 请求头取值,不是鉴权。生产部署 前必须用 app.dependency_overrides[default_dependency] = your_auth 替换为 JWT / OAuth2 / 会话 token 等真实鉴权依赖。
  • 工作区后端按隔离需求选LocalWorkspaceManager 无强隔离,工具直接操作宿主文件系统;生产建议 DockerWorkspaceManager(容器隔离)或 E2BWorkspaceManager(云沙箱隔离)。隔离粒度 (per_agent / per_session / per_user)由工作区管理器决定。
  • 固定版本:PyPI 当前 4 - Beta 分类,生产接入请固定 agentscope==2.0.4 并跟踪 release notes, 不要浮动到 2.0.5dev

先修

  • 可观测性 - 服务层的 Tracing、事件流可观测基础

下一步

  • Agent Team - Leader-Worker 多 Agent 协作,SubAgentTemplate 与团队工具

官方参考

学习文档整合站点