Delegate Task Tool

Give an agent a one-line tool to spawn a sub-agent for a specific task

delegate_task gives an agent a single tool to spawn a specialist sub-agent for one task and return its output.

Diagram

Delegate Task Flow

granted

denied

yes

no, returns immediately

🤖 Parent Agent

🔧 delegate_task

✋ Approval?

🚀 Spawn Sub-Agent
role = agent_type

❌ Approval Failure

⏱️ Within timeout?

✅ Output JSON

❌ Timeout JSON

Quick Start

  1. Agent picks the tool
    python
    from praisonaiagents import Agent
    from praisonaiagents.tools import delegate_task
    
    agent = Agent(
        name="Coordinator",
        instructions="Delegate specialist work to a sub-agent when useful.",
        tools=[delegate_task],
    )
    
    agent.start("Delegate a market research task on competitor pricing.")

    The coordinator picks delegate_task, spins up a sub-agent whose role is derived from agent_type, and returns the result.

  2. Direct call (headless / CI)
    python
    import json
    from praisonaiagents.tools.delegation_tools import delegate_task
    
    # In headless / CI, set PRAISONAI_AUTO_APPROVE=true to bypass the approval gate.
    raw = delegate_task(
        task_description="Summarise Q3 competitor pricing changes",
        agent_type="research",
        priority="high",
        timeout=120,
    )
    print(json.loads(raw)["output"])

Which Delegation Primitive?

Three delegation entry points overlap — pick the simplest one that fits.

Diagram

One-line tool call
from inside a prompt

Full control over
model / permissions / background

Programmatic async
fan-out & concurrency

Delegate to my own
.praisonai/agents by name

What kind of delegation
do I need?

delegate_task
this page

create_subagent_tool
see Subagent Tool

parallel_handoffs
see Handoffs

Named Agent Delegation

Featuredelegate_task (this page)create_subagent_toolparallel_handoffs
ShapeSingle tool functionTool factory returning {function, result_tool}Async function over (agent, prompt) tuples
Sync / asyncSyncSync or backgroundAsync
Timeout✅ enforced (thread-bounded)Per-call via subagent runtime✅ via HandoffConfig(timeout_seconds=...)
Approval✅ built-in @require_approval("medium")Depends on agent configDepends on agent config
Model / permission modeFixed lightweight defaults✅ Fully configurableEach target is a full Agent
Background jobs❌✅ (background=True, deliver=...)✅ concurrent fan-out (max_concurrent)
Named-agent resolution❌✅ (agent_resolver=)Pass the target Agent objects directly
When to useYou want a one-line drop-in delegation tool an agent can invoke in a promptYou want full control over the sub-agentYou want async fan-out across several agents at once

How It Works

delegate_task runs the sub-agent, waits for it (bounded by timeout), and returns a JSON string.

Diagram
🧠 Sub-Agent✋ Approval Gate🔧 delegate_task🤖 Coordinator👤 User🧠 Sub-Agent✋ Approval Gate🔧 delegate_task🤖 Coordinator👤 User“Research competitor pricing”delegate_task(task, agent_type=”research”, timeout=120)require_approval(risk_level=”medium”)granted (auto in CI with PRAISONAI_AUTO_APPROVE)spawn Agent(role=”research”, …) via create_subagent_tooloutput (within timeout){“success”: true, “output”: “…”, “priority”: “high”}Summary of findings

agent_type maps to the sub-agent’s identity:

  • role = agent_type (unless agent_type == "general", in which case role="assistant")
  • name = f"{agent_type}_agent"
  • goal = f"Complete delegated {agent_type} tasks accurately."
  • verbose=False

This is intentionally lightweight — no extra config knobs and no separate registry of agent profiles. For richer control (custom LLM, permission mode, background execution, named-agent resolution), reach for create_subagent_tool directly — see Subagent Tool.


Signature

python
@require_approval(risk_level="medium")
def delegate_task(
    task_description: str,
    agent_type: str = "general",
    priority: str = "medium",
    timeout: int = 300,
) -> str
ParameterTypeDefaultDescription
task_descriptionstrrequiredDescription of the task to delegate to the sub-agent
agent_typestr"general"Type/role of agent (e.g. "research", "reviewer"). Used as the sub-agent’s role so the model can be steered toward a specialisation without extra config. "general" falls back to a plain "assistant" role.
prioritystr"medium"Task priority hint — "low", "medium", or "high". Echoed back in the success response for observability.
timeoutint300Maximum execution time in seconds. Enforced via a daemon worker — on expiry the tool returns the structured timeout JSON immediately, without waiting for the sub-agent to finish. timeout <= 0 disables the bound.

