Skip to main content
Version: 0.7 (latest)

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_tools are available to every child agent.
  • SubagentSpec.tools are available only to that subagent type.
  • excluded_tool_names prevents 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.