Skip to content

feat: subagent功能增强#8152

Open
elecvoid243 wants to merge 120 commits into
AstrBotDevs:masterfrom
elecvoid243:subagent
Open

feat: subagent功能增强#8152
elecvoid243 wants to merge 120 commits into
AstrBotDevs:masterfrom
elecvoid243:subagent

Conversation

@elecvoid243

@elecvoid243 elecvoid243 commented May 11, 2026

Copy link
Copy Markdown
Contributor

Modifications / 改动点

一、概述

resolve #6954
本PR为subagent能力进行了功能扩充,使得astrbot能够执行更复杂的任务,并向生产级的全能性助手靠拢。支持2种子代理类型和2种编排方式:

  1. 静态配置:即原版的subagent,通过 subagent_orchestrator.agents 在配置文件中预定义子代理,并伴随整个astrbot生命周期存在
  2. 动态创建:主Agent在运行时通过工具调用动态创建子代理,在每轮对话结束后自动清理,也可由主Agent自主回收或加上清理保护

所有子代理(无论静态还是动态)都由统一的 SubAgentManager 管理,支持以下高级功能:独立上下文记忆、独立工具隔离、工作目录隔离、技能隔离、公共上下文共享、超时限制、后台任务模式等。

编排方式

  1. 默认编排:由主Agent自主协调什么时候调用哪个子代理,并担当传话员。这可能涉及多轮transfer_to_*wait_for_subagent(新增)调用
  2. DAG 编排:主 Agent 可以通过 orchestrate_tasks 工具一次性声明所有任务及其依赖,系统自动进行拓扑排序、分层并行执行、前置结果自动注入以及级联失败跳过。DAG执行结束后,主Agent直接取得最终结果,避免自行调度链过长导致的幻觉。

核心特性

特性 说明
统一实现 静态配置和动态创建的子代理都由 SubAgentManager 统一管理
动态创建 主Agent可通过create_subagent在运行时动态创建子代理
更好的后台任务模式 支持将耗时任务放到后台执行,主Agent可并行处理其他任务,也可通过wait_for_subagent阻塞式等待输出
自动清理 一轮对话结束时自动清理未受保护的子代理
上下文记忆 如开启,子代理可以保留跨轮对话历史,并支持历史截断和tool结果压缩
工作目录隔离 每个子代理可配置独立工作目录,并带有路径安全检查
Skills隔离 子代理可使用Skills,每个子代理拥有独立的技能配置
公共上下文 如开启,每个子代理可访问公共上下文,实现共享信息和协调工作
行为规范注入 如开启,为子代理自动注入安全模式、输出规范、时间信息等行为约束
数量限制 可配置的子代理最大数量限制
工具管理 除了主Agent动态分配的工具,用户可配置黑名单:防止子代理获得管理类工具;固有名单:子代理可拥有固有工具保证基础能力
执行超时控制 除了工具调用超时限制外,支持为子代理设置执行总长超时,避免无限等待
会话过期清理 自动清理长时间(30分钟)不活跃会话的子代理,防止内存泄漏
运行追踪 SubAgent 执行全过程可追踪,层级化 Span 关联父子关系,前端独立展示主 Agent 与 SubAgent 追踪视图,支持实时观察异步任务执行
DAG 编排 支持声明式多任务依赖编排,自动拓扑排序与分层并行执行,前置结果智能注入,Fail-fast 级联失败跳过,Dashboard 可视化配置

二、配置说明

2.1 新增配置项说明

cmd_config.json 中通过 subagent_orchestrator 配置块进行设置:

  "subagent_orchestrator": {
    "main_enable": true,
    "remove_main_duplicate_tools": false,
    "router_system_prompt": "You are a task router. Your job is to chat naturally, recognize user intent, and delegate work to the most suitable subagent using transfer_to_* tools. Do not try to use domain tools yourself. If no subagent fits, respond directly.",
    "agents": [
      {
        "name": "static_subagent",
        "persona_id": "测试人格",
        "public_description": "测试子代理(静态)",
        "enabled": true,
        "provider_id": "kimi-code/kimi-for-coding"
      }
    ],
    "dynamic_agents": {
      "enabled": true,
      "max_subagent_count": 5,
      "auto_cleanup_per_turn": true,
      "default_provider_id": "",
      "rule_prompt": "# Subagent Rules ...",
      "tools_blacklist": [
        "create_subagent",
        "manage_subagent_protection",
        "remove_subagent",
        "list_subagents",
        "wait_for_subagent",
        "orchestrate_tasks",
        "broadcast_shared_context",
        "view_shared_context"
      ],
      "tools_inherent": [
        "astrbot_execute_shell",
        "astrbot_execute_python"
      ]
    },
    "time_prompt_enabled" : true,
    "history_enabled": true,
    "shared_context_enabled": true,
    "shared_context_maxlen": 300,
    "subagent_history_maxlen": 300,
    "execution_timeout": 1200,
    "dag_enabled": false,
    "dag_max_nodes": 10,
    "dag_max_parallel": 5,
    "dag_max_inject_length": 4000
  }

2.2 配置项详解

配置项 类型 默认值 说明
main_enable bool false 总开关,启用SubAgent编排功能(静态+动态)
静态子代理(原版)
remove_main_duplicate_tools bool false 是否从主Agent移除已分配给子代理的工具(静态)
router_system_prompt str "" 主Agent路由提示词(仅启用静态且未开启动态时有效)
agents list [] 静态子代理配置列表
动态子代理(新增)
enabled bool false 是否允许主Agent动态创建子代理
max_subagent_count int 5 单个会话允许的最大子代理数量,包含动态和静态
auto_cleanup_per_turn bool true 每轮对话结束后自动清理非保护子代理
default_provider_id str "" 动态创建的子代理默认使用的 LLM Provider ID(为空则跟随全局设置)
rule_prompt str 默认规则提示词 动态子代理的固定提示词(例如行为规范)
tools_blacklist list 预设黑名单列表 动态subagent工具黑名单列表,默认包含 create_subagent、manage_subagent_protection、protect_subagent、remove_subagent、list_subagents、wait_for_subagent、orchestrate_tasks、broadcast_shared_context、view_shared_context
tools_inherent list 预设固有工具列表 动态subagent固有工具列表
通用配置
time_prompt_enabled bool true 是否启用子代理的时间信息注入
history_enabled bool true 是否启用子代理的上下文历史功能,为true可以保留跨多轮对话的记忆
shared_context_enabled bool true 是否启用子代理间公共上下文共享
shared_context_maxlen int 300 公共上下文消息最大数量(条);该项仅控制管理类的变量长度,实际子代理仍受到truncate逻辑控制
subagent_history_maxlen int 300 每个子代理最多保留的历史消息(条);该项仅控制管理类的变量长度,实际子代理仍受到truncate逻辑控制
execution_timeout float 1200.0 SubAgent执行超时时间(秒),-1表示不限制
DAG 编排(新增)
dag_enabled bool false 是否启用 DAG 编排(orchestrate_tasks 工具 + Prompt 注入)。Dashboard 中通过「编排方式」下拉切换
dag_max_nodes int 10 单个 DAG 编排允许的最大任务节点数
dag_max_parallel int 5 每波并行执行的最大任务数(硬上限),同层超限时自动分批
dag_max_inject_length int 4000 前置任务结果注入到后继任务上下文的最大字符数,超出截断

三、核心文件

3.1 subagent_manager.py

文件路径astrbot/core/subagent_manager.py

核心数据结构

class SubAgentStatus(str, Enum):
    IDLE = "IDLE"
    RUNNING = "RUNNING"
    COMPLETED = "COMPLETED"
    FAILED = "FAILED"
    CANCELLED = "CANCELLED"

@dataclass
class SubAgentConfig:
    name: str
    system_prompt: str = ""
    tools: set[str] | None = None        # 分配的工具名称集合
    skills: set[str] | None = None       # 分配的技能名称集合
    provider_id: str | None = None       # 可选的LLM提供商ID
    description: str = ""                # handoff工具描述
    workdir: str | None = None           # 子代理工作目录
    execution_timeout: float = 600.0    # SubAgent 执行超时时间(秒)

@dataclass
class SubAgentExecutionResult:
    task_id: str          # 任务唯一标识符(递增数字字符串)
    agent_name: str
    success: bool
    result: str | None = None
    error: str | None = None
    execution_time: float = 0.0
    created_at: float = 0.0
    completed_at: float = 0.0
    metadata: dict = field(default_factory=dict)

@dataclass
class SubAgentSession:
    session_id: str
    subagents: dict = field(default_factory=dict)       # 存储SubAgentConfig对象
    handoff_tools: dict = field(default_factory=dict)
    subagent_status: dict = field(default_factory=dict) # 工作状态: SubAgentStatus 枚举值 ("IDLE" "RUNNING" "COMPLETED" "FAILED")
    protected_agents: set = field(default_factory=set)  # 受保护agent不会被自动清理
    history_enabled: bool = True                        # 是否保存子代理历史
    subagent_histories: dict = field(default_factory=dict) # 每个子代理的历史上下文
    shared_context: list = field(default_factory=list)  # 公共上下文列表
    shared_context_enabled: bool = False                # 是否启用公共上下文
    subagent_background_results: dict = field(default_factory=dict)  # 后台subagent结果存储
    background_task_counters: dict = field(default_factory=dict)  # 任务计数器
    subagent_traces: dict = field(default_factory=dict)  # 每个子代理的 TraceSpan: {agent_name: TraceSpan}
    active_dag: DAGExecutionContext | None = None  # 当前活跃的 DAG 执行上下文
    dag_history: list = field(default_factory=list)  # 已完成的 DAG 历史记录
    last_activity_at: float = field(default_factory=time.time)  # 最后活跃时间

核心类SubAgentManager