Return Shapes

The tool returns a JSON string in one of four shapes.

Success
{
  "success": true,
  "task_description": "Summarise Q3 competitor pricing changes",
  "agent_type": "research",
  "priority": "high",
  "output": "…sub-agent output text…"
}
Runtime failure
{
  "success": false,
  "task_description": "…",
  "agent_type": "research",
  "error": "delegation failed"
}
Timeout
{
  "success": false,
  "task_description": "…",
  "agent_type": "research",
  "error": "Delegated task timed out after 120s"
}
Unhandled exception
{
  "success": false,
  "task_description": "…",
  "agent_type": "research",
  "error": "Error delegating task: <exception message>"
}

Approval Gate

delegate_task is decorated with @require_approval(risk_level="medium") because spawning a sub-agent is a medium-risk action.

  • Interactive: users get a prompt to approve or deny the call.
  • Headless / CI: set PRAISONAI_AUTO_APPROVE=true (or configure per-tool auto-approval) or the call is blocked before the sub-agent is spawned.

Since PR #4878, PRAISONAI_AUTO_APPROVE=true works even when delegate_task runs inside an agent that has an approval backend attached (the default ConsoleBackend on a TTY, or any chat/gateway front-end) — the env var is now checked before the backend prompt. See Standing grants and attached backends.

See Approval Protocol for how the gate works.


Timeout Enforcement

The timeout parameter is a hard wall-clock bound on how long delegate_task blocks the caller.

  • timeout > 0 (default 300): the sub-agent runs on a daemon worker thread. If it has not returned by the deadline, a structured success: false timeout JSON is returned immediately — the caller does not wait for the worker.
  • timeout <= 0: bound disabled — the call blocks for as long as the sub-agent takes. Use this only when you have another way to cap runtime (e.g. an outer scheduler).

Bot / Registry Usage

delegate_task is not auto-injected into the bot default toolset. Opt in explicitly:

python
from praisonaiagents import BotConfig

config = BotConfig(
    token="YOUR_TOKEN",
    default_tools=[
        "search_web", "store_memory",
        "delegate_task",  # opt in
    ],
)

The tool is also available under the plain function and workspace-scoped forms:

python
from praisonaiagents.tools import delegate_task              # module-level function
from praisonaiagents.tools.delegation_tools import DelegationTools, create_delegation_tools

# Optional: workspace-scoped instance
tools = create_delegation_tools(workspace=my_workspace)

Common Patterns

Ad-hoc research delegation — a coordinator agent has delegate_task in its tool list; when it needs research it calls the tool and inlines the result.

python
from praisonaiagents import Agent
from praisonaiagents.tools import delegate_task

coordinator = Agent(
    name="Coordinator",
    instructions="When you need research, delegate it and summarise the result.",
    tools=[delegate_task],
)
coordinator.start("Find competitor pricing changes this quarter.")

Headless batch job — set PRAISONAI_AUTO_APPROVE=true, call delegate_task(...) directly for each work item, parse the JSON return.

python
import json
from praisonaiagents.tools.delegation_tools import delegate_task

items = ["Region A pricing", "Region B pricing"]
for item in items:
    raw = delegate_task(task_description=item, agent_type="research", timeout=120)
    result = json.loads(raw)
    print(result["success"], result.get("output") or result.get("error"))

Priority-tagged workqueue — pass priority="high" to record intent (echoed back in the response) even though it does not currently affect scheduling.

python
delegate_task(task_description="Urgent audit", agent_type="reviewer", priority="high")

Best Practices

Prefer delegate_task for one-line delegation

Use delegate_task when you want a single-line tool an agent can pick up automatically. For anything else — background jobs, a custom model, or a named agent — reach for create_subagent_tool.

Always pass a realistic timeout

The default is 300 s, but a scoped task usually completes in under 60 s. Set timeout to bound runtime and get a structured timeout JSON instead of a hang.

Set PRAISONAI_AUTO_APPROVE in CI

In headless runs, set PRAISONAI_AUTO_APPROVE=true explicitly rather than removing the approval decorator — the gate stays in place for interactive use.

Treat priority as an observability tag

priority is echoed back in the success response only. There is no scheduler behind it — don’t rely on it to reorder work.


Related