Add a Specialist Agent or Tool
The @tool and sub-agent-as-tool pattern
Every capability the supervisor agent can invoke is registered as a Strands
@tool-decorated function.
The agents/supervisor/tools/ directory contains all tool implementations;
the registry in agents/supervisor/tools/init.py exports them as
factories and maps them to personas via PERSONA_TOOL_FACTORIES.
A tool factory takes a SessionContext and a Config and returns the
decorated function.
This closure pattern keeps the session’s tenant_id, JWT, and session_id
out of the LLM-visible signature while still making them available at call
time:
# agents/supervisor/tools/my_new_tool.py from strands import tool from agents.supervisor.session import SessionContext from agents.supervisor.config import Config def make_my_new_tool(ctx: SessionContext, config: Config): @tool def my_new_tool(query: str) -> dict: """One-sentence description Nova uses for routing decisions.""" # ... implementation ... return {"result": "..."} return my_new_tool
After implementing the factory, register it in
agents/supervisor/tools/init.py:
from agents.supervisor.tools.my_new_tool import make_my_new_tool __all__ = [ # ... existing entries ... "make_my_new_tool", ] PERSONA_TOOL_FACTORIES: dict[str, list] = { "fleet_driver": [ # ... existing factories ... make_my_new_tool, # <-- add here for the personas that need it ], # ... other personas ... }
Nova 2 Sonic latency constraint
Nova 2 Sonic’s bidi loop assumes tool calls return within approximately one second. Tools that exceed this window cause Nova’s post-tool TTS to go silent for the remainder of the session — a hard operational constraint discovered during early development (see Agentic Architecture).
The production-safe pattern is the retrieval-only sub-agent: the tool
returns raw KB content and Nova synthesizes the spoken response herself.
diy_repair_advisor and knowledge follow this pattern.
agents/supervisor/tools/sub_agent.py provides make_sub_agent_tool and
SubAgentConfig as the reusable factory for this pattern:
# Example: a new recall-lookup sub-agent pointing at the tsb-recalls corpus from agents.supervisor.tools.sub_agent import make_sub_agent_tool, SubAgentConfig recall_config = SubAgentConfig( name="recall_lookup", description=( "Look up open recalls and TSBs for the current vehicle. " "Call this when the driver asks about recalls, campaigns, or safety notices." ), corpus_subdir="tsb-recalls", # directory under corpora/ ) def make_recall_lookup_tool(ctx, config): return make_sub_agent_tool(recall_config, ctx=ctx)
Note
make_sub_agent_tool loads .md files from corpora/<subdir>/ at module
import and returns raw text.
Adding new content requires a code change and a full agent redeploy.
To update content without a redeploy, replace _load_corpus(subdir) with a
Bedrock Knowledge Base query call.
See Content-as-Config for the KB update workflow.