方法 功能
configure() 配置管理器全局设置(数量限制、自动清理、公共上下文、历史记忆、时区、DAG等)
get_execution_timeout() 获取SubAgent执行超时时间
is_auto_cleanup_per_turn() 检查是否启用自动清理
is_shared_context_enabled() 检查是否启用公共上下文
is_history_enabled() 检查是否启用子代理历史记忆
register_blacklisted_tool(tool_name) 注册不应被子Agent使用的工具
register_inherent_tool(tool_name) 注册子Agent默认拥有的工具
create_subagent(session_id, config, protected=False) 创建子代理,返回 (tool_name, handoff_tool) 元组
register_static_subagent(session_id, handoff_tool, skills, workdir) 注册静态子代理到管理器(自动protected=True)
remove_subagent(session_id, agent_name) 移除指定子代理或全部子代理
cleanup_session_turn_end(session_id) 每轮结束时自动清理非保护子代理
cleanup_expired_sessions() 清理超过超时时间未活跃的会话,防止内存泄漏
protect_subagent(session_id, agent_name) 保护子代理不被自动清理
is_protected(session_id, agent_name) 检查子代理是否受保护
update_subagent_history(session_id, agent_name, current_messages) 更新子代理历史(支持system消息过滤和tool结果截断)
get_subagent_history(session_id, agent_name) 获取子代理历史
clear_subagent_history(session_id, agent_name) 清除子代理历史
build_subagent_system_prompt(session_id, agent_name, runtime) 构建子代理系统提示词(工作目录、行为规范、Skills)
build_subagent_extra_content_parts(session_id, agent_name) 构建子代理追加内容部分(公共上下文、时间信息)
build_task_router_prompt(session_id) 构建主Agent的路由提示词(配额信息、创建指南、生命周期等)
get_subagent_tools(session_id, agent_name) 获取子代理被分配的工具列表
add_shared_context(session_id, sender, context_type, content, target) 添加公共上下文消息
get_shared_context(session_id, filter_by_agent) 获取公共上下文(支持按Agent过滤)
_build_shared_context_prompt(session_id, agent_name) 分块构建公共上下文提示(按类型和优先级分组)
create_pending_subagent_task(session_id, agent_name) 为SubAgent创建pending任务,返回task_id
get_pending_subagent_tasks(session_id, agent_name) 获取SubAgent的所有pending任务ID列表
register_dag(session_id, dag_ctx) 注册 DAG 执行上下文到会话
get_active_dag(session_id) 获取当前活跃的 DAG 执行上下文
cancel_dag(session_id) 取消当前活跃的 DAG 执行
_filter_skills_for_current_config(skills) 根据插件激活状态和 plugin_set 配置过滤 skills
_build_subagent_skills_prompt(session_id, agent_name, runtime) 为子代理构建 skills prompt(根据分配的 skills 过滤后生成)
get_latest_task_id(session_id, agent_name) 获取SubAgent的最新任务ID
store_subagent_result(session_id, agent_name, success, result, task_id, error, execution_time, metadata) 存储SubAgent的执行结果
get_subagent_result(session_id, agent_name, task_id) 获取SubAgent的执行结果
has_subagent_result(session_id, agent_name, task_id) 检查SubAgent是否有结果
clear_subagent_result(session_id, agent_name, task_id) 清除SubAgent的执行结果
get_subagent_status(session_id, agent_name) 获取SubAgent的状态:IDLE/RUNNING/COMPLETED/FAILED
get_all_subagent_status(session_id) 获取所有SubAgent的状态
set_subagent_status(session_id, agent_name, status) 设置SubAgent的状态
cleanup_shared_context_by_agent(session_id, agent_name) 清理与指定Agent相关的公共上下文消息
clear_shared_context(session_id) 清除所有公共上下文
set_shared_context_enabled(session_id, enabled) 启用/禁用公共上下文
set_history_enabled(session_id, enabled) 启用/禁用子代理历史记忆
get_handoff_tools_for_session(session_id) 获取会话的所有handoff工具
cleanup_session(session_id) 清理整个会话

3.2 subagent_dag.py

文件路径astrbot/core/subagent_dag.py

核心类SubAgentDAGEngine

DAG 编排引擎,提供基于有向无环图的任务调度,包含 Kahn 拓扑排序、分层并行执行、前置结果自动注入(带截断保护)、Fail-fast 级联失败跳过。核心数据结构 DAGTaskNode(6 态:PENDING→READY→RUNNING→COMPLETED/FAILED/SKIPPED)和 DAGExecutionContext。通过 task_id 精确匹配消除并发竞争条件。

3.3 subagent_tools.py

文件路径astrbot/core/subagent_tools.py

该文件包含所有子代理管理工具的类定义,这些工具供主Agent在运行时调用以创建、管理和与子代理交互。包含 OrchestrateTasksTool(DAG 编排入口)。

核心工具类

工具类 名称 说明
CreateSubAgentTool create_subagent 创建子代理
RemoveSubagentTool remove_subagent 移除子代理
ListSubagentsTool list_subagents 列出子代理
ResetSubAgentTool reset_subagent 重置子代理历史
ManageSubagentProtectionTool manage_subagent_protection 保护/取消保护子代理(合并了protect/unprotect功能)
BroadCastSharedContextTool broadcast_shared_context 主Agent广播公共上下文(替代原send_shared_context_for_main_agent)
SendSharedContextTool send_shared_context 子Agent发送公共上下文
ViewSharedContextTool view_shared_context 查看公共上下文
WaitForSubagentTool wait_for_subagent 等待后台SubAgent结果

四、功能实现

4.1 静态子代理

功能描述

静态子代理是原版的子代理实现,由配置文件预定义人格和工具分配。

为了实现统一管理,静态子代理在 build_main_agent() 时自动注册到 SubAgentManager,可以享受历史记忆、公共上下文、Skills调用等增强功能(如果开启)。

实现方式

  • 文件astrbot/core/subagent_orchestrator.py
  • 核心方法SubAgentOrchestrator.register_static_subagents_to_manager()
  • 调用时机astr_main_agent.py_apply_subagent_manager_tools()

注册流程

  1. build_main_agent() 构建主Agent时调用 _apply_subagent_manager_tools()
  2. _apply_subagent_manager_tools() 调用 so.register_static_subagents_to_manager(session_id)
  3. 遍历 SubAgentOrchestrator.handoffs 中的所有静态 handoff 工具
  4. 对每个 handoff 调用 SubAgentManager.register_static_subagent()
  5. register_static_subagent() 内部:
    • HandoffTool 提取 agent 信息
    • 创建 SubAgentConfig
    • 调用 create_subagent(session_id, config, protected=True)
  6. 静态子代理注册完成,自动受保护(防止自动清理)

4.2 动态子代理

功能描述

当动态子代理功能开启时,主Agent可以通过create_subagent工具动态创建子代理,每个子代理拥有独立的人设、工具、技能和工作目录配置。随后系统会创建对应的transfer_to_xxx工具供主Agent调用

实现方式

  • 文件astrbot/core/subagent_tools.py
  • 核心类CreateSubAgentTool
  • 参数
    • name: 子代理名称
    • system_prompt: 子代理的人设和系统提示
    • tools: 可用工具列表(字符串名称)
    • skills: 可用技能列表(字符串名称)
    • workdir: 子代理工作目录(绝对路径,可选)
    • provider_id: 子代理使用的LLM提供商ID(可选,默认使用 dynamic_agents.default_provider_id 全局配置,若也为空则跟随主Agent设置)

使用示例

create_subagent(
    name="data_analyst",
    system_prompt="你是一个专业的数据分析师,擅长分析数据并给出见解",
    tools=["astrbot_execute_shell", "astrbot_execute_python"],
    skills=["excel", "pdf"],
    workdir="/path/to/workspace",
    provider_id="kimi-code/kimi-for-coding"
)

名称验证规则

  1. 必须以字母开头
  2. 只允许英文字母、数字和下划线
  3. 长度1-32字符(正则:^[a-zA-Z][a-zA-Z0-9_]{0,31}$
  4. 子代理名称可能会作为文件夹名的一部分(具备独立工作目录),因此不允许Windows保留文件夹名

创建后流程

  1. 验证名称格式和工作目录安全性
  2. 检查子代理数量是否达到上限
  3. 从工具列表中移除黑名单工具(如管理类工具)
  4. 自动添加固有工具(如 astrbot_execute_shell, astrbot_execute_python 。若公共上下文启用,还会添加 send_shared_context
  5. 创建 SubAgentConfig 配置对象
  6. 创建 AgentHandoffTool 对象
  7. 注册到 SubAgentManager
  8. 初始化子代理历史和状态("IDLE")
  9. 返回带有 __DYNAMIC_TOOL_CREATED__ 标记的消息,触发工具schema刷新

工作目录安全检查

CreateSubAgentTool._check_path_safety() 对传入的 workdir 进行安全验证:

检查项 说明
绝对路径 必须是绝对路径
路径遍历 不允许包含 ..
Windows危险目录 禁止访问 windows, system32, syswow64, boot
Linux危险目录 禁止访问 /etc, /bin, /sbin, /root
macOS危险目录 禁止访问 /System, /Library, /private/var, /usr
路径存在性 路径必须实际存在

验证失败时,工作目录回退到 Path(get_astrbot_workspaces_path()) / normalized_umo / agent_name,即主Agent默认工作目录下对应子agent名称的文件夹

工具黑名单与固有工具

_tools_blacklist: set[str] = {
    "create_subagent",
    "manage_subagent_protection",
    "protect_subagent",
    "remove_subagent",
    "list_subagents",
    "wait_for_subagent",
    "orchestrate_tasks",
    "broadcast_shared_context",
    "view_shared_context",
}

_tools_inherent: set[str] = {
    "astrbot_execute_shell",
    "astrbot_execute_python",
}
  • 黑名单工具:创建子代理时自动从子代理工具列表中移除,防止子代理获得管理能力
  • 固有工具:创建子代理时自动添加到子代理工具列表,确保基础执行能力

4.3 动态子代理委派 (transfer_to_xxx)

功能描述

创建子代理后,主Agent使用 transfer_to_xxx 工具将任务委派给对应子代理。

实现方式

  • 文件astrbot/core/astr_agent_tool_exec.py
  • 核心方法FunctionToolExecutor._execute_handoff() / _execute_handoff_background()

子代理Prompt构建

# 基础角色定义(由主Agent给出)
subagent_system_prompt = f"# Role\nYour name is {agent_name}(used for tool calling)\n{tool.agent.instructions}\n"

# 其他系统提示词(工作目录、行为规范、Skills)
subagent_system_prompt += SubAgentManager.build_subagent_system_prompt(umo, agent_name, runtime)

# 追加内容(公共上下文、时间信息)
extra_content_parts = SubAgentManager.build_subagent_extra_content_parts(umo, agent_name)

委派执行流程

  1. 主Agent调用 transfer_to_xxx 工具
  2. ToolLoopAgentRunner._handle_function_tools()SubAgentManager 中查找handoff工具
  3. 匹配后返回完整的 HandoffTool 对象
  4. 调用 FunctionToolExecutor._execute_handoff() 执行委派
  5. 构建子代理工具集(包含分配的tools + runtime computer tools + 固有工具),以及子代理的skills
  6. 如果公有上下文启用,自动注入 send_shared_context 工具到子代理工具集
  7. 支持指定 provider_id 使用不同的LLM提供商(默认与主Agent一致)
  8. 加载历史上下文(如果有),合并到contexts中
  9. 通过 _get_subagent_execution_timeout() 获取超时时间
  10. 通过 asyncio.wait_for() 添加执行超时控制
  11. 超时发生时调用 _handle_subagent_timeout() 将状态设为 "FAILED"
  12. 执行完成后,保存运行时消息到历史记录

历史上下文注入流程

  1. 子代理执行前,从 subagent_histories 获取历史消息
  2. 将历史消息转换为 Message 对象
  3. 历史消息插入到 begin_dialogs 之前
  4. 执行完成后,runner_messages(Agent运行期间的所有消息)追加到历史
  5. 过滤system消息,对超过2000字符的tool结果进行截断
  6. 历史消息总数不超过 subagent_history_maxlen(默认300条),超出时保留最新的。(此处仅用于约束SubAgentManager中的列表长度,实际上下文长度仍由astrbot的truncate管理)

执行超时控制

# 获取子代理的超时时间
execution_timeout = cls._get_subagent_execution_timeout()

# 添加执行超时控制
if execution_timeout > 0:
    try:
        llm_resp = await asyncio.wait_for(
            _run_subagent(), timeout=execution_timeout
        )
    except asyncio.TimeoutError:
        error_msg = f"SubAgent '{agent_name}' execution timeout after {execution_timeout:.1f} seconds."
        logger.warning(f"[SubAgent:Timeout] {error_msg}")
        cls._handle_subagent_timeout(umo=umo, agent_name=agent_name)
        # 返回超时错误信息
        yield mcp.types.CallToolResult(
            content=[mcp.types.TextContent(type="text", text=f"error: {error_msg}")]
        )
        return
else:
    # 不设置超时
    llm_resp = await _run_subagent()

4.4 后台任务等待

功能描述

当主Agent认为某个任务耗时很长时,可以让SubAgent以后台模式运行,主Agent不会被阻塞,可继续执行其他可并行的任务

原版Subagent结束任务时,会通过_wake_main_agent_for_background_result唤醒主Agent

如果Subagent耗时很长,Agent的理想做法是等待,例如执行time.sleep()的python代码。但我们要假设LLM是愚蠢的,事实上,许多情况下,主Agent会觉得迟迟拿不到结果而试图自己执行,导致同一任务完成两遍

因此引入了一个wait_for_subagent工具,主Agent需要拿到Subagent结果时,可进行主动的阻塞式等待,避免此类情况发生

实现方式

  • 文件astrbot/core/astr_agent_tool_exec.py
  • 核心方法
    • _execute_handoff_background() - 执行后台委派
    • _do_handoff_background() - 后台任务执行逻辑
    • _register_subagent_task() - 注册SubAgent任务
    • _handle_subagent_background_result() - 处理SubAgent结果
    • _maybe_wake_main_agent_after_background() - 智能唤醒主Agent。Subagent完成任务时,如果主Agent已经结束运行,才执行_wake_main_agent_for_background_result,否则把结果存到subagent_background_results

执行流程

1. 主Agent调用 transfer_to_xxx(background_task=True)
2. 触发 _execute_handoff_background() 方法
3. 调用 _register_subagent_task() 在 SubAgentManager 中创建 pending 任务
   - 如果当前子代理状态为 RUNNING,不允许创建新任务
   - 生成递增的 task_id(数字字符串)
4. 设置子代理状态为 "RUNNING"
5. 返回 task_id 给主Agent(此时主Agent不会被阻塞)
6. SubAgent 在后台异步执行任务(_do_handoff_background)
7. 任务完成后:
   - 结果存储到 subagent_background_results
   - 更新子代理状态为 "COMPLETED" 或 "FAILED"
   - 调用 _maybe_wake_main_agent_after_background() 检查主Agent是否仍在运行
   - 仅在主Agent已结束时,通过 _wake_main_agent_for_background_result 通知用户

主Agent状态检测

后台任务完成后,需要决定是否通知用户。关键逻辑:

# 通过 main_agent_runner 判断主Agent是否仍在运行
context_extra = getattr(run_context.context, "extra", None)
main_agent_runner = context_extra.get("main_agent_runner") if context_extra else None
main_agent_is_running = main_agent_runner is not None and not main_agent_runner.done()

if main_agent_is_running:
    return False  # 主Agent仍在运行,不唤醒,主Agent会自己取出结果
else:
    await cls._wake_main_agent_for_background_result(...)  # 唤醒通知用户
    return True

这依赖 AstrAgentContext.extra 字段,在 build_main_agent() 中注入:

astr_agent_ctx = AstrAgentContext(
    context=plugin_context, event=event, extra={"main_agent_runner": agent_runner}
)

主动等待工具

# 等待特定任务的结果
wait_for_subagent(
    subagent_name="analyst",
    task_id="1",          # 可选,不填则获取最新任务结果
    timeout=60,           # 最大等待时间(秒)
    poll_interval=5       # 轮询间隔(秒)
)

WaitForSubagentTool 轮询逻辑

  1. 如果未指定 task_id,获取最新的 pending 任务
  2. 轮询子代理状态:
    • IDLE → 返回错误:子代理未在运行任务
    • COMPLETED → 返回执行结果
    • FAILED → 返回失败信息
    • RUNNING → 继续等待
  3. 超时后返回提示信息,可再次调用继续等待。

后台Subagent任务管理

每个subagent都会储存结果到subagent_background_results中。同一个subagent可以有多个任务,通过task_id来区分(每次创建任务递增)

subagent_background_results: dict = field(
        default_factory=dict
    )  # 后台subagent结果存储: {agent_name: {task_id: SubAgentExecutionResult}}
    # 任务计数器: {agent_name: next_task_id}
background_task_counters: dict = field(default_factory=dict)

创建任务

    @classmethod
    def create_pending_subagent_task(cls, session_id: str, agent_name: str) -> str:
        """为 SubAgent 创建一个 pending 任务,返回 task_id

        Args:
            session_id: Session ID
            agent_name: SubAgent 名称

        Returns:
            task_id: 任务ID,格式为简单的递增数字字符串
        """

获取结果

    @classmethod
    def get_subagent_result(
        cls, session_id: str, agent_name: str, task_id: str | None = None
    ) -> SubAgentExecutionResult | None:
        """获取 SubAgent 的执行结果

        Args:
            session_id: Session ID
            agent_name: SubAgent 名称
            task_id: 任务ID,如果为None则获取最新完成的任务结果

        Returns:
            SubAgentExecutionResult 或 None
        """

4.5 子代理历史记忆

功能描述

history_enabled=true时,子代理可以保留跨轮对话的历史上下文,实现连续对话能力。

实现方式

  • 存储结构SubAgentSession.subagent_histories
  • 配置subagent_history_maxlen(默认300条)
  • 开关SubAgentManager.is_history_enabled() / set_history_enabled()

历史管理机制

  1. 存储:每次子代理执行完成后,runner_messages(Agent运行期间的消息)追加到历史
  2. 过滤
    • 自动移除 role=system 的消息
    • 对超过 _MAX_TOOL_RESULT_LEN(2000字符)的tool结果截断,附加 ...[truncated]
  3. 截断:历史消息总数超过 subagent_history_maxlen 时,保留最新的消息
  4. 注入:子代理执行前,历史消息转换为 Message 对象,合并到 contexts

历史清理

  • 主Agent可以通过 reset_subagent 工具主动清除指定子代理的历史
  • 如果开启了公共上下文,清理时同时清理与该Agent相关的公共上下文消息

4.6 动态子代理工作目录隔离

功能描述

每个子代理可配置独立的工作目录,未指定时,或工作目录非法时,默认使用 Path(get_astrbot_workspaces_path()) / normalized_umo / agent_name,即主代理默认目录下的子代理文件夹。

实现方式

  • 配置SubAgentConfig.workdir
  • 安全检查CreateSubAgentTool._check_path_safety()
  • Prompt注入_build_workdir_prompt()

注入的工作目录提示

# Working Directory
Your working directory is `{workdir}`. Unless specified by the user, all generated files are saved by default in this directory.

4.7 动态子代理行为规范注入

功能描述

子代理自动注入安全模式、输出规范和时间信息等行为约束。

注入内容

角色定义build_subagent_system_prompt()

# Role
Your name is {agent_name}(used for tool calling)
{base_instructions}

行为规范 _build_rule_prompt(),可由用户在配置中决定。默认配置:

# Behavior Rules
## Safety
{LLM_SAFETY_MODE_SYSTEM_PROMPT}
## Output Guidelines
- If output is long, save it to file. Summarize in your response and provide the file path.
- Mark all generated code/documents with your name and timestamp (if given).

动态时间信息 _build_time_prompt():前两项是静态的,加入到system prompt中;时间信息则加入到附加信息中

DAG 任务状态提示 _TASK_STATUS_PROMPT:当 dag_enabled=true 时,_build_rule_prompt() 会额外注入任务状态标记提示,教导子代理在输出第一行标记 [TASK RESULT: SUCCESS][TASK RESULT: FAILURE],供 DAG 引擎解析

# Current Time
2026-04-14 23:09 (CST)

4.8 Skills隔离

功能描述

修复了Subagent无法使用skills的问题,每个子代理可分配不同的Skills,相互隔离。

注入逻辑

  1. 获取子代理分配的技能列表(SubAgentConfig.skills
  2. 通过 SkillManager.list_skills() 获取所有可用技能
  3. 过滤只保留分配的技能
  4. 调用 build_skills_prompt() 生成提示词
  5. 通过 build_subagent_system_prompt() 注入到子代理的 system_prompt

4.9 公共上下文

功能描述

shared_context_enabled=true 时,维护一个所有子代理共享的、实时更新的群聊区域。在SubAgent每次调用LLM之前,公共上下文的内容会被注入到子代理的追加信息中。

公共上下文中每条信息的格式

message = {
    "type": context_type,  # status, message, system
    "sender": sender,
    "target": target,
    "content": content,
    "timestamp": time.time(),
}

上下文类型

类型 说明 使用场景
status 状态更新 子代理报告任务进度
message 消息传递 子代理间直接通信
system 系统公告 主Agent发布全局信息

公共上下文注入方式

按类型和优先级分组注入到子代理的追加信息中,让Agent可以更清晰地获取共享上下文的信息,并知道哪些需要优先处理。

实现方式

  • 文件astrbot/core/subagent_manager.py
  • 核心方法SubAgentManager._build_shared_context_prompt()

Prompt结构

---
# Shared Context - Collaborative communication area among different agents

## Message Type Definition
- **@ToMe**: Message send to current agent(you), you may need to reply if necessary.
- **@System**: Messages published by the main agent/System that should be followed with priority
- **@AgentName -> @TargetName**: Communication between other agents (for reference)
- **@Status**: The progress of other agents' tasks (can be ignored unless it involves your task)

## Handling Priorities
1. @System messages (highest priority) > @ToMe messages > @Status > @OtherAgents
2. Messages of the same type: In chronological order, with new messages taking precedence

## @System - System Announcements
[时间戳] System: 系统公告内容...

## @ToMe - Messages sent to @当前代理名
 **These messages are addressed to you. If needed, please reply using `send_shared_context`**
[时间戳] @发送者 -> @当前代理名: 消息内容

## @OtherAgents - Communication among Other Agents (Last 10 messages)
[时间戳] AgentA -> AgentB: 消息内容

## @Status - Task progress of each agent (Last 10 messages)
[时间戳] AgentA: 已完成数据清洗
[时间戳] AgentB: 开始数据可视化
---

容量管理

  • 公共上下文消息数超过 shared_context_maxlen 时,保留最近90%的消息
  • 子代理清理时自动移除相关公共上下文消息
  • 所有子代理都被清理后,清除全部公共上下文

公共上下文特点

  • 优先级明确:System消息 > ToMe消息 > Status > 其他Agent之间的通信
  • 相关性过滤:只显示与当前Agent相关的消息
  • 信息精简:其他Agent间通信和状态只显示最近10条,避免信息过载

4.10 主Agent路由提示

功能描述

dynamic_agents.enabled=true 时,在主Agent的System Prompt中注入动态SubAgent能力说明,包括创建指南和委派流程。如果dynamic_agents.enabled=false,则仍然使用router_system_prompt

动态子代理路由的注入内容

核心方法SubAgentManager.build_task_router_prompt()

# Sub-Agent Orchestration
You can manage sub-agents with isolated instructions, tools and skills. Maximum 3 subagents.

## When to Use
Create sub-agents ONLY when:
- Task has ≥2 independent workstreams with clear inputs/outputs
- Context exceeds your effective processing window

## Workflow: Plan → Create → Delegate → Collect → Cleanup
### 1. Create Sub-agent
**Name**: 1 to 32 characters (letters, numbers, or underscores), starting with a letter.
**Required fields:**
| Field | Description |
|-------|-------------|
| Role | Expertise + work style |
| Context | Parent goal, this step, sibling agents |
| Instruction | Input → Process → Output (step-by-step) |
| Tools | **Minimum necessary only** |

### 2. Delegate
- Sequential: `transfer_to_*(...)` — block until return
- Parallel: `transfer_to_*(..., background_task=True)``wait_for_subagent(name, timeout=secs)`

### 3. Collect & Cleanup
- Merge independent outputs by concatenation
- Resolve conflicts by preferring explicit data over inference
- Sub-agents auto-destroy per turn; use `manage_subagent_protection` for multi-turn stateful tasks

4.11 动态子代理的自动清理

功能描述

auto_cleanup_per_turn=true时,每轮对话结束后,自动清理产生的动态子代理。

auto_cleanup_per_turn=true,但又想要保留某个子代理留作后续使用,可以由主agent调用manage_subagent_protection管理工具为子代理添加保护,防止被自动清理。

主Agent也可以根据需要,手动通过manage_subagent_protection移除保护,或直接通过remove_subagent工具清理某个子代理。

清理规则

  1. 遍历所有非保护的子代理
  2. 调用 remove_subagent() 进行清理(移除配置、handoff工具、历史、后台结果)
  3. 清理公共上下文中与被移除Agent相关的消息
  4. 清理后,如果没有子代理剩余,清除全部公共上下文

触发时机

internal.py 的 agent 结束流程中:

if build_cfg.subagent_orchestrator.get("main_enable"):
    if SubAgentManager.is_auto_cleanup_per_turn():
        SubAgentManager.cleanup_session_turn_end(session_id)

4.12 动态子代理数量限制

功能描述

限制单个会话中子代理的最大数量,防止资源耗尽。

注意:替换已存在的同名子代理不增加计数。


4.13 执行超时控制

功能描述

除了原有的工具调用超时外,为每个子代理设置总的执行超时时间,避免无限等待。这是一项全局设置,对所有子代理有效

实现方式

  • 配置SubAgentConfig.execution_timeout(默认1200秒)
  • 全局配置subagent_orchestrator.execution_timeout
  • 核心方法SubAgentManager.get_execution_timeout()

超时处理流程

1. 调用 _get_subagent_execution_timeout() 获取超时时间
2. 通过 asyncio.wait_for() 包装子代理执行协程
3. 超时时:
   a. 记录警告日志
   b. 调用 _handle_subagent_timeout() 将状态设为 "FAILED"
   c. 返回超时错误信息给调用者
4. 执行完成后,正常返回结果

4.14 会话过期清理

功能描述

为防止内存泄漏,SubAgentManager 会自动清理长时间未活跃的会话。默认超时时间为30分钟。

实现方式

  • 核心属性_session_timeout_seconds(默认1800秒 = 30分钟)
  • 核心方法cleanup_expired_sessions()
  • 触发时机cleanup_session_turn_end() 每轮结束时自动调用

清理逻辑

1. 检查所有会话的 last_activity_at 时间
2. 超过 _session_timeout_seconds 的会话标记为过期
3. 清理过期会话中的所有子代理
4. 记录日志:会话ID、不活跃时间、清理的子代理数量

内置/reset命令扩展

/reset用户指令现在会连同当前会话的subagent一起清理


4.15 SubAgent 运行过程追踪(Trace)

功能描述

为主 Agent 和 SubAgent 提供完整、可观测的运行追踪能力。通过层级化 parent_span_id 关联父子关系,追踪覆盖 SubAgent 的创建、执行、工具调用、超时、后台任务全生命周期。前端 TraceDisplayer 拆分为"Main Agent Traces"和"SubAgent Traces"两个独立视图,SubAgent 事件以绿色主题标识,并显示与父事件的关联关系。

实现方式

核心设计:在现有 TraceSpan 中增加可选的 parent_span_id 字段,建立父子 Span 关系。同时将工具调用追踪从 astr_agent_run_util.py 迁移到 tool_loop_agent_runner.py,解决并发 SubAgent 与主 Agent 工具调用追踪记录混淆的问题。

追踪埋点位置

追踪点 所在文件/方法 追踪 Action 说明
SubAgent 创建 SubAgentManager.create_subagent() subagent_created 记录名称、工具、技能、保护状态
SubAgent 状态变更 SubAgentManager.set_subagent_status() subagent_status_change 记录 from_status → to_status
SubAgent 结果存储 SubAgentManager.store_subagent_result() subagent_result_stored 记录 task_id、成功/失败、执行耗时
同步 SubAgent 执行 FunctionToolExecutor._execute_handoff() subagent_execution_beginsubagent_history_loadedsubagent_system_promptsubagent_execution_complete / subagent_execution_timeoutsubagent_history_saved 完整覆盖 SubAgent 执行全链路
后台任务创建 FunctionToolExecutor._execute_handoff_background() subagent_background_task_created 记录 task_id 和 original_task_id
后台任务执行 FunctionToolExecutor._do_handoff_background() subagent_background_execution_startsubagent_background_execution_end 记录成功/失败、结果预览、执行耗时
工具调用(通用) ToolLoopAgentRunner._handle_function_tools() agent_tool_call / agent_tool_result 适用于主 Agent 和 SubAgent,通过 AstrAgentContext.trace_span 区分

关键架构变更

  1. TraceSpan.parent_span_id (astrbot/core/utils/trace.py)

    • 新增可选字段,与主事件建立父子关联
    • 向后兼容:现有主 Agent 追踪不受影响
  2. AstrAgentContext.trace_span (astrbot/core/astr_agent_context.py)

    • 新增字段,SubAgent 执行时传入专属 TraceSpan
    • tool_loop_agent_runner.py 通过该字段将工具调用记录到正确的 Span
  3. SubAgentSession.subagent_traces (astrbot/core/subagent_manager.py)

    • 存储每个 SubAgent 的生命周期 TraceSpan
    • remove_subagent 时自动清理
  4. 前端 TraceDisplayer.vue 重构

    • 拆分为 mainEventsparent_span_id == null)和 subagentEvents 两个计算属性
    • 主 Agent 区域保持蓝色主题,SubAgent 区域使用绿色主题
    • SubAgent 行显示 SA 徽章和 父 Span 引用
    • 新增 parent_span_id 字段到 event 对象
    • 国际化文案同步更新(zh-CN / en-US / ru-RU)

追踪数据流

主事件 (AstrMessageEvent)
  └── trace: TraceSpan (span_id=main-xxx)
        ├── astr_agent_prepare
        ├── agent_tool_call (transfer_to_researcher)
        │       │
        │       ▼
        │   SubAgent TraceSpan (span_id=sub-xxx, parent_span_id=main-xxx)
        │       ├── subagent_execution_begin
        │       ├── subagent_history_loaded
        │       ├── subagent_system_prompt
        │       ├── agent_tool_call (web_search)    ← 通过 trace_span 注入
        │       ├── agent_tool_result               ← 通过 trace_span 注入
        │       ├── subagent_execution_complete
        │       └── subagent_history_saved
        │
        ├── agent_tool_result (transfer_to_researcher)
        └── astr_agent_complete

4.16 DAG 编排

功能描述

dag_enabled=true 时,主 Agent 获得 orchestrate_tasks 工具,可在一次调用中声明 2+ 个子代理任务及其依赖关系。系统自动进行拓扑排序、分层并行执行、前置结果注入以及 Fail-fast 级联失败跳过。

适用场景: 当你有多个独立任务可并行执行,或任务间存在依赖关系时(如 research → analyze → report),优先使用 orchestrate_tasks 而非逐个 transfer_to_*

架构

orchestrate_tasks (LLM Tool)
  └─ SubAgentDAGEngine
       ├─ validate_dag()      验证依赖存在性 + 环检测
       ├─ _kahn_sort()        Kahn 拓扑排序 → 分层
       ├─ execute_dag()       逐层分波并行执行
       │    ├─ _execute_single_node()  单节点: 注入前置结果 → 启动 → 轮询
       │    ├─ _cascade_skip()         失败节点 → BFS 标记所有后继 SKIPPED
       │    └─ _format_dag_result()    聚合为 LLM 可读格式
       └─ _build_injected_context()    构建前置结果注入消息

任务状态检测

子代理通过 _TASK_STATUS_PROMPT 学会在输出第一行标记执行结果:

[TASK RESULT: SUCCESS]

[TASK RESULT: FAILURE]
[FAILURE REASON: API 返回 503]

DAG 引擎解析该标记并提取失败原因,失败节点的完整输出会透传给主 Agent。

Dashboard 配置

SubAgent 编排页面新增「编排方式」下拉:

  • 「默认」→ dag_enabled=false
  • 「DAG 编排」→ dag_enabled=true,展开 dag_max_nodes / dag_max_parallel / dag_max_inject_length 三项配置

Prompt 注入体系

Prompt 注入条件 目标 位置
_DAG_GUIDE_PROMPT dag_enabled=true 主 Agent — 教导 orchestrate_tasks 使用 build_task_router_prompt()
_TASK_STATUS_PROMPT dag_enabled=true 子代理 — 自审计 + 状态标记 _build_rule_prompt()build_subagent_system_prompt()

关键特性

  • Wave-based 并行: 每层分批执行,每波每个 SubAgent 最多运行 1 个任务,防止上下文污染
  • task_id 精确匹配: 替代时间戳启发式,消除并发竞争
  • 前置结果截断: 每个前置结果注入最大 dag_max_inject_length 字符
  • Fail-fast: 任一节点失败,自动 BFS 跳过所有传递后继
  • 会话保护: DAG 运行中 cleanup_session_turn_end() 不清理子代理

限制

  • 单次 DAG 最多 dag_max_nodes(默认 10)个任务节点
  • 暂不支持 DAG 内子代理的交叉通信(公共上下文仍可用于非 DAG 场景)
  • 暂不支持重试机制

五、工具列表

5.1 主Agent新增可用工具

工具名 功能 参数 条件
create_subagent 创建子代理 name, system_prompt, tools, skills, workdir, provider_id dynamic_agents.enabled=true
remove_subagent 清理子代理(支持"all") name dynamic_agents.enabled=true
list_subagents 列出子代理及其状态和工具 include_status dynamic_agents.enabled=true
manage_subagent_protection 保护/取消保护子代理 name, protected (bool) dynamic_agents.enabled=true, auto_cleanup_per_turn=True
view_shared_context 查看公共上下文 - shared_context_enabled=true
broadcast_shared_context 广播公共上下文(以System身份广播,或单独给某个Subagent发指令) context_type, content, target shared_context_enabled=true
wait_for_subagent 等待并获取后台SubAgent结果 subagent_name, task_id, timeout, poll_interval 始终注册
orchestrate_tasks DAG 编排:一次性声明多任务及依赖 tasks(id, agent, prompt, depends_on), max_parallel dag_enabled=true

5.2 子代理可用工具

工具名 功能 参数 说明
send_shared_context 发送公共上下文 context_type, content, sender, target shared_context启用时自动分配该工具
主Agent分配的工具 - - -
固有工具 无论主Agent是否分配,都会注入的工具 - 由配置文件tools_inherent给出

六、修改文件清单

文件路径 修改说明
astrbot/core/subagent_manager.py 新增:为本PR的核心实现,定义了Subagent管理类SubAgentManager,包含会话管理、后台任务管理、历史信息、公共上下文、Prompt构建、会话过期清理、SubAgent追踪埋点、DAG 注册/取消/生命周期管理等;以及配套的SubAgentConfigSubAgentSession数据结构
astrbot/core/subagent_dag.py 新增:DAG 编排引擎,Kahn 拓扑排序、分层并行执行、前置结果注入、级联跳过、结果格式化
astrbot/core/subagent_tools.py 新增:所有子代理管理工具的类定义(create_subagent、remove_subagent、list_subagents、manage_subagent_protection、reset_subagent、broadcast_shared_context、send_shared_context、view_shared_context、wait_for_subagent、orchestrate_tasks 等),这些工具供主Agent进行运行时管理
astrbot/core/astr_agent_tool_exec.py 修改: _execute_handoff()(静态/动态Prompt构建、历史注入、超时控制、SubAgent执行追踪埋点); _execute_handoff_background()(pending任务创建、后台任务追踪埋点);新增 _do_handoff_background()(结果存储与智能唤醒逻辑、后台执行追踪埋点);新增 _register_subagent_task();新增 _load_subagent_history_build_subagent_system_prompt_save_subagent_history_handle_subagent_timeout_is_managed_subagent_handle_subagent_background_result_maybe_wake_main_agent_after_background 等方法封装核心逻辑
astrbot/core/astr_main_agent.py 修改:新增 _apply_subagent_manager_tools(),在 enable_dynamic=True 时注册动态管理工具。在 build_main_agent() 中注入 main_agent_runnerAstrAgentContext.extra
astrbot/core/subagent_orchestrator.py 修改:新增 register_static_subagents_to_manager() 方法;静态subagent自动注册到 SubAgentManager 享受增强功能
astrbot/core/pipeline/process_stage/method/agent_sub_stages/internal.py 修改:读取新版SubAgent配置、每轮结束后调用清理逻辑
astrbot/core/agent/runners/tool_loop_agent_runner.py 修改:_handle_function_tools() 中集成动态SubAgent工具查找;新增 _resolve_dynamic_subagent_tool()_maybe_register_dynamic_tool_from_result() 方法;将工具调用追踪(agent_tool_call / agent_tool_result)迁移至此,通过 AstrAgentContext.trace_span 区分主Agent和SubAgent
astrbot/core/config/default.py 修改:默认配置文件格式,新增dynamic_agentstime_prompt_enabledhistory_enabledshared_context_enabledshared_context_maxlensubagent_history_maxlenexecution_timeout等配置项
astrbot/core/astr_agent_context.py 修改:把extra字段的类型改成dict[str, Any],使得可以记录任意类型的extra信息;新增 trace_span 字段,用于 SubAgent 执行时传入专属 TraceSpan,实现工具调用追踪隔离
astrbot/core/star/context.py 修改:tool_loop_agent() 支持 runner_messages 参数和 trace_span 参数(通过kwargs传递),用于记录SubAgent历史和注入专属TraceSpan
astrbot/builtin_stars/builtin_commands/commands/conversation.py 修改:在 /reset 命令处理中新增 subagent 清理逻辑,调用 SubAgentManager.cleanup_session() 清理当前会话的所有子代理
astrbot/dashboard/routes/subagent.py 修改:Dashboard后端API,新增动态子代理配置项的读取和保存支持
dashboard/src/i18n/locales/en-US/features/subagent.json 修改:英文国际化文件,新增动态子代理相关翻译词条
dashboard/src/i18n/locales/ru-RU/features/subagent.json 修改:俄文国际化文件,新增动态子代理相关翻译词条
dashboard/src/i18n/locales/zh-CN/features/subagent.json 修改:中文国际化文件,新增动态子代理相关翻译词条
dashboard/src/views/SubAgentPage.vue 修改:Dashboard前端页面,新增动态子代理配置界面(全局设置、运行参数、共享上下文、工具策略等分区)
astrbot/core/utils/trace.py 修改:TraceSpan 新增 parent_span_id 可选字段,record() payload 包含 parent_span_id,向后兼容
astrbot/core/astr_agent_run_util.py 修改:移除原工具调用追踪(agent_tool_call / agent_tool_result),迁移至 tool_loop_agent_runner.py
dashboard/src/components/shared/TraceDisplayer.vue 修改:前端追踪展示拆分为 Main Agent Traces 和 SubAgent Traces 双区域;新增 parent_span_id 支持、SA 徽章、父子关系 引用;SubAgent 区域使用绿色主题;新增 mainEvents / subagentEvents 计算属性
dashboard/src/i18n/locales/zh-CN/features/trace.json 修改:更新 hint 文案为「实时展示 AstrBot 主 Agent 及 SubAgent 的完整模型调用链路、工具调用与执行结果」
dashboard/src/i18n/locales/en-US/features/trace.json 修改:同步更新英文 hint 文案
dashboard/src/i18n/locales/ru-RU/features/trace.json 修改:同步更新俄文 hint 文案

七、使用流程

7.1 静态子代理使用流程

与原版一致,但子代理获得增强

1. 在 subagent_orchestrator.agents 中配置子代理,并设置 subagent_orchestrator.main_enable = true
2. 主Agent自动获得 transfer_to_xxx 工具
3. 主Agent使用 transfer_to_xxx 委派任务
4. 子代理执行任务并返回结果
5. 主Agent整合结果回复用户
6. 如果配置文件中允许,静态子代理可以被赋予历史上下文记忆、公共上下文交互等增强功能

7.2 动态子代理使用流程

1. 设置 subagent_orchestrator.main_enable = true
2. 设置 subagent_orchestrator.dynamic_agents.enabled = true
3. 主Agent识别需要创建子代理,调用 create_subagent 工具
4. 系统在运行时创建子代理和 transfer_to_xxx 工具
5. 主Agent使用 transfer_to_xxx 委派任务
6. 子代理执行任务并返回结果
7. 主Agent整合结果回复用户
8. 动态子代理被自动清理(如果auto_cleanup_per_turn = true)

7.3 带保护的多轮对话流程

当动态子代理被保护时,不会被自动清理

第1轮:
  用户 -> 主Agent: 创建分析师,帮我分析数据
  主Agent -> create_subagent(analyst)
  主Agent -> manage_subagent_protection(analyst, protected=true)
  主Agent -> transfer_to_analyst(分析这份数据)
  分析师 -> 返回分析结果
  用户 <- 主Agent <- 分析结果
  (轮结束后,analyst因受保护不会被清理)

第2轮:
  用户 -> 主Agent: 继续分析另一份数据
  主Agent -> transfer_to_analyst(分析新数据)  // 分析师带历史上下文
  分析师(带历史上下文) -> 返回新分析结果
  用户 <- 主Agent <- 新结果

7.4 带公共上下文的协作流程

1. 启用 shared_context_enabled=true
2. 主Agent创建多个SubAgent
3. 子代理A: send_shared_context(status, "已完成数据清洗"), send_shared_context(message, A, B, "请子代理B开始数据可视化")
4. 子代理B: send_shared_context(status, "开始数据可视化"), send_shared_context(message, B, A, "我已收到,开始执行数据可视化")
5. 子代理C: 可看到A和B的状态更新
6. 主Agent: 公共上下文不会自动注入给主Agent,但可以调用view_shared_context() 查看,或通过 broadcast_shared_context() 广播消息

7.5 后台任务并行处理流程

复杂场景:用户要求同时进行数据分析、文件处理、报告生成三个任务。同时用户要求打开浏览器。
        该过程可以同时包含前台和后台任务,并具有复杂的数据相关

主Agent决策:
  1. 分析四个任务可以并行执行,而数据分析任务可能要执行多步,执行的步数依赖于上一次分析的结果。
  2. 系统给出了3个Subagent的最大限制,因此创建三个SubAgent,分别负责前三个不同任务。自己负责剩下的浏览器任务
  3. 使用 background_task=True 委派任务

执行流程:
  主Agent -> create_subagent(data_analyst)
  主Agent -> create_subagent(file_processor)
  主Agent -> create_subagent(report_generator)

  主Agent -> transfer_to_data_analyst(分析数据, background_task=True)
  主Agent -> transfer_to_file_processor(处理文件, background_task=True)
  主Agent -> transfer_to_report_generator(生成报告, background_task=True)

  # 主Agent此时可以继续处理其他不依赖SubAgent的任务
  主Agent 可以去处理其他事情(打开浏览器)

  # 或者主Agent有任务需要等待某个SubAgent的结果
  主Agent -> wait_for_subagent(subagent_name="data_analyst")
  # 获取到数据分析师的结果后
  主Agent -> 评审数据分析师的结果,判断是否继续分析
  主Agent -> transfer_to_data_analyst(分析剩余的少量数据, background_task=false)
  主Agent -> 由于是background_task=false,直接能拿到结果

  # 所有任务完成后,整合结果
  主Agent -> wait_for_subagent(subagent_name="file_processor")
  主Agent -> wait_for_subagent(subagent_name="report_generator")
  主Agent -> 整合所有结果回复用户

7.6 后台任务与共享上下文结合

场景:多个SubAgent并行处理数据,最后汇总结果

1. 创建处理Agent和汇总Agent
   主Agent -> create_subagent(handler_a, ...)
   主Agent -> create_subagent(handler_b, ...)
   主Agent -> create_subagent(summarizer, ...)

2. Handler A和B以后台模式并行处理
   主Agent -> transfer_to_handler_a(处理数据A, background_task=True)
   主Agent -> transfer_to_handler_b(处理数据B, background_task=True)

3. 处理完成后,发布状态到共享上下文
   handler_a -> send_shared_context(status, "数据A处理完成,结果保存到文件X")
   handler_b -> send_shared_context(status, "数据B处理完成,结果保存到文件Y")

4. 汇总Agent看到状态后,开始汇总
   summarizer 可以看到:
     @Status: handler_a - 数据A处理完成,结果保存到文件X
     @Status: handler_b - 数据B处理完成,结果保存到文件Y

   主Agent -> transfer_to_summarizer(汇总处理结果)
   summarizer -> 读取文件X和Y,生成汇总报告

5. 主Agent获取最终结果
   主Agent -> wait_for_subagent(subagent_name="summarizer")
   主Agent -> 将汇总报告发送给用户

7.7 DAG 编排流程

场景:用户要求研究 Python 异步最佳实践 + 分析现有代码 + 撰写迁移报告 + 生成代码示例。
      其中"研究"和"分析"可以并行,"报告"依赖两者,"示例"依赖"报告"。

1. 启用 dag_enabled=true(Dashboard 或配置文件)
2. 确保所需的子代理已存在(静态或动态创建)
3. 主 Agent 通过 orchestrate_tasks 一次性声明所有任务:

   orchestrate_tasks(tasks=[
     {"id": "research",  "agent": "researcher",   "prompt": "Search Python async best practices 2026"},
     {"id": "analyze",   "agent": "code-reviewer", "prompt": "Analyze codebase async patterns"},
     {"id": "report",    "agent": "writer",        "prompt": "Write migration report",
      "depends_on": ["research", "analyze"]},
     {"id": "examples",  "agent": "coder",         "prompt": "Generate code examples",
      "depends_on": ["report"]}
   ])

执行过程:
  Layer 0 (2 parallel): research, analyze → 并发执行
  Layer 1: report → 等待 research+analyze 完成后,注入两者结果执行
  Layer 2: examples → 等待 report 完成后,注入报告执行

4. 若 research 失败 → analyze 不受影响继续运行,但 report 被级联跳过
5. 系统返回格式化结果:✅ 全部成功,或 ❌ 含失败/跳过的汇总

八、API 参考

8.1 SubAgentManager 核心方法

配置与生命周期

方法签名 说明
configure(max_subagent_count, auto_cleanup_per_turn, shared_context_enabled, shared_context_maxlen, subagent_history_maxlen, tools_blacklist, tools_inherent, execution_timeout, history_enabled, rule_prompt, time_prompt_enabled, timezone, dag_enabled, default_provider_id) 全局配置
get_execution_timeout() -> float 获取执行超时时间
is_auto_cleanup_per_turn() -> bool 检查是否启用自动清理
is_shared_context_enabled() -> bool 检查是否启用公共上下文
is_history_enabled() -> bool 检查是否启用子代理历史记忆
set_history_enabled(session_id, enabled) 启用/禁用指定会话的子代理历史记忆
register_blacklisted_tool(tool_name) 注册不应被子Agent使用的工具
register_inherent_tool(tool_name) 注册子Agent默认拥有的工具
cleanup_expired_sessions() -> dict 清理过期会话,防止内存泄漏
register_dag(session_id, dag_ctx) -> None 注册 DAG 执行上下文到会话
get_active_dag(session_id) -> DAGExecutionContext | None 获取当前活跃的 DAG 执行上下文
cancel_dag(session_id) -> dict 取消当前活跃的 DAG 执行
_filter_skills_for_current_config(skills) -> list 按插件激活状态过滤 skills 列表

子代理管理

方法签名 说明
create_subagent(session_id, config, protected=False) -> tuple 创建子代理,返回(tool_name, handoff_tool)
register_static_subagent(session_id, handoff_tool, skills, workdir) -> tuple 注册静态子代理到管理器(自动protected=True)
remove_subagent(session_id, agent_name) -> str 移除子代理(name="all"移除全部)
protect_subagent(session_id, agent_name) 保护子代理
is_protected(session_id, agent_name) -> bool 检查是否受保护
set_subagent_status(session_id, agent_name, status) 设置子代理状态
cleanup_session_turn_end(session_id) -> dict 结束时清理
cleanup_session(session_id) -> dict 清理整个会话
get_handoff_tools_for_session(session_id) -> list 获取会话的handoff工具列表
get_subagent_tools(session_id, agent_name) -> list | None 获取子代理的工具列表

历史管理

方法签名 说明
update_subagent_history(session_id, agent_name, current_messages) 更新历史(自动过滤system消息、截断tool结果)
get_subagent_history(session_id, agent_name) -> list 获取历史
clear_subagent_history(session_id, agent_name) -> str 清除历史

Prompt构建

方法签名 说明
build_task_router_prompt(session_id) -> str 构建主Agent路由提示,告诉主Agent可以动态创建和管理子代理
build_subagent_system_prompt(session_id, agent_name, runtime) -> str 构建subagent系统提示(人格、工作目录、行为规范、Skills)
build_subagent_extra_content_parts(session_id, agent_name) -> list 构建追加内容(公共上下文、时间信息)

后台任务管理

方法签名 说明
create_pending_subagent_task(session_id, agent_name) -> str 创建pending任务,返回task_id
get_pending_subagent_tasks(session_id, agent_name) -> list[str] 获取所有pending任务ID
get_latest_task_id(session_id, agent_name) -> str | None 获取最新任务ID
store_subagent_result(session_id, agent_name, success, result, task_id, error, execution_time, metadata) 存储执行结果
get_subagent_result(session_id, agent_name, task_id) -> SubAgentExecutionResult | None 获取执行结果
has_subagent_result(session_id, agent_name, task_id) -> bool 检查是否有结果
clear_subagent_result(session_id, agent_name, task_id) 清除执行结果
get_subagent_status(session_id, agent_name) -> str 获取状态:IDLE/RUNNING/COMPLETED/FAILED
get_all_subagent_status(session_id) -> dict 获取所有SubAgent状态

公共上下文管理

方法签名 说明
add_shared_context(session_id, sender, context_type, content, target) 添加公共上下文消息
get_shared_context(session_id, filter_by_agent) -> list 获取公共上下文
set_shared_context_enabled(session_id, enabled) 启用/禁用公共上下文
cleanup_shared_context_by_agent(session_id, agent_name) 清理与指定Agent相关的消息
clear_shared_context(session_id) 清除所有公共上下文

8.2 SubAgentExecutionResult 数据结构

# 用于记录每个subagent的执行结果
@dataclass
class SubAgentExecutionResult:
    task_id: str           # 任务唯一标识符(递增数字字符串)
    agent_name: str        # SubAgent名称
    success: bool          # 是否成功
    result: str | None     # 执行结果
    error: str | None      # 错误信息
    execution_time: float  # 执行耗时(秒)
    created_at: float      # 创建时间戳
    completed_at: float    # 完成时间戳
    metadata: dict         # 额外元数据

8.3 SubAgentConfig 数据结构

# 用于定义每个subagent
@dataclass
class SubAgentConfig:
    name: str                          # subagent名字
    system_prompt: str = ""            # subagent系统提示词
    tools: set[str] | None = None      # subagent工具集合
    skills: set[str] | None = None     # subagent skill集合
    provider_id: str | None = None     # subagent provider id
    description: str = ""              # subagent 描述,对应handoff_tool的描述
    workdir: str | None = None         # subagent工作目录
    execution_timeout: float = 600.0   # 执行超时时间(秒)

8.4 SubAgentSession 数据结构

# 存储每个会话的subagent所有相关信息
@dataclass
class SubAgentSession:
    session_id: str                                     # 会话ID
    subagents: dict = field(default_factory=dict)       # 存储SubAgentConfig对象
    handoff_tools: dict = field(default_factory=dict)   # 存储handoff工具列表
    subagent_status: dict = field(                      # 存储每个subagent的工作状态,{agent_name: SubAgentStatus 枚举值}
      default_factory=dict                              # 状态包括 "IDLE" "RUNNING" "COMPLETED" "FAILED"
    )  
    protected_agents: set = field(                      # 受保护的subagent列表,若某个agent受到保护,则不会被自动清理
        default_factory=set
    ) 
    history_enabled: bool = True                        # 是否保存子代理历史
    subagent_histories: dict = field(default_factory=dict)  # 存储每个subagent的历史上下文
    shared_context: list = field(default_factory=list) # 公共上下文列表
    shared_context_enabled: bool = False               # 是否启用公共上下文
    subagent_background_results: dict = field(
        default_factory=dict
    )                                                  # 后台subagent结果存储: {agent_name: {task_id: SubAgentExecutionResult}}
    background_task_counters: dict = field(default_factory=dict)   # 任务计数器: {agent_name: next_task_id}
    subagent_traces: dict = field(default_factory=dict)  # 每个子代理的 TraceSpan: {agent_name: TraceSpan}
    active_dag: DAGExecutionContext | None = None  # 当前活跃的 DAG 执行上下文
    dag_history: list = field(default_factory=list)  # 已完成的 DAG 历史记录
    last_activity_at: float = field(default_factory=time.time)  # 最后活跃时间戳

Screenshots or Test Results / 运行截图或测试结果

Dashboard页面

suabgent_dashboard2

运行示例

截图

subagent_example

日志记录

[18:09:56.103] [Core] [INFO] [core.event_bus:61]: [Astrbot专家] [webchat(webchat)] astrbot/astrbot: 请创建三个不同风格的诗人子代理,分别写一首诗,并由你汇总为一个.md文件
[18:09:56.228] [Core] [INFO] [core.subagent_manager:710]: [SubAgent:History] Subagent history enabled
[18:09:56.228] [Core] [INFO] [core.subagent_manager:720]: [SubAgent:SharedContext] Shared context enabled
[18:09:56.233] [Core] [INFO] [respond.stage:183]: Prepare to send - astrbot/astrbot:
[18:09:56.233] [Core] [INFO] [respond.stage:199]: 应用流式输出(webchat)
[18:10:02.980] [Core] [INFO] [core.astr_main_agent:976]: Generated chatui title for session 14c57255-2002-4e8d-ab6a-a4b420b765fe: 创建诗人子代理并汇总诗作
[18:10:18.385] [Core] [INFO] [runners.tool_loop_agent_runner:976]: Agent 使用工具: ['create_subagent', 'create_subagent', 'create_subagent']
[18:10:18.386] [Core] [INFO] [runners.tool_loop_agent_runner:1042]: 使用工具:create_subagent,参数:{'name': 'classical_poet', 'system_prompt': '你是一位中国古典风格诗人,精通唐诗宋词的格律与意境。\n\n创作风格:\n- 讲究平仄对仗,意境深远\n- 善用典故,借景抒情\n- 语言凝练典雅,富有画面感\n- 主题多为山水、离别、怀古、人生感悟\n\n输出要求:\n- 创作一首古典风格的诗歌(律诗或绝句形式)\n- 在诗后附上简短的赏析(2-3句话)\n- 标注诗歌体裁(如:七言绝句、五言律诗等)'}
[18:10:18.397] [Core] [INFO] [core.subagent_manager:843]: [SubAgent:Create] Created subagent: classical_poet (protected=False)
[18:10:18.398] [Core] [INFO] [runners.tool_loop_agent_runner:1491]: [SubAgent] Tool created: transfer_to_classical_poet
[18:10:18.399] [Core] [INFO] [runners.tool_loop_agent_runner:1510]: [SubAgent] Added transfer_to_classical_poet to func_tool set
[18:10:18.400] [Core] [INFO] [runners.tool_loop_agent_runner:1245]: Tool create_subagent Result: DYNAMIC_TOOL_CREATED:transfer_to_classical_poet:transfer_to_classical_poet:Created. Use transfer_to_classical_poet to delegate.
[18:10:18.401] [Core] [INFO] [runners.tool_loop_agent_runner:1042]: 使用工具:create_subagent,参数:{'name': 'modern_poet', 'system_prompt': '你是一位中国现代派诗人,受新月派、朦胧诗等现代诗歌流派影响。\n\n创作风格:\n- 打破传统格律,追求自由表达\n- 善用意象叠加与隐喻象征\n- 关注现代都市生活与个体精神困境\n- 语言简洁但富有张力,留白与跳跃感并存\n\n输出要求:\n- 创作一首现代自由诗(8-16行)\n- 在诗后附上简短的创作手记(2-3句话)\n- 标注诗歌主题'}
[18:10:18.411] [Core] [INFO] [core.subagent_manager:843]: [SubAgent:Create] Created subagent: modern_poet (protected=False)
[18:10:18.412] [Core] [INFO] [runners.tool_loop_agent_runner:1491]: [SubAgent] Tool created: transfer_to_modern_poet
[18:10:18.412] [Core] [INFO] [runners.tool_loop_agent_runner:1510]: [SubAgent] Added transfer_to_modern_poet to func_tool set
[18:10:18.413] [Core] [INFO] [runners.tool_loop_agent_runner:1245]: Tool create_subagent Result: DYNAMIC_TOOL_CREATED:transfer_to_modern_poet:transfer_to_modern_poet:Created. Use transfer_to_modern_poet to delegate.
[18:10:18.414] [Core] [INFO] [runners.tool_loop_agent_runner:1042]: 使用工具:create_subagent,参数:{'name': 'romantic_poet', 'system_prompt': '你是一位浪漫主义诗人,深受西方浪漫主义与中国抒情传统影响。\n\n创作风格:\n- 情感浓烈奔放,直抒胸臆\n- 歌颂自然之美、爱情之纯、理想之光\n- 想象瑰丽,善用夸张与排比\n- 语言华丽优美,节奏舒缓如歌\n\n输出要求:\n- 创作一首浪漫主义风格的抒情诗(12-20行)\n- 在诗后附上简短的情感寄语(2-3句话)\n- 标注诗歌献给的对象或主题'}
[18:10:18.425] [Core] [INFO] [core.subagent_manager:843]: [SubAgent:Create] Created subagent: romantic_poet (protected=False)
[18:10:18.426] [Core] [INFO] [runners.tool_loop_agent_runner:1491]: [SubAgent] Tool created: transfer_to_romantic_poet
[18:10:18.427] [Core] [INFO] [runners.tool_loop_agent_runner:1510]: [SubAgent] Added transfer_to_romantic_poet to func_tool set
[18:10:18.429] [Core] [INFO] [runners.tool_loop_agent_runner:1245]: Tool create_subagent Result: DYNAMIC_TOOL_CREATED:transfer_to_romantic_poet:transfer_to_romantic_poet:Created. Use transfer_to_romantic_poet to delegate.

[SYSTEM NOTICE] By the way, you have executed the same tool create_subagent 3 times consecutively. Double-check whether another tool, different arguments, or a summary would move the task forward better.
[18:10:26.487] [Core] [INFO] [runners.tool_loop_agent_runner:976]: Agent 使用工具: ['transfer_to_classical_poet', 'transfer_to_modern_poet', 'transfer_to_romantic_poet']
[18:10:26.487] [Core] [INFO] [runners.tool_loop_agent_runner:1042]: 使用工具:transfer_to_classical_poet,参数:{'input': '请以"初夏黄昏"为主题,创作一首古典风格的诗歌。要求体现初夏时节黄昏时分的景色与心境,包含对时光流逝的淡淡感慨。请直接输出诗歌内容、体裁标注和赏析。', 'background_task': True}
[18:10:26.488] [Core] [INFO] [core.astr_agent_tool_exec:924]: [SubAgent:BackgroundTask] Created background task 1 for classical_poet
[18:10:26.520] [Core] [INFO] [runners.tool_loop_agent_runner:1245]: Tool transfer_to_classical_poet Result: Background task submitted. subagent_task_id=1. SubAgent 'classical_poet' is working on the task. Use wait_for_subagent(subagent_name='classical_poet', task_id='1') to get the result.
[18:10:26.520] [Core] [INFO] [runners.tool_loop_agent_runner:1042]: 使用工具:transfer_to_modern_poet,参数:{'input': '请以"城市霓虹下的独行者"为主题,创作一首现代自由诗。要求体现都市夜晚的孤独感与现代人的精神漂泊,同时保留一丝对未来的希望。请直接输出诗歌内容、主题标注和创作手记。', 'background_task': True}
[18:10:26.521] [Core] [INFO] [core.astr_agent_tool_exec:924]: [SubAgent:BackgroundTask] Created background task 1 for modern_poet
[18:10:26.534] [Core] [INFO] [runners.tool_loop_agent_runner:1245]: Tool transfer_to_modern_poet Result: Background task submitted. subagent_task_id=1. SubAgent 'modern_poet' is working on the task. Use wait_for_subagent(subagent_name='modern_poet', task_id='1') to get the result.
[18:10:26.535] [Core] [INFO] [runners.tool_loop_agent_runner:1042]: 使用工具:transfer_to_romantic_poet,参数:{'input': '请以"致远方的星辰"为主题,创作一首浪漫主义风格的抒情诗。要求表达对遥远理想的追寻与对美好事物的永恒向往,情感真挚热烈。请直接输出诗歌内容、主题标注和情感寄语。', 'background_task': True}
[18:10:26.536] [Core] [INFO] [core.astr_agent_tool_exec:924]: [SubAgent:BackgroundTask] Created background task 1 for romantic_poet
[18:10:26.554] [Core] [INFO] [runners.tool_loop_agent_runner:1245]: Tool transfer_to_romantic_poet Result: Background task submitted. subagent_task_id=1. SubAgent 'romantic_poet' is working on the task. Use wait_for_subagent(subagent_name='romantic_poet', task_id='1') to get the result.
[18:10:30.621] [Core] [INFO] [runners.tool_loop_agent_runner:976]: Agent 使用工具: ['wait_for_subagent', 'wait_for_subagent', 'wait_for_subagent']
[18:10:30.622] [Core] [INFO] [runners.tool_loop_agent_runner:1042]: 使用工具:wait_for_subagent,参数:{'subagent_name': 'classical_poet', 'timeout': 60}
[18:10:35.649] [Core] [INFO] [runners.tool_loop_agent_runner:1245]: Tool wait_for_subagent Result: SubAgent 'classical_poet' execution completed
Task id: 1
Execution time: 5.4s
--- Result ---

初夏黄昏

七言绝句

绿槐高柳咽新蝉,
薰风初入小庭前。
斜阳影里人独立,
一霎微凉又一年。


赏析

此诗以初夏黄昏为背景,前两句写绿槐高柳间新蝉初鸣、薰风轻过小庭之景,声色交融,尽显初夏生机;后两句转入抒情,斜阳独立之人忽觉微凉,顿感流光易逝,"又一年"三字将淡淡惆怅轻轻托出,余韵悠长。全诗以景起以情结,含蓄蕴藉,颇得唐人绝句风神。

[18:10:35.650] [Core] [INFO] [runners.tool_loop_agent_runner:1042]: 使用工具:wait_for_subagent,参数:{'subagent_name': 'modern_poet', 'timeout': 60}
[18:10:44.899] [Core] [INFO] [runners.tool_loop_agent_runner:976]: Agent 使用工具: ['astrbot_file_write_tool']
[18:10:44.899] [Core] [INFO] [runners.tool_loop_agent_runner:1042]: 使用工具:astrbot_file_write_tool,参数:{'path': '城市霓虹下的独行者.md', 'content': '# 城市霓虹下的独行者\n\n> 作者:modern_poet \n> 创作时间:2026-05-11 18:10 (CST)\n\n---\n\n## 霓虹之下\n\n地铁口的风卷起一张旧报纸,\n像只折翼的鸟,撞向玻璃幕墙——\n碎成二十四楼的倒影。\n\n便利店永远亮着,\n关东煮在塑料盒里浮沉,\n如同我们,在格子间里\n数着秒针,等一个不会来的春天。\n\n天桥上有人弹唱,\n吉他箱里躺着几枚硬币,\n和一张去远方的车票,\n日期是昨天。\n\n而霓虹从不熄灭,\n它把每个人的影子\n拉得很长,很长——\n长到可以当作一条回家的路。\n\n---\n\n主题:城市霓虹下的独行者\n\n---\n\n创作手记:\n\n这首诗以都市夜晚的典型意象——地铁口、便利店、天桥弹唱者——构建了一幅现代漂泊者的精神图景。霓虹既是围困的光,也是指引的灯;旧报纸与远方车票暗示着被折叠的梦想,而"影子拉成回家的路"则在孤独中保留了一丝温柔的期盼。我希望读者能在这些碎片中,看见自己,也看见彼此。\n'}
[18:10:44.906] [Core] [INFO] [runners.tool_loop_agent_runner:1245]: Tool astrbot_file_write_tool Result: File written successfully: F:\github\Astrbot\data\workspaces\webchat_FriendMessage_webchat_astrbot_14c57255-2002-4e8d-ab6a-a4b420b765fe\城市霓虹下的独行者.md
[18:11:00.677] [Core] [INFO] [runners.tool_loop_agent_runner:1245]: Tool wait_for_subagent Result: SubAgent 'modern_poet' execution completed
Task id: 1
Execution time: 33.9s
--- Result ---
诗歌已创作完成并保存至文件。以下是内容展示:


霓虹之下

地铁口的风卷起一张旧报纸,
像只折翼的鸟,撞向玻璃幕墙——
碎成二十四楼的倒影。

便利店永远亮着,
关东煮在塑料盒里浮沉,
如同我们,在格子间里
数着秒针,等一个不会来的春天。

天桥上有人弹唱,
吉他箱里躺着几枚硬币,
和一张去远方的车票,
日期是昨天。

而霓虹从不熄灭,
它把每个人的影子
拉得很长,很长——
长到可以当作一条回家的路。


主题:城市霓虹下的独行者


创作手记

这首诗以都市夜晚的典型意象——地铁口、便利店、天桥弹唱者——构建了一幅现代漂泊者的精神图景。霓虹既是围困的光,也是指引的灯;旧报纸与远方车票暗示着被折叠的梦想,而"影子拉成回家的路"则在孤独中保留了一丝温柔的期盼。我希望读者能在这些碎片中,看见自己,也看见彼此。


📄 文件路径F:\github\Astrbot\data\workspaces\webchat_FriendMessage_webchat_astrbot_14c57255-2002-4e8d-ab6a-a4b420b765fe\城市霓虹下的独行者.md

[18:11:00.678] [Core] [INFO] [runners.tool_loop_agent_runner:1042]: 使用工具:wait_for_subagent,参数:{'subagent_name': 'romantic_poet', 'timeout': 60}
[18:11:00.681] [Core] [INFO] [runners.tool_loop_agent_runner:1245]: Tool wait_for_subagent Result: SubAgent 'romantic_poet' has no pending tasks. Latest completed task id: 1. Task id 1 Results:

致远方的星辰


致远方的星辰

当夜幕垂落如深蓝的绸缎,
我便仰望你,那遥远的光点。
亿万里的虚空无法冷却我的凝望,
你是理想在天穹点燃的火焰!

我穿越荆棘丛生的山谷与荒原,
只为追逐你抛洒的一线银辉。
风暴撕裂我的斗篷,泥泞吞没我的步履,
可你依然高悬——我永恒的方位。

啊,星辰!你是诗人梦中的圣殿,
是旅人寒夜里不灭的灯盏。
纵使穷尽一生也无法抵达你的身旁,
我仍将整个灵魂,化作向你飞翔的翅膀。

让世俗在脚下沉沦成灰色的尘埃吧,
我的心,永远向着璀璨的存在!


主题:致远方的星辰——献给所有追寻理想与美好的人们

情感寄语:愿我们都能成为自己的星辰,在漫长黑夜里为彼此照亮前路。理想或许永远在前方,但追寻本身已让生命绽放光芒。


romantic_poet | 2026-05-11 18:10 (CST)

[SYSTEM NOTICE] By the way, you have executed the same tool wait_for_subagent 3 times consecutively. Double-check whether another tool, different arguments, or a summary would move the task forward better.
[18:11:30.271] [Core] [INFO] [runners.tool_loop_agent_runner:976]: Agent 使用工具: ['astrbot_file_write_tool']
[18:11:30.272] [Core] [INFO] [runners.tool_loop_agent_runner:1042]: 使用工具:astrbot_file_write_tool,参数:{'path': 'D:\AstrbotWorkSpace\三诗人合集.md', 'content': '# 三诗人合集\n\n> 编者注:本合集由三位不同风格的诗人子代理独立创作,分别代表古典、现代、浪漫三种诗歌美学。\n>\n> 汇总时间:2026-05-11 18:10 (CST)\n> 编者:AstrBot 开发专家\n\n---\n\n## 一、古典诗人 · 初夏黄昏\n\n体裁:七言绝句\n\n> 绿槐高柳咽新蝉, \n> 薰风初入小庭前。 \n> 斜阳影里人独立, \n> 一霎微凉又一年。\n\n赏析:此诗以初夏黄昏为背景,前两句写绿槐高柳间新蝉初鸣、薰风轻过小庭之景,声色交融,尽显初夏生机;后两句转入抒情,斜阳独立之人忽觉微凉,顿感流光易逝,"又一年"三字将淡淡惆怅轻轻托出,余韵悠长。全诗以景起以情结,含蓄蕴藉,颇得唐人绝句风神。\n\n---\n\n## 二、现代诗人 · 霓虹之下\n\n主题:城市霓虹下的独行者\n\n> 地铁口的风卷起一张旧报纸, \n> 像只折翼的鸟,撞向玻璃幕墙—— \n> 碎成二十四楼的倒影。\n>\n> 便利店永远亮着, \n> 关东煮在塑料盒里浮沉, \n> 如同我们,在格子间里 \n> 数着秒针,等一个不会来的春天。\n>\n> 天桥上有人弹唱, \n> 吉他箱里躺着几枚硬币, \n> 和一张去远方的车票, \n> 日期是昨天。\n>\n> 而霓虹从不熄灭, \n> 它把每个人的影子 \n> 拉得很长,很长—— \n> 长到可以当作一条回家的路。\n\n创作手记:这首诗以都市夜晚的典型意象——地铁口、便利店、天桥弹唱者——构建了一幅现代漂泊者的精神图景。霓虹既是围困的光,也是指引的灯;旧报纸与远方车票暗示着被折叠的梦想,而"影子拉成回家的路"则在孤独中保留了一丝温柔的期盼。我希望读者能在这些碎片中,看见自己,也看见彼此。\n\n---\n\n## 三、浪漫诗人 · 致远方的星辰\n\n献给:所有追寻理想与美好的人们\n\n> 当夜幕垂落如深蓝的绸缎, \n> 我便仰望你,那遥远的光点。 \n> 亿万里的虚空无法冷却我的凝望, \n> 你是理想在天穹点燃的火焰!\n>\n> 我穿越荆棘丛生的山谷与荒原, \n> 只为追逐你抛洒的一线银辉。 \n> 风暴撕裂我的斗篷,泥泞吞没我的步履, \n> 可你依然高悬——我永恒的方位。\n>\n> 啊,星辰!你是诗人梦中的圣殿, \n> 是旅人寒夜里不灭的灯盏。 \n> 纵使穷尽一生也无法抵达你的身旁, \n> 我仍将整个灵魂,化作向你飞翔的翅膀。\n>\n> 让世俗在脚下沉沦成灰色的尘埃吧, \n> 我的心,永远向着璀璨的存在!\n\n情感寄语:愿我们都能成为自己的星辰,在漫长黑夜里为彼此照亮前路。理想或许永远在前方,但追寻本身已让生命绽放光芒。\n\n---\n\n## 编后记\n\n三首诗,三种时空,三种心境:\n\n- 古典诗人在小庭斜阳中感怀流年,以二十八字道尽中国文人的时间意识;\n- 现代诗人在霓虹倒影里打捞都市人的碎片,用断裂的意象拼贴当代精神图谱;\n- 浪漫诗人向星辰敞开灵魂,以炽热的宣言捍卫理想主义的最后堡垒。\n\n它们共同构成了一幅人类情感的完整光谱——从含蓄到直白,从孤独到热烈,从回望到追寻。\n\n> "诗无达诂,而心有灵犀。"\n\n---\n\n本文档由 AstrBot Agent Harness 编排生成 \n生成时间:2026-05-11 18:10 (CST)\n'}
[18:11:30.278] [Core] [INFO] [runners.tool_loop_agent_runner:1245]: Tool astrbot_file_write_tool Result: File written successfully: D:\AstrbotWorkSpace\三诗人合集.md
[18:11:32.338] [Core] [INFO] [runners.tool_loop_agent_runner:976]: Agent 使用工具: ['remove_subagent']
[18:11:32.339] [Core] [INFO] [runners.tool_loop_agent_runner:1042]: 使用工具:remove_subagent,参数:{'name': 'all'}
[18:11:32.340] [Core] [INFO] [core.subagent_manager:953]: [SubAgent:Cleanup] All subagents cleaned.
[18:11:32.342] [Core] [INFO] [runners.tool_loop_agent_runner:1245]: Tool remove_subagent Result: SUBAGENT_REMOVED: All subagents have been removed.
[18:11:42.244] [Core] [INFO] [result_decorate.stage:189]: 流式输出已启用,跳过结果装饰阶段

日志追踪功能

subagent_traces subagent_traces2

DAG编排演示

subagent_example2

详细测试报告

详见
test_report.zip


Checklist / 检查清单

  • 😊 If there are new features added in the PR, I have discussed it with the authors through issues/emails, etc.
    / 如果 PR 中有新加入的功能,已经通过 Issue / 邮件等方式和作者讨论过。

  • 👀 My changes have been well-tested, and "Verification Steps" and "Screenshots" have been provided above.
    / 我的更改经过了良好的测试,并已在上方提供了“验证步骤”和“运行截图”

  • 🤓 I have ensured that no new dependencies are introduced, OR if new dependencies are introduced, they have been added to the appropriate locations in requirements.txt and pyproject.toml.
    / 我确保没有引入新依赖库,或者引入了新依赖库的同时将其添加到 requirements.txtpyproject.toml 文件相应位置。

  • 😮 My changes do not introduce malicious code.
    / 我的更改没有引入恶意代码。

@elecvoid243

Copy link
Copy Markdown
Contributor Author

已通过内部生产环境测试。后续会考虑加入缓存友好的fork模式

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] 增强版的SubAgent功能

1 participant