它们做什么
Gateway 位于你的应用代码和 agent 之间,负责:- 会话管理 — 把每个用户对话映射到稳定的 session id。agent 在跨轮次时看到一致的记忆。
- Per-session 并发控制 — 同一 session 的并发消息会公平排队,agent 不会和自己竞争。
- Agent 路由 — 在多 agent 场景下,把每条消息路由到正确的 agent。
agent.channel(...) 会在后台自动完成所有接线。
快速开始
agent.channel(...) 会懒加载创建内部 gateway,注册当前 agent,并把 gateway 注入到 channel 中。调用之后 chat 就可以直接使用了。
SendOptions
SendOptions 告诉 channel 谁在说话、这属于哪个对话:
多模态 / 结构化消息
纯文本send(String) 只是便捷方法。图片、音频或多段内容请传预构建的 Msg(或 List<Msg>)——每个 String 重载都有对应的 Msg / List<Msg> 版本(含 SendOptions 与 sendStream):
RuntimeContext 合并
Channel 路径会在 Gateway 内构建RuntimeContext。调用方可通过 SendOptions / InboundMessage.runtimeContext() / ChannelRuntimeContextResolver 提供 caller base。合并顺序:
- 以 caller 上下文为起点(可为空)
- 若配置了
ChannelRuntimeContextResolver且返回非 null,则 替换 caller base - Gateway 再覆盖身份字段——
sessionId(gw-…)、userId、msgContext、gateKey、outboundAddress——冲突时以 Gateway 为准
GatewayBootstrap 接线:
gateway.setRuntimeContextResolver(...)。不要把业务属性写进 MsgContext.extra——该 map 参与 session key 计算。
流式事件 + SSE
sendStream() 返回 Flux<AgentEvent>,和 agent.streamEvents() 一样的细粒度事件流,但经过 gateway 路由并带有会话管理。
Spring Boot SSE Controller
与暴露的子 Agent 对话
当 agent 通过expose_to_user=true spawn 子 agent 时,gateway 会把这个子 agent 暴露为用户可直接寻址的入口。一个 SubagentExposedEvent 会出现在 sendStream() 的事件流中,携带 subagentId。
发现暴露的子 Agent
SubagentExposedEvent 字段:
向子 Agent 发消息
拿到subagentId 之后,可以直接和子 agent 对话——完全绕过父 agent:
带子 Agent 支持的 SSE
典型的 SSE controller 同时处理主 agent 和子 agent 消息:SUBAGENT_EXPOSED 事件来渲染新的对话标签页,后续请求时把 subagentId 传回来即可。
多 HarnessAgent 路由
如果有多个HarnessAgent 实例,使用 GatewayBootstrap:
按 agentId 路由
使用SendOptions.withAgentId() 把消息路由到指定 agent:
GatewayBootstrap 下暴露子 Agent
要在 GatewayBootstrap 模式下启用expose_to_user,需要把 gateway bridge 接到每个 agent 的子 agent 中间件上:
agent.channel(...) 时,这个接线会自动完成。
自定义 Channel
实现Channel 接口来适配新的消息平台:
GatewayBootstrap 注册:
内置 Channel 适配器
AgentScope 提供了多个开箱即用的 Channel 适配器作为扩展模块:- 钉钉 — Stream 协议(持久 WebSocket)
- 飞书 / Lark — 事件订阅回调
- GitHub — Issue / PR 评论 webhook
- GitLab — Note hook
- 企业微信 — 加密回调