Quick Start
1
Create Subagent Tool
2
Spawn a Subagent
3
With Model and Permission Mode
Configuration Options
Delegating to Named Agents
Passagent_resolver to let the parent delegate to your own named agents instead of spawning a generic worker. When a passed agent_name resolves, that named agent runs the sub-task under its own model, tools, and permissions.
resolvable_agents enriches the tool description so the model knows which named agents it may delegate to. The CLI wires both parameters for you from .praisonai/agents/*.md — see Named Agent Delegation as the primary entry point.
Spawn Parameters
When calling the subagent function:platform, chat_id, thread_id and session_id are host-only (Python) parameters — the model-visible JSON schema does not include them. When deliver is set, the gateway fills them from get_session_context().Deliver Background Job Results Back to Chat
When a background job finishes, its result can be pushed back to the user’s chat automatically — no polling required.Delivery targets
deliver="origin" is auto-sent only inside a gateway (BotOS) turn whose send policy allows it. From a plain script with no gateway, the job stays pull-only. Failures are delivered as Background task failed: <error>; if the send is rejected the job stays delivered=False. See Background Subagents → When auto-delivery kicks in.deliver vocabulary mirrors the scheduling tool’s deliver= parameter. See JOB_COMPLETED Hook for the hook that fires on completion.
Backward compatibility: with no deliver target set, behaviour is byte-for-byte identical to before — pull-only via subagent_result.
Background Mode
Run a long subtask without blocking the parent agent. Use it for full test runs, broad codebase scans, or large refactors — anything where the parent agent should keep working instead of waiting.The parent turn is protected while a foreground subagent runs. When the parent agent sits behind a bot with
busy_mode="interrupt", a user message that arrives mid-subagent is queued (acked with ”⏳ Finishing current work, your message is queued”) instead of cancelling the parent turn mid-child-run. Background subagents (background=True) do not block the parent and are not protected. /stop still cancels either way. See Turn Protection Window and Bot Run Control. (PR #6124)1
Kick off in the background
2
Keep working, then collect the result
3
Handle failures cleanly
When to use background mode
Background return shapes
spawn_subagent(..., background=True) returns a handle (not a final result):
subagent_result(job_id) polls without blocking:
subagent_result(job_id, wait=True) blocks until done:
Depth (
max_depth), allowed_agents, and per-call tools / llm / permission_mode apply to background subagents identically to synchronous ones. Background jobs run on a worker thread but inherit the same scoping the parent set up.Model Selection
Model selection priority:- Per-call
llmparameter - Highest priority default_llmfrom tool creation - Fallback- Agent’s default model - Final fallback
Permission Modes
Custom Agent Factory
Create agents with custom configurations:Delegate to named agents
Turn discovered.praisonai/agents/*.md agents into delegation targets with a resolver. When the caller passes an agent_name that resolves, that named agent runs the sub-task under its own model / tools / permission.
Depth Limiting
Prevent infinite subagent recursion:Agent Restrictions
Limit which agent types can be spawned:Inter-Agent Provenance (default on)
By default, every sub-agent’s textual output is wrapped in an inter-agent provenance envelope so injected upstream text cannot drive the parent.See Inter-Agent Provenance for the full story, the envelope format, and how to opt a trusted source out with
trusted_sources.Result Structure
Synchronous calls (background=False, the default) return the final result directly. The output is wrapped in the inter-agent provenance envelope unless the source is in trusted_sources:
subagent_result shapes.
When a call is served by an
agent_resolver (named agent delegation), agent_name in the result is the resolved named agent (e.g. "researcher"), not "subagent". See Named Agent Delegation.Observability — SUBAGENT_STOP
Every spawned subagent emits HookEvent.SUBAGENT_STOP exactly once when it reaches a terminal state, regardless of how it was launched:
- Synchronous spawns
background=Truejobs- Resolver-routed named agents
- Generic factory spawns
- Simulation mode
- Failures (the hook still fires with
success=Falseanderrorpopulated)
task, success, output, error, llm, permission_mode, depth, duration_ms).
Best Practices
Use appropriate models
Use appropriate models
Use smaller models like
gpt-4o-mini for simple tasks and larger models for complex analysis.Set permission modes
Set permission modes
Always set
permission_mode="plan" for exploration tasks to prevent accidental modifications.Limit allowed agents
Limit allowed agents
Restrict
allowed_agents to only the agent types needed for your use case.Handle errors
Handle errors
Always check
result["success"] before accessing the output.Use background mode for long tasks
Use background mode for long tasks
For test suites, broad scans, or refactors, use
background=True so the parent agent can keep working and collect results with subagent_result.Related
Named Agent Delegation
Delegate to your .praisonai/agents by name — no Python
Subagent Delegation
Advanced subagent management
Permission Modes
Permission mode details
Sub-agent output arrives as labelled data, not instructions
JOB_COMPLETED Hook
Hook that fires when a background job finishes — success or failure

