Subagents
SubagentMiddleware adds a subagent tool. When the model calls that tool,
CubePi creates an ephemeral child Agent, runs a self-contained prompt, and
returns the child agent's final assistant text as the tool result.
Use it when a parent agent needs to delegate bounded work such as research, review, extraction, or a focused implementation pass.
Define subagent specs
from cubepi import Agent
from cubepi.middleware import SubagentMiddleware, SubagentSpec
subagents = {
"researcher": SubagentSpec(
name="researcher",
description="Researches a narrow question and returns concise notes.",
system_prompt="You are a precise research assistant.",
),
"reviewer": SubagentSpec(
name="reviewer",
description="Reviews code for bugs, regressions, and missing tests.",
system_prompt="You are a rigorous senior code reviewer.",
),
}
model = provider.model("claude-sonnet-4-5-20250929")
agent = Agent(
model=model,
middleware=[
SubagentMiddleware(
subagents=subagents,
default_model=model,
shared_tools=[web_search],
),
],
)
If the model requests an unknown subagent_type, CubePi falls back to the
general-purpose subagent. If you do not define one, the middleware supplies a
basic default.
Tool access and middleware inheritance
Subagents only receive the tools you pass in:
shared_toolsare available to every child agent.SubagentSpec.toolsare available only to that subagent type.excluded_tool_namesprevents recursive or host-only tools from being shared.
Use inherited_middleware for middleware every child should run. Use
SubagentSpec.middleware for behavior specific to one subagent type.
Stream child events to your host
Applications often need child events in their own UI or audit log. Provide an
event_mapper and optional event_handler:
def map_event(event):
if event.type == "text_delta":
return {"type": "subagent_text_delta", "delta": event.delta}
return None
async def handle_event(agent_id, payload):
await ui_stream.send({"agent_id": agent_id, **payload})
SubagentMiddleware(
subagents=subagents,
default_model=model,
event_mapper=map_event,
event_handler=handle_event,
)
Mapped payloads are also stored in the parent tool result under
details["subagent_events"].
Tracing and aborts
Pass a Tracer via tracer=... to attach tracing to each child run. Nested
subagent spans share the parent trace, so cubepi trace view <trace_id> renders
the parent tool call and child run together.
The parent run's abort signal is forwarded to the child agent. If the parent is aborted while a subagent is running, the child agent is aborted as well.
Prompting guidelines
The parent model should send a self-contained prompt in the subagent tool
call. Do not rely on the child seeing the parent's full hidden context. Include
the goal, relevant facts, constraints, and desired output shape in the prompt.