Files
owlen/crates/tools/task/SUBAGENT_ORCHESTRATION.md

8.6 KiB

Subagent Orchestration Enhancement

This document describes the enhanced Task tool with proper subagent orchestration support using plugin agents.

Overview

The Task tool has been enhanced to support a new architecture for spawning and managing specialized subagents. The system now integrates with the plugin system's AgentDefinition type, allowing both built-in and plugin-provided agents to be orchestrated.

Key Components

1. SubagentConfig

Configuration structure for spawning subagents:

pub struct SubagentConfig {
    /// Agent type/name (e.g., "code-reviewer", "explore")
    pub agent_type: String,

    /// Task prompt for the agent
    pub prompt: String,

    /// Optional model override
    pub model: Option<String>,

    /// Tool whitelist (if None, uses agent's default)
    pub tools: Option<Vec<String>>,

    /// Parsed agent definition (if from plugin)
    pub definition: Option<AgentDefinition>,
}

Builder Pattern:

let config = SubagentConfig::new("explore".to_string(), "Find all Rust files".to_string())
    .with_model("claude-3-opus".to_string())
    .with_tools(vec!["read".to_string(), "glob".to_string()]);

2. SubagentRegistry

Thread-safe registry for tracking available agents:

pub struct SubagentRegistry {
    agents: Arc<RwLock<HashMap<String, AgentDefinition>>>,
}

Key Methods:

  • new() - Create empty registry
  • register_builtin() - Register built-in agents
  • register_from_plugins(Vec<AgentDefinition>) - Register plugin agents
  • get(name: &str) - Get agent by name
  • list() - List all agents with descriptions
  • contains(name: &str) - Check if agent exists
  • agent_names() - Get all agent names

Usage:

let registry = SubagentRegistry::new();
registry.register_builtin();

// Load plugin agents
let plugin_manager = PluginManager::new();
plugin_manager.load_all()?;
let plugin_agents = plugin_manager.load_all_agents();
registry.register_from_plugins(plugin_agents);

// Use registry
if let Some(agent) = registry.get("explore") {
    println!("Agent: {} - {}", agent.name, agent.description);
}

3. Built-in Agents

The system includes six specialized built-in agents:

explore

  • Purpose: Codebase exploration
  • Tools: read, glob, grep, ls
  • Color: blue
  • Use Cases: Finding files, understanding structure

plan

  • Purpose: Implementation planning
  • Tools: read, glob, grep
  • Color: green
  • Use Cases: Designing architectures, creating strategies

code-reviewer

  • Purpose: Code analysis
  • Tools: read, grep, glob (read-only)
  • Color: yellow
  • Use Cases: Quality review, bug detection

test-writer

  • Purpose: Test creation
  • Tools: read, write, edit, grep, glob
  • Color: cyan
  • Use Cases: Writing unit tests, integration tests

doc-writer

  • Purpose: Documentation
  • Tools: read, write, edit, grep, glob
  • Color: magenta
  • Use Cases: Writing READMEs, API docs

refactorer

  • Purpose: Code refactoring
  • Tools: read, write, edit, grep, glob (no bash)
  • Color: red
  • Use Cases: Improving structure, applying patterns

Future Implementation

The following functions will be implemented to complete the orchestration system:

spawn_subagent

/// Spawn a subagent with the given configuration
pub async fn spawn_subagent<P: LlmProvider>(
    provider: &P,
    registry: &SubagentRegistry,
    config: SubagentConfig,
    perms: &PermissionManager,
) -> Result<String>

Behavior:

  1. Look up agent definition from registry or config
  2. Extract system prompt and tool whitelist from definition
  3. Build full prompt combining system prompt + task
  4. Create filtered permission manager if tool whitelist specified
  5. Run agent loop with system prompt
  6. Return result string

spawn_parallel

/// Spawn multiple subagents in parallel and collect results
pub async fn spawn_parallel<P: LlmProvider + Clone>(
    provider: &P,
    registry: &SubagentRegistry,
    configs: Vec<SubagentConfig>,
    perms: &PermissionManager,
) -> Vec<Result<String>>

Behavior:

  1. Create futures for each config
  2. Execute all in parallel using join_all
  3. Return vector of results

Note: Requires PermissionManager to implement Clone. This may need to be added to the permissions crate.

