数据截至 (上游 commit 4d1c35a6dd5e)
巧妙之处、边界、对比与代码地图
前三章讲「怎么工作」,这章讲「哪里值得学、哪里会崩、和别人比怎样」。
5. 巧妙之处(可借鉴的技术)
① 无状态 agent + 运行期注入。 Agent 不挂会话状态,所有「环境」在执行时由 AgencyContext 注入,让同一个 Agent 实例能被多 agency / 多会话复用。spot:agent/core.py:102-104(设计声明)、agent/core.py:382-400(get_all_tools 运行期合并工具)。这是整个框架最核心的取舍。
② 一张扁平历史表表达多种对话。 不维护 N 个 thread 对象,而用 agent/callerAgent 两个标签 + 过滤,既能取「跨入口共享的用户线程」又能取「每对 agent 的子对话」。spot:utils/thread.py:80-100、177-196。妙在新增一对通信不需要新数据结构。
③ send_message = 递归 get_response。 委派不是消息队列,而是同步函数调用:工具调用即把 recipient 跑一整轮,final_output 当返回值。实现简单、调用树清晰(parent_run_id 串起来),代价是天然串行。spot:tools/send_message.py:505-511。
④ 待处理去重锁。 防止模型在一轮里对同一个 recipient 并发发多条(会导致历史错乱)。按 (thread, recipient) 记一个 pending 集合,命中就返回友好错误,finally 里释放。spot:tools/send_message.py:379-393、560-567。
⑤ 一次一调的工具并发守卫。 对标了 one_call_at_a_time 的工具,框架包一层 guarded_on_invoke:若已有 one-call 工具在跑就拒绝其它工具、并把这条要求写进工具描述里告诉模型。spot:agent/tools.py:236-295,并发状态机 tools/concurrency.py:18-64。
⑥ 对话启动器缓存(延迟优化)。 对固定的 conversation_starters / quick_replies / system_reminders,首条消息可命中缓存直接拼出 RunResult、跳过真正调模型;还在 agency 初始化时 后台预热缓存。spot:命中拼装 agent/execution.py:211-249,预热 agency/core.py:607-645。缓存键是个 fingerprint(随 instructions/工具变化失效),保证不串味。
⑦ 跨 agent 逐模型成本归集。 子 agent 的响应连同它自己的模型名被收集上来,父运行据此分模型计费,正确处理混模型委派。spot:tools/send_message.py:481-492、agent/execution.py:251-272。
6. 边界与局限(诚实)
- 强依赖 OpenAI Agents SDK,且锁死版本。
openai-agents==0.18.1(pyproject.toml:16-18),要求 Python ≥ 3.12(pyproject.toml:13)。推理循环、handoff、工具协议都来自 SDK——这是「站在 SDK 肩上」的红利,也是耦合点。 - 委派是同步串行的。 send_message 直接
await recipient.get_response,一个 manager 想「并行」问两个专家,在单轮里被去重锁挡住(send_message.py:379-393);真正并发要靠模型分多轮或自定义编排。 - 通信是显式有向图,没有自动路由。 没在
communication_flows里画的边就发不了消息;supports_outbound_communication=False的 agent 当 sender 会直接抛错(agency/setup.py:260-265)。好处是可控、可审计;代价是拓扑得手工维护。 - 历史协议不能混。 换模型导致一条历史里 Responses 与 Chat Completions 格式混杂会抛
IncompatibleChatHistoryError,需要清历史重开(messages/message_formatter.py:184-198)。 - 运算符语法有「比较链」黑魔法。
a > b > c靠重载__bool__把中间边塞进类级全局列表来接住,作者自承是 hack(agent/agent_flow.py:73-90)。能用,但属于需要小心的隐式行为。 _create_recipient_agency_context用了内联MinimalAgency。 recipient 的上下文是工具里临时拼的「最小 agency」对象而非真Agency(tools/send_message.py:281-289),功能够用,但它不是完整 agency,某些依赖Agency具体类型的逻辑会走降级分支。- 默认模型字符串看着像占位符。 源码 docstring 写默认
"gpt-5.6-luna"(agent/core.py:174),疑似上游占位/示意值,本文按原样引用,不据此断言真实模型 id。
7. 横向对比
Agency Swarm 在 ai-agent-reference 的 multi-agent 区,核心取舍可这样定位:
| 维度 | Agency Swarm 的选择 | 含义 |
|---|---|---|
| 推理循环 | 复用 OpenAI Agents SDK,不自研 | 轻量、跟随 SDK 演进;强耦合单一 SDK |
| 拓扑 | 显式有向图(手画通信流) | 可控可审计;不自动路由 |
| 委派原语 | send_message(同步求助)+ Handoff(转交) | 两种语义分明 |
| 历史 | 单张扁平表 + 标签过滤 | 结构简单、易持久化;靠标签隔离 |
| 状态 | agent 无状态,运行期注入 | 实例可复用、可并发多会话 |
| 持久化 | 回调式(load/save 两个函数) | 后端自带、不绑数据库 |
对比方向(同 shelf 兄弟项目,验证后再链对应 doc):
- 「自研推理循环」型框架(把规划/工具/记忆都自己实现):控制力强但维护重;Agency Swarm 反向选择——把循环外包给 SDK,只做编排层。
- 「自动路由 / 角色协商」型(让 LLM 决定下一个谁干):灵活但不可预测;Agency Swarm 用显式有向边换确定性与可审计。
- 跨库的「多 agent 编排」第一性原理与对比表,见本 shelf 总库 doc 的 multi-agent 章节(占位,待总库锚定)。
8. 代码地图(导航索引)
| 主题 | 文件 | 关键符号 |
|---|---|---|
| 顶层编排器、入口、初始化 | src/agency_swarm/agency/core.py | Agency、Agency.__init__、get_response、_schedule_starter_cache_warmup |
| 通信流解析(运算符 → 边) | src/agency_swarm/agency/setup.py | parse_agent_flows、configure_agents、register_agent |
| 运算符 DSL | src/agency_swarm/agent/agent_flow.py | AgentFlow、__gt__、__bool__、get_and_clear_chain_flows |
| 无状态 Agent 定义 | src/agency_swarm/agent/core.py | Agent、get_response、get_all_tools、register_subagent |
| 一次 turn 的执行流程 | src/agency_swarm/agent/execution.py | Execution.get_response、Execution.get_response_stream |
| 执行辅助 / MasterContext 构造 | src/agency_swarm/agent/execution_helpers.py | prepare_master_context、setup_execution、_resolve_latest_shared_instructions |
| send_message 工具(生成+调用) | src/agency_swarm/tools/send_message.py | SendMessage、on_invoke_tool、_discover_inline_fields、_create_recipient_agency_context |
| Handoff(转交控制权) | src/agency_swarm/tools/send_message.py | Handoff.create_handoff、SendMessageHandoff |
| 子 agent 注册 | src/agency_swarm/agent/subagents.py | register_subagent、_resolve_send_message_class |
| 运行期上下文对象 | src/agency_swarm/agent/context_types.py | AgencyContext、AgentRuntimeState |
| 共享上下文(传给 Runner) | src/agency_swarm/context.py | MasterContext |
| 扁平消息表 + 持久化 | src/agency_swarm/utils/thread.py | MessageStore、ThreadManager、get_conversation_history |
| 消息元数据 / 协议校验 | src/agency_swarm/messages/message_formatter.py | MessageFormatter、prepare_history_for_runner、add_agency_metadata、strip_agency_metadata、_ensure_history_protocol_compatibility |
| 持久化 hooks | src/agency_swarm/hooks.py | PersistenceHooks、on_run_end |
| 一次一调并发守卫 | src/agency_swarm/agent/tools.py、src/agency_swarm/tools/concurrency.py | _attach_one_call_guard、ToolConcurrencyManager |
| 包导出 / 公共 API | src/agency_swarm/__init__.py | Agency、Agent、SendMessage、function_tool、run_fastapi |