> ## Documentation Index
> Fetch the complete documentation index at: https://docs.veadk.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# 动态智能体委派

## 功能说明

导入路径：`from veadk.tools.builtin_tools.create_agent import CreateAgentToolset`

`CreateAgentToolset` 是一个内置工具集，让主智能体在运行时收集可用资源、按任务需要创建一个或多个子智能体，并通过 Google ADK 的 `transfer_to_agent` 把当前任务移交给指定子智能体。子智能体在同一会话上下文中继续执行并直接给出最终回答。

该工具集对外暴露两个工具：

| 工具 | 作用 |
| :- | :- |
| `collect_resources` | 收集当前账号可用的技能、知识库和 VeADK 内置工具，并按主智能体提供的任务关键词检索公共 Skill Hub，返回一份资源清单和 `collection_id`。 |
| `create_agents` | 根据 `collect_resources` 返回的 `collection_id` 与主智能体设计的智能体蓝图创建子智能体，将其注册为当前智能体的子智能体，然后把控制权移交给 `handoff_to` 指定的智能体。每次 `collect_resources` 的结果只需调用一次 `create_agents`，并在同一次调用中包含全部所需子智能体；调用完成或设置 `handoff_to` 后不再重复调用。 |

<Note>
  `collect_resources` 返回的资源是候选清单，不会自动挂载到子智能体。主智能体必须在每个 LLM 节点的 `resources` 中显式写入需要使用的每个资源 ref；当清单中存在与任务相关的技能时，至少绑定一个技能。
</Note>

## 何时使用

适合以下场景：

* 主智能体需要根据用户任务临时组建具备特定技能、知识库或工具的专家子智能体，而不在开发期固定子智能体结构。
* 需要在同一会话上下文中把任务移交给动态创建的子智能体，由子智能体直接向用户输出最终结果。
* 需要从公共 Skill Hub 或账号下的 Skill Space、知识库与内置工具中按任务匹配资源。

不适合需要严格可控、固定编排拓扑的场景——这类场景应直接在开发期声明静态子智能体树。

<Note>
  在 Studio 对话中，如果当前会话已挂载 AIO Sandbox 执行环境，挂载环境的优先级高于动态子智能体创建。智能体应优先使用挂载环境（通过 `list_envs`、`execute_in_sandbox` 等工具）完成任务，除非用户明确要求创建或委派新智能体。详见[会话沙箱环境](/productions/veadk/preview/zh/components/frontend/studio#会话沙箱环境)。
</Note>

## 依赖与前提

<Warning>
  使用前请确认：

  1. 主智能体使用的推理模型已配置 API Key。
  2. 如需收集账号下的 AgentKit 技能中心技能或知识库，需配置火山引擎 AK / SK 或 STS 临时凭证（BytePlus 模式使用 `BYTEPLUS_ACCESS_KEY` 等）。公共 Skill Hub 检索不需要凭证。
  3. `create_agents` 必须在由 `Runner` 驱动的智能体调用链中执行，否则无法注册子智能体并完成移交。
</Warning>

公共 Skill Hub 检索由主智能体根据任务生成关键词完成，无需配置 Space ID。配置 AK/SK 或 STS 后，AgentKit 技能中心会自动检索当前账号可访问的全部 Skill Space。`SKILL_SPACE_ID` 仅用于将检索范围限制到指定 Space，多个 Space ID 用逗号分隔；兼容旧版 Skill Hub Space 时仍可使用 `SKILL_HUB_SPACE_ID`。

| 环境变量 | 默认值 | 说明 |
| :- | :- | :- |
| `MODEL_AGENT_API_KEY` | — | 主智能体推理模型的 API Key。 |
| `VOLCENGINE_ACCESS_KEY` | — | 火山引擎 AccessKey，用于检索账号下的技能与知识库。 |
| `VOLCENGINE_SECRET_KEY` | — | 火山引擎 SecretKey。 |
| `VOLCENGINE_SESSION_TOKEN` | — | 火山引擎 STS 临时凭证令牌，使用临时凭证时填写。 |
| `BYTEPLUS_ACCESS_KEY` | — | BytePlus 模式下的 AccessKey。 |
| `BYTEPLUS_SECRET_KEY` | — | BytePlus 模式下的 SecretKey。 |
| `BYTEPLUS_SESSION_TOKEN` | — | BytePlus 模式下的 STS 临时凭证令牌。 |
| `CLOUD_PROVIDER` | `volcengine` | 云服务商，设为 `byteplus` 时改用 BytePlus 凭证与端点。 |
| `SKILL_SPACE_ID` | — | 将 AgentKit 技能中心检索范围限制到指定 Space，多个用逗号分隔。 |
| `SKILL_HUB_SPACE_ID` | — | 兼容旧版 Skill Hub Space 的范围限制，多个用逗号分隔。 |
| `AGENTKIT_TOOL_REGION` | 云服务商默认地域 | 指定 AgentKit 控制面地域。 |
| `VEADK_STUDIO_PROJECT` | — | 指定知识库检索所属项目，在 Studio 环境中通常已设置。 |

## 使用方法

把 `CreateAgentToolset()` 实例加入 `Agent` 的 `tools` 列表即可。主智能体在指令中描述资源收集、蓝图设计与移交的流程，运行时由模型自主决定何时调用两个工具。

```python title="dynamic_agent_coordinator.py" lines theme={null}
import asyncio

from veadk import Agent, Runner
from veadk.memory.short_term_memory import ShortTermMemory
from veadk.tools.builtin_tools.create_agent import CreateAgentToolset

create_agent = CreateAgentToolset()

agent = Agent(
    name="dynamic_agent_coordinator",
    model_name="doubao-seed-2-1-pro-260628",
    description="按任务需要动态组建专家并移交执行的协调智能体。",
    instruction="""
你是动态智能体协调器。

对于问候、身份介绍或能力说明，直接回答，不要创建子智能体。

对于需要检索、专业技能、知识库、工具调用或编写 Python 工具才能完成的任务：
1. 先调用 collect_resources，根据用户任务提炼 2 到 5 个简短的 Skill Hub 检索关键词传入 skill_hub_keywords。
2. 根据返回的资源清单设计最少数量的子智能体。把需要使用的每个技能、知识库和内置工具的完整 ref 显式写入对应 LLM 节点的 resources。
3. 调用 create_agents，在同一次调用中包含全部所需子智能体，在 handoff_to 中指定真正负责完成用户任务的智能体。
4. create_agents 会把任务直接移交给该智能体，调用后不要自行重复作答。

如果用户明确禁止联网、知识库或任何外部资源访问，跳过 collect_resources，直接调用 create_agents 并传入空字符串作为 collection_id，同时确保每个 LLM 节点的 resources 为空列表。
""",
    tools=[create_agent],
)

runner = Runner(agent=agent, short_term_memory=ShortTermMemory())


async def main():
    response = await runner.run("检索并总结最近 AgentKit 的公开资料，给出三条结论和来源。")
    print(response)


if __name__ == "__main__":
    asyncio.run(main())
```

### 资源收集与匹配

`collect_resources` 默认从以下来源收集资源，并将其统一为带 `ref` 的候选清单：

| 来源 | 资源类型 | ref 形式 | 凭证要求 |
| :- | :- | :- | :- |
| 公共 Skill Hub 搜索 | 技能 | `skill_hub:<标识>` | 无 |
| 账号下的 Skill Space | 技能 | `<space_id>:<skill_id>` | AK/SK 或 STS |
| AgentKit 知识库 | 知识库 | `agentkit_kb:<knowledge_id>` | AK/SK 或 STS |
| VeADK 内置工具 | 工具 | `veadk_tool:<工具名>` | 无 |

收集完成后返回的 `collection_id` 需要在随后调用 `create_agents` 时原样传入，用于关联本次收集的资源快照。

### 离线模式

当用户明确禁止联网、知识库和任何外部资源访问时，主智能体可以跳过 `collect_resources`，直接调用 `create_agents` 并传入空字符串作为 `collection_id`。此时每个 LLM 节点的 `resources` 必须为空列表，子智能体仅使用自身模型能力完成当前任务。离线模式下不会发起 Skill Hub 关键词检索或其他资源源调用。

### 智能体蓝图

`create_agents` 的 `agents` 参数是一个蓝图列表，每个蓝图描述一个独立构建的根智能体：

| 字段 | 类型 | 必填 | 说明 |
| :- | :- | :- | :- |
| `name` | `str` | 是 | 智能体名称，需匹配 `[A-Za-z_][A-Za-z0-9_]*`，同一批次内唯一。应使用可复用的能力标识，不含请求特定的实体、品牌、平台、行业、语言或题材。 |
| `task` | `str` | 是 | 该智能体要完成的当前一次性任务描述，包含具体的目标、对象、输入和交付要求。 |
| `root_node` | `str` | 是 | 蓝图节点中作为入口的节点 id。 |
| `nodes` | `list[节点]` | 是 | 节点列表，至少一个；节点 id 在同一蓝图内唯一。 |

蓝图内的节点支持以下类型，具体可用类型取决于已安装的 Google ADK 版本：

| 节点类型 | 说明 | 关键字段 |
| :- | :- | :- |
| `llm` | 由语言模型驱动的叶节点，承载技能、知识库和工具 | `instruction`、`resources`、`python_tools`、`model_name` |
| `sequential` | 顺序执行子节点 | `children` |
| `parallel` | 并行执行子节点 | `children` |
| `loop` | 循环执行子节点 | `children`、`max_iterations`（默认 3） |
| `workflow` | 基于 DAG 的工作流编排 | `edges`、`max_concurrency` |

<Note>
  `workflow` 节点仅在 Google ADK 2.0.0 及以上版本可用；低版本下 `collect_resources` 返回的能力清单会标明当前支持的节点类型，`create_agents` 也会忽略 `workflow` 节点。
</Note>

### 可复用身份与任务分离

蓝图中的 `name`、节点 `id`、`description` 和 `instruction` 字段应描述可跨请求复用的稳定能力域，而 `task` 字段是当前一次性任务具体信息的唯一载体。具体而言：

* `name` 和 `id` 使用简洁的 snake\_case 能力名，例如 `video_creation_agent`、`document_translation_agent`、`investment_analysis_agent`，不要按本次交付物或研究对象命名。
* `description` 和 `instruction` 描述通用操作，如「调研用户指定的主题」「比较用户指定的候选项」，不硬编码本次任务中的品牌、平台、行业、语言或题材。
* `task` 完整保留当前用户的具体目标、对象、输入和交付要求，包括具体的研究对象、行业信息、源语言或目标语言等请求特有内容。

<Note>
  运行时，`task` 中的任务上下文会自动附加到每个 LLM 节点的指令末尾，子智能体可据此完成当前一次性任务，而无需在 `instruction` 中重复请求特定的实体。
</Note>

### LLM 节点

LLM 节点是最常用的叶节点，其字段如下：

| 字段 | 类型 | 默认值 | 说明 |
| :- | :- | :- | :- |
| `id` | `str` | — | 节点 id，需匹配 `[A-Za-z_][A-Za-z0-9_]*`，蓝图内唯一。应使用可复用的操作标识。 |
| `type` | `"llm"` | — | 固定为 `llm`。 |
| `description` | `str` | `""` | 节点描述，应描述可复用的能力，不含请求特定实体。 |
| `instruction` | `str` | — | 节点系统指令，应包含明确目标、输出格式和完成标准，使用参数化表达（如「用户指定的主题」）而非硬编码请求特定实体。 |
| `model_name` | `str \| list[str] \| None` | `None` | 节点使用的模型；为空时继承主智能体模型。 |
| `model_provider` | `str \| None` | `None` | 模型提供方。 |
| `model_api_base` | `str \| None` | `None` | 模型 API 地址。 |
| `resources` | `list[str]` | `[]` | 需要挂载的资源 ref 列表，必须来自 `collect_resources` 的返回。 |
| `python_tools` | `list[PythonToolSpec]` | `[]` | 由主智能体编写的可信 Python 工具，独立于 `resources` 中的内置工具。 |

### 临时 Python 工具

主智能体可以在 LLM 节点的 `python_tools` 中提供完整 Python 源码，作为子智能体可调用的工具：

| 字段 | 类型 | 默认值 | 说明 |
| :- | :- | :- | :- |
| `name` | `str` | — | 工具名称，需匹配 `[A-Za-z_][A-Za-z0-9_]*`。 |
| `description` | `str` | — | 工具描述，供模型决定是否调用。 |
| `code` | `str` | — | 定义可调用对象的完整 Python 源码。参数、返回值及跨工具边界传递的全部数据必须可由标准 JSON 无损表达：对象键只能是字符串，不得使用 tuple、对象或其他非字符串字典键；组合键等复合结构应改为记录列表。 |
| `entrypoint` | `str \| None` | `None` | 暴露的可调用对象名，省略时与 `name` 一致。 |
| `dependencies` | `list[str]` | `[]` | 需校验的 Python 依赖，如 `pandas>=2`；缺失的包会被报错，不会自动安装。 |

<Warning>
  `python_tools` 中的代码以主智能体身份在当前进程内执行，不经过沙箱隔离。仅应接受受信任源提供的代码，并避免让不可信的输入直接成为可执行源码。小规模、可直接枚举或心算验证的问题优先由子智能体直接推理，不需要创建临时 Python 工具。
</Warning>

## 参数

`CreateAgentToolset` 的构造参数：

| 参数 | 类型 | 默认值 | 说明 |
| :- | :- | :- | :- |
| `skill_source_ids` | `str \| Sequence[str] \| None` | `None` | 将技能检索范围限制到指定 Space。以 `sp-` 开头的 id 视为 Skill Hub Space，其余视为 AgentKit Skill Space；为空时读取 `SKILL_HUB_SPACE_ID` 与 `SKILL_SPACE_ID`。 |
| `resource_sources` | `Sequence[ResourceSource] \| None` | 默认来源 | 自定义资源来源列表；省略时使用技能、知识库与内置工具四个默认来源。 |
| `capabilities` | `AgentCapabilities \| None` | 自动检测 | 指定运行时能力；省略时根据已安装的 Google ADK 版本自动检测支持的节点类型。 |
| `resource_store` | `ResourceStore \| None` | 新建实例 | 自定义资源快照存储；省略时使用进程内有界存储，最多保留 128 份快照，每次 `collect_resources` 覆盖同一会话的上一份。 |
| `skill_cache_dir` | `Path \| None` | `None` | 技能物化缓存目录。 |
| `leaf_factory` | `Callable \| None` | 默认工厂 | 自定义 LLM 节点构建器，用于替换默认的叶智能体创建逻辑。 |
| `knowledge_factory` | `Callable \| None` | 默认工厂 | 自定义知识库挂载器，用于替换默认的 VikingDB 知识库构建逻辑。 |

## 限制

* `create_agents` 必须在由 `Runner` 驱动的活跃智能体调用中执行，否则无法注册子智能体并完成移交。
* 每次 `collect_resources` 的结果只需调用一次 `create_agents`，并在同一次调用中包含全部所需子智能体；调用完成或设置 `handoff_to` 后不应再次调用。
* 同一会话内多次调用 `collect_resources` 会覆盖同一会话的资源快照；资源快照存储在进程内有界缓存中（最多 128 份），`create_agents` 读取快照后不会使其失效，同一快照可被具有相同请求指纹的后续调用复用。
* 动态创建的子智能体注册在当前会话的智能体树中，会话结束后不再保留。
* `python_tools` 在当前进程内执行，不做沙箱隔离。