Integration Points

With Plugin System

use plugins::PluginManager;
use tools_task::SubagentRegistry;

let mut plugin_manager = PluginManager::new();
plugin_manager.load_all()?;

let registry = SubagentRegistry::new();
registry.register_builtin();
registry.register_from_plugins(plugin_manager.load_all_agents());

With Agent Core

The subagent execution will integrate with agent-core by:

  1. Calling the same run_agent_loop function used by main agent
  2. Passing filtered tool definitions based on agent's tool whitelist
  3. Using agent-specific system prompts
  4. Inheriting parent's permission manager (or creating restricted copy)

With Permission System

Subagents respect the permission system:

  • Tool whitelist from agent definition restricts available tools
  • Permission manager checks are still applied
  • Parent's mode (plan/acceptEdits/code) is inherited

Example Usage Patterns

Basic Exploration

let registry = SubagentRegistry::new();
registry.register_builtin();

let config = SubagentConfig::new(
    "explore".to_string(),
    "Find all test files in the codebase".to_string()
);

let result = spawn_subagent(&provider, &registry, config, &perms).await?;
println!("Found files:\n{}", result);

Parallel Analysis

let configs = vec![
    SubagentConfig::new("explore".to_string(), "Find all Rust files".to_string()),
    SubagentConfig::new("code-reviewer".to_string(), "Review auth module".to_string()),
    SubagentConfig::new("test-writer".to_string(), "Check test coverage".to_string()),
];

let results = spawn_parallel(&provider, &registry, configs, &perms).await;

for (i, result) in results.iter().enumerate() {
    match result {
        Ok(output) => println!("Agent {} completed:\n{}", i, output),
        Err(e) => eprintln!("Agent {} failed: {}", i, e),
    }
}

Custom Plugin Agent

// Plugin provides custom-analyzer agent
let config = SubagentConfig::new(
    "custom-analyzer".to_string(),
    "Analyze security vulnerabilities".to_string()
);

if registry.contains("custom-analyzer") {
    let result = spawn_subagent(&provider, &registry, config, &perms).await?;
} else {
    eprintln!("Agent not found. Available: {:?}", registry.agent_names());
}

Migration Guide

From Legacy Subagent API

The legacy Subagent struct and keyword-based matching is still available for backward compatibility:

// Legacy API (still works)
let agent = Subagent::new(
    "reader".to_string(),
    "Read-only agent".to_string(),
    vec!["read".to_string()],
    vec![Tool::Read, Tool::Grep],
);

Migrate to new API:

  1. Use SubagentRegistry instead of custom keyword matching
  2. Use SubagentConfig instead of direct agent instantiation
  3. Use spawn_subagent instead of manual tool execution

Testing

Run tests:

cargo test -p tools-task

All tests pass, including:

  • Registry builtin registration
  • Plugin agent registration
  • Config builder pattern
  • Legacy API backward compatibility

Dependencies

  • plugins - For AgentDefinition type
  • parking_lot - For RwLock in thread-safe registry
  • permissions - For tool permission checks
  • color-eyre - For error handling
  • serde / serde_json - For serialization

Future Work

  1. Implement spawn_subagent: Complete the actual subagent spawning logic
  2. Add Clone to PermissionManager: Required for parallel execution
  3. System Prompt Support: Ensure agent loop respects system prompts
  4. Tool Filtering: Implement filtered tool definitions based on whitelist
  5. Progress Tracking: Add hooks for monitoring subagent progress
  6. Error Recovery: Handle subagent failures gracefully
  7. Resource Limits: Add timeout and resource constraints
  8. Inter-Agent Communication: Allow agents to share context
  • /home/cnachtigall/data/git/projects/Owlibou/owlen/crates/tools/task/src/lib.rs - Main implementation
  • /home/cnachtigall/data/git/projects/Owlibou/owlen/crates/tools/task/Cargo.toml - Dependencies
  • /home/cnachtigall/data/git/projects/Owlibou/owlen/crates/platform/plugins/src/lib.rs - AgentDefinition type
  • /home/cnachtigall/data/git/projects/Owlibou/owlen/crates/core/agent/src/lib.rs - Agent execution loop
  • /home/cnachtigall/data/git/projects/Owlibou/owlen/crates/platform/permissions/src/lib.rs - Permission system