agentscope-ai / agentscope-ai/agentscope
SubAgentTemplate workers cannot declare or receive custom business tools — only the framework default toolset
- Lingua principale
- Python
- Stelle
- 31.5k
- Fork
- 3.5k
- Merge medio
- 1g 23h
- PR unite (30g)
- 95
Descrizione
## Context
The `SubAgentTemplate` feature (#1825) works well for configuring a worker's *system prompt*, *context*, *react*, and *permission* config, and routing to templates via `AgentCreate(subagent_type=...)` is clean. ✅
However, there's a gap regarding **business tools**: a worker spawned from a `SubAgentTemplate` has no way to declare "I need tool X" and actually receive it. This forces a workaround, and I'd like to discuss whether the framework can support this elegantly.
## The problem
A `SubAgentTemplate` lets you configure a worker's *system prompt*, but the prompt is the **only** thing that survives into the worker's identity. `AgentCreate` builds the worker `AgentRecord` as follows (`_tools/_agent_create.py:423`):
```python
worker_agent = AgentRecord(
user_id=...,
source="team",
data=AgentData(
name=name, # ← leader-assigned, free-form, NOT the template type
system_prompt=system_prompt,
context_config=...,
react_config=...,
# no field carries subagent_type / template identity / tool requirements
),
)
```
Two consequences that together block clean tool injection:
1. **The worker's `name` is not the template `type`.** `name` is whatever the leader passes to `AgentCreate` (e.g. `"analyst-1"`, different every run), while `subagent_type` (e.g. `"analyst"`) is discarded after routing. So `custom_agent_cls.__new__(name)` cannot dispatch the worker to a type-specific subclass — the routing key is gone.
2. **`get_toolkit` assembles the worker's tools from generic sources only** (`_service/_toolkit.py`): workspace builtins, planning tools, and `TeamSay` for workers. The `extra_factory` hook only receives `(user_id, agent_id, session_id)` — it cannot see `system_prompt` or template type, so it can't decide *which* tools *this* worker needs without hacky heuristics. Applying it globally also pollutes every worker (e.g. one worker type receiving tools another type never asked for).
**Result:** a worker can be instructed (via prompt) to use project-specific tools, but has no mechanism to actually receive them. It silently falls back to framework builtins, which work but lose the value of the tools the template intended.
## What we tried (and why each is a workaround)
- **\`@register(name)\` a per-type subclass with \`_assemble_tools\`** → doesn't work. Worker `name` ≠ template `type` and isn't stable (consequence #1).
- **\`extra_factory\` global injection** → wrong granularity. Can't tell workers apart; pollutes unrelated workers.
- **Fingerprint matching on \`system_prompt\`** → works and is generic for new templates, but it's clearly a workaround — re-parsing a prompt to recover identity the framework already knew and discarded.
## Proposal
Some way for a `SubAgentTemplate` (or the worker it produces) to carry tool requirements through to `get_toolkit`. A few options, roughly in order of how invasive:
1. **Add an optional \`extra_tools_factory\` to \`SubAgentTemplate\`** — same shape as the app-level `extra_agent_tools` factory, but per-template, invoked by `get_toolkit` only for workers whose `subagent_type` matches. Smallest change; templates that need custom tools opt in, others unaffected.
2. **Persist \`subagent_type\` on the worker \`AgentRecord\`/\`SessionRecord\`** so `custom_agent_cls` and `get_toolkit` can route/inject by it. More general (unblocks the `@register`-by-type approach too), but a storage-schema change.
3. **Pass template identity into \`extra_factory\`** signature (e.g. add `agent_record` / `subagent_type`), so app developers can branch per-worker without a global blast radius.
## Environment
- agentscope 2.0.2
Would appreciate your thoughts on whether any of these directions is acceptable.
Guida per i contributori
Apri la guida per i contributori
Valutazione
Questa issue non è ancora stata valutata.