Skip to content

Add sub-agent support as tools#348

Open
JVillator0 wants to merge 1 commit intolaravel:0.xfrom
JVillator0:feat/sub-agents-as-tools
Open

Add sub-agent support as tools#348
JVillator0 wants to merge 1 commit intolaravel:0.xfrom
JVillator0:feat/sub-agents-as-tools

Conversation

@JVillator0
Copy link
Copy Markdown

Agents can now be returned directly from the tools() method, allowing them to act as sub-agents. Following the industry-standard pattern of treating sub-agents as tools, the parent agent's LLM invokes sub-agents like any other tool, passing a task description and receiving the result text.

class ProjectManager implements Agent, HasTools
{
    use Promptable;

    public function instructions(): string
    {
        return 'You delegate research tasks to your sub-agent.';
    }

    public function tools(): iterable
    {
        return [
            new WebSearch,
            new ResearchAgent,
        ];
    }
}

Sub-agents are full agents, they support attributes, their own tools, structured output, and any other agent capability:

#[Provider('anthropic')]
#[Model('claude-sonnet-4-5')]
#[MaxSteps(5)]
class ResearchAgent implements Agent, HasTools
{
    use Promptable;

    public function name(): string
    {
        return 'research_agent';
    }

    public function description(): string
    {
        return 'Research a topic in depth and return a summary.';
    }

    public function instructions(): string
    {
        return 'You are a research agent. Summarize your findings concisely.';
    }

    public function tools(): iterable
    {
        return [new WebSearch];
    }
}

Sub-agents can optionally define name() and description() methods for better tool identification. If omitted, the class basename and instructions() are used as fallbacks.

Each sub-agent invocation runs with isolated context, no conversation history is shared from the parent, keeping context clean and preventing bloat.

Approach

  • AgentTool: adapter class that wraps an Agent as a Tool with a { task: string } schema
  • GeneratesText::resolveTools(): automatically wraps any Agent found in tools() into an AgentTool
  • Both GeneratesText and StreamsText use resolveTools() instead of reading tools() directly
  • Sub-agent errors are caught and returned as tool results instead of killing the parent flow

Ref: #75, #58

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant