For complex tasks, deputy supports a lead agent that delegates work to specialised sub-agents. Each sub-agent has its own tools, prompt, and (optionally) model. The lead agent decides when to delegate and synthesises the results.
When to Use Multi-Agent
Multi-agent orchestration is useful when:
- Different parts of a task need different tools (e.g., code analysis vs. data analysis)
- You want to isolate sub-tasks with their own system prompts
- Sub-agents should run with restricted permissions
- You need audit trails per sub-agent via
SubagentStophooks
For simpler tasks, a single Agent with the right tools
is usually enough.
Defining Sub-Agents
Use agent_definition() to describe a sub-agent:
library(deputy)
code_reviewer <- agent_definition(
name = "code_reviewer",
description = "Reviews R code for best practices and potential issues",
prompt = "You are an expert R developer. Review code for correctness,
style, and potential bugs. Be specific and actionable.",
tools = tools_file()
)
data_analyst <- agent_definition(
name = "data_analyst",
description = "Analyses data files and produces statistical summaries",
prompt = "You are a data analyst. Read data files and provide clear,
concise statistical summaries with key insights.",
tools = tools_data()
)Fields:
| Field | Description |
|---|---|
name |
Unique identifier (used by the lead to delegate) |
description |
What this agent does (shown to the lead LLM) |
prompt |
System prompt for the sub-agent |
tools |
Tools available to the sub-agent |
model |
"inherit" (default) or a specific model name |
skills |
Optional list of skills to load |
Creating a LeadAgent
LeadAgent extends Agent with a built-in
delegate_to_agent tool:
lead <- LeadAgent$new(
chat = ellmer::chat_anthropic(),
sub_agents = list(code_reviewer, data_analyst),
system_prompt = "You coordinate analysis tasks. Delegate to the
appropriate specialist and synthesise their findings."
)
lead$available_sub_agents()
#> [1] "code_reviewer" "data_analyst"Running a Delegation Task
When the lead agent decides to delegate, it calls
delegate_to_agent internally. The sub-agent runs to
completion and returns its result to the lead:
library(deputy)
code_reviewer <- agent_definition(
name = "code_reviewer",
description = "Reviews R code and suggests improvements",
prompt = "You are an R code reviewer. Be concise.",
tools = tools_file()
)
chat <- ellmer::chat_anthropic(model = "claude-sonnet-4-20250514")
lead <- LeadAgent$new(
chat = chat,
sub_agents = list(code_reviewer)
)
result <- lead$run_sync(
"Ask the code reviewer to look at the DESCRIPTION file and
summarise what this package does."
)
cat(result$response)Convenience Constructor
agent_with_delegation() creates a lead agent with one
line:
lead <- agent_with_delegation(
chat = ellmer::chat_anthropic(),
sub_agents = list(code_reviewer, data_analyst),
tools = tools_file()
)Monitoring with SubagentStop Hooks
Use a SubagentStop hook to log or inspect sub-agent
results:
hook_monitor <- HookMatcher$new(
event = "SubagentStop",
callback = function(agent_name, task, result, context) {
cli::cli_alert_info("Sub-agent {agent_name} finished")
cli::cli_alert("Cost: {result$cost$total}")
HookResultSubagentStop()
}
)
lead$add_hook(hook_monitor)