> ## 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.

# Dynamic agent delegation

## Overview

Import path: `from veadk.tools.builtin_tools.create_agent import CreateAgentToolset`

`CreateAgentToolset` is a built-in toolset that lets a main agent collect available resources at runtime, create one or more sub-agents on demand, and transfer control to a chosen sub-agent through the Google ADK `transfer_to_agent` event. The sub-agent continues in the same session context and produces the final answer.

The toolset exposes two tools:

| Tool | Purpose |
| :- | :- |
| `collect_resources` | Collects skills, knowledge bases, and VeADK built-in tools available to the current account, and searches the public Skill Hub using task keywords provided by the main agent. Returns a resource catalog and a `collection_id`. |
| `create_agents` | Creates sub-agents from the `collection_id` returned by `collect_resources` and blueprints designed by the main agent, registers them as sub-agents of the current agent, and transfers control to the agent named by `handoff_to`. |

<Note>
  Resources returned by `collect_resources` are candidates only and are not mounted automatically. The main agent must explicitly include each resource ref it wants to use in the `resources` list of every LLM node; when relevant skills are present in the catalog, at least one must be bound.
</Note>

## When to use

Use this toolset when:

* A main agent needs to assemble sub-agents with specific skills, knowledge bases, or tools on demand, rather than fixing the sub-agent structure at development time.
* You need to hand off a task to a dynamically created sub-agent within the same session context, where the sub-agent produces the final answer directly.
* You need to match resources from the public Skill Hub, account Skill Spaces, knowledge bases, and built-in tools against a task.

It is not suitable when you require a strict, fixed orchestration topology — in that case declare a static sub-agent tree at development time.

## Prerequisites

<Warning>
  Before use:

  1. Configure the API key for the main agent's reasoning model.
  2. To collect account-level AgentKit Skill Center skills or knowledge bases, configure Volcengine AK / SK or an STS temporary credential (use `BYTEPLUS_ACCESS_KEY` and friends in BytePlus mode). Public Skill Hub search does not require credentials.
  3. `create_agents` must run within an agent invocation driven by a `Runner`, otherwise it cannot register sub-agents and complete the handoff.
</Warning>

The public Skill Hub search is driven by keywords generated by the main agent from the task; no Space ID is required. Once AK/SK or STS credentials are configured, the AgentKit Skill Center automatically enumerates every Skill Space visible to the account. `SKILL_SPACE_ID` only narrows the search to a specific Space, with multiple IDs separated by commas. `SKILL_HUB_SPACE_ID` is retained for compatibility with legacy Skill Hub Spaces.

| Environment variable | Default | Description |
| :- | :- | :- |
| `MODEL_AGENT_API_KEY` | — | API key for the main agent's reasoning model. |
| `VOLCENGINE_ACCESS_KEY` | — | Volcengine AccessKey, used to enumerate account skills and knowledge bases. |
| `VOLCENGINE_SECRET_KEY` | — | Volcengine SecretKey. |
| `VOLCENGINE_SESSION_TOKEN` | — | Volcengine STS temporary credential token, required when using STS. |
| `BYTEPLUS_ACCESS_KEY` | — | AccessKey in BytePlus mode. |
| `BYTEPLUS_SECRET_KEY` | — | SecretKey in BytePlus mode. |
| `BYTEPLUS_SESSION_TOKEN` | — | STS temporary credential token in BytePlus mode. |
| `CLOUD_PROVIDER` | `volcengine` | Cloud provider; set to `byteplus` to use BytePlus credentials and endpoints. |
| `SKILL_SPACE_ID` | — | Restricts AgentKit Skill Center search to the specified Space, comma-separated for multiple. |
| `SKILL_HUB_SPACE_ID` | — | Restricts search to legacy Skill Hub Spaces, comma-separated for multiple. |
| `AGENTKIT_TOOL_REGION` | Provider default region | Specifies the AgentKit control-plane region. |
| `VEADK_STUDIO_PROJECT` | — | Project used for knowledge-base enumeration; usually pre-set in the Studio environment. |

## Usage

Add a `CreateAgentToolset()` instance to the `Agent` `tools` list. Describe the resource-collection, blueprint-design, and handoff flow in the agent instruction; the model decides at runtime when to call the two 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="A coordinator that assembles experts on demand and delegates execution.",
    instruction="""
You are a dynamic agent coordinator.

For greetings, introductions, or capability questions, answer directly without creating sub-agents.

For tasks that require retrieval, specialized skills, knowledge bases, tool calls, or authoring Python tools:
1. First call collect_resources, deriving 2 to 5 short Skill Hub search keywords from the user's task and passing them via skill_hub_keywords.
2. Design the minimum number of sub-agents from the returned resource catalog. Explicitly include each skill, knowledge base, and built-in tool ref you need in the resources list of the corresponding LLM node.
3. Call create_agents, specifying in handoff_to the agent that should actually complete the user's task.
4. create_agents transfers the task directly to that agent; do not repeat the answer yourself.
""",
    tools=[create_agent],
)

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


async def main():
    response = await runner.run("Search and summarize the latest public AgentKit materials, giving three conclusions and sources.")
    print(response)


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

### Resource collection and matching

By default `collect_resources` gathers resources from the following sources and unifies them into a candidate catalog with a `ref`:

| Source | Resource type | ref form | Credential |
| :- | :- | :- | :- |
| Public Skill Hub search | skill | `skill_hub:<slug>` | None |
| Account Skill Spaces | skill | `<space_id>:<skill_id>` | AK/SK or STS |
| AgentKit knowledge bases | knowledge base | `agentkit_kb:<knowledge_id>` | AK/SK or STS |
| VeADK built-in tools | tool | `veadk_tool:<tool_name>` | None |

The `collection_id` returned after collection must be passed unchanged to the subsequent `create_agents` call to associate the resource snapshot.

### Agent blueprints

The `agents` argument of `create_agents` is a list of blueprints, each describing one independently constructed root agent:

| Field | Type | Required | Description |
| :- | :- | :- | :- |
| `name` | `str` | Yes | Agent name, matching `[A-Za-z_][A-Za-z0-9_]*`, unique within the batch. |
| `task` | `str` | Yes | Description of the task the agent must complete. |
| `root_node` | `str` | Yes | The node id used as the entry point. |
| `nodes` | `list[node]` | Yes | Node list, at least one; node ids are unique within a blueprint. |

Nodes inside a blueprint support the following types, with availability depending on the installed Google ADK version:

| Node type | Description | Key fields |
| :- | :- | :- |
| `llm` | Model-driven leaf node carrying skills, knowledge bases, and tools | `instruction`, `resources`, `python_tools`, `model_name` |
| `sequential` | Runs children in sequence | `children` |
| `parallel` | Runs children in parallel | `children` |
| `loop` | Runs children in a loop | `children`, `max_iterations` (default 3) |
| `workflow` | DAG-based workflow orchestration | `edges`, `max_concurrency` |

<Note>
  The `workflow` node is available only on Google ADK 2.0.0 and above. On lower versions, the capability catalog returned by `collect_resources` indicates the supported node types, and `create_agents` omits `workflow` nodes.
</Note>

### LLM node

The LLM node is the most common leaf node. Its fields are:

| Field | Type | Default | Description |
| :- | :- | :- | :- |
| `id` | `str` | — | Node id, matching `[A-Za-z_][A-Za-z0-9_]*`, unique within the blueprint. |
| `type` | `"llm"` | — | Fixed to `llm`. |
| `description` | `str` | `""` | Node description. |
| `instruction` | `str` | — | System instruction for the node; should include a clear goal, output format, and completion criteria. |
| `model_name` | `str \| list[str] \| None` | `None` | Model used by the node; inherits the main agent's model when empty. |
| `model_provider` | `str \| None` | `None` | Model provider. |
| `model_api_base` | `str \| None` | `None` | Model API base URL. |
| `resources` | `list[str]` | `[]` | Resource refs to mount; must come from the `collect_resources` return value. |
| `python_tools` | `list[PythonToolSpec]` | `[]` | Trusted Python tools authored by the main agent, separate from built-in tools in `resources`. |

### Ad-hoc Python tools

The main agent can provide complete Python source in the `python_tools` of an LLM node, exposed as tools callable by the sub-agent:

| Field | Type | Default | Description |
| :- | :- | :- | :- |
| `name` | `str` | — | Tool name, matching `[A-Za-z_][A-Za-z0-9_]*`. |
| `description` | `str` | — | Tool description, used by the model to decide when to call it. |
| `code` | `str` | — | Complete Python source defining the callable. |
| `entrypoint` | `str \| None` | `None` | Callable to expose; defaults to `name` when omitted. |
| `dependencies` | `list[str]` | `[]` | Python requirements to verify, e.g. `pandas>=2`; missing packages are reported and never installed. |

<Warning>
  Code in `python_tools` runs as the main agent in the current process without sandboxing. Only accept code from trusted sources, and avoid letting untrusted input become executable source directly.
</Warning>

## Parameters

Constructor parameters of `CreateAgentToolset`:

| Parameter | Type | Default | Description |
| :- | :- | :- | :- |
| `skill_source_ids` | `str \| Sequence[str] \| None` | `None` | Narrows skill search to the specified Spaces. ids starting with `sp-` are treated as Skill Hub Spaces and the rest as AgentKit Skill Spaces; when empty, `SKILL_HUB_SPACE_ID` and `SKILL_SPACE_ID` are read. |
| `resource_sources` | `Sequence[ResourceSource] \| None` | Default sources | Custom resource source list; when omitted, the four default sources for skills, knowledge bases, and built-in tools are used. |
| `capabilities` | `AgentCapabilities \| None` | Auto-detected | Specifies runtime capabilities; when omitted, supported node types are detected from the installed Google ADK version. |
| `resource_store` | `ResourceStore \| None` | New instance | Custom resource snapshot store; when omitted, an in-process store keeps only the latest snapshot per session. |
| `skill_cache_dir` | `Path \| None` | `None` | Skill materialization cache directory. |
| `leaf_factory` | `Callable \| None` | Default factory | Custom LLM-node builder to replace the default leaf-agent creation logic. |
| `knowledge_factory` | `Callable \| None` | Default factory | Custom knowledge-base mounter to replace the default VikingDB knowledge-base construction logic. |

## Limitations

* `create_agents` must run within an active agent invocation driven by a `Runner`, otherwise it cannot register sub-agents and complete the handoff.
* Within a session, each `collect_resources` call overwrites the previous resource snapshot, and `create_agents` consumes the matching snapshot, after which it is no longer valid.
* Dynamically created sub-agents are registered in the agent tree of the current session and are not retained after the session ends.
* `python_tools` run in the current process without sandbox isolation.
