Skip to content
Blog

Agents as Tools: Composing Hierarchical Agent Networks

Master the agents-as-tools pattern for building hierarchical multi-agent systems using the OpenAI Agents SDK for complex orchestration workflows.

Published on September 7, 2026

AI Assistant

Introduction

Single agents hit a ceiling. They can handle straightforward tasks, but complex workflows—research that spans multiple sources, document processing with validation, customer support that routes across departments—require coordination. The question isn’t whether you need multiple agents, but how to compose them.

The OpenAI Agents SDK introduces a powerful primitive: agents as tools. Instead of building monolithic agents that do everything, you build specialized agents and let other agents call them as tools. This creates hierarchical networks where a supervisor agent delegates to specialist agents, each with their own instructions, tools, and expertise.

The SDK’s design philosophy favors minimal API surface over comprehensive abstractions. As their documentation states: “The core primitives for agent handoffs, tool calling, and delegation are clean and easy to reason about, which makes it faster to understand what an agent is doing than with heavier orchestration stacks.”

Why This Matters

Monolithic agents fail at scale:

  • Context overflow: A single agent handling everything runs out of context window
  • Prompt bloat: Trying to teach one agent everything about everything produces mediocre results
  • No separation of concerns: Bugs in one capability affect all others
  • Difficult debugging: When something goes wrong, you can’t isolate which part failed

Hierarchical agent networks solve these by distributing responsibility. A research supervisor delegates to a web search specialist, a data analysis specialist, and a writing specialist. Each agent focuses on what it does best, and the supervisor coordinates.

The OpenAI Agents SDK makes this pattern first-class with the “agents as tools” mechanism—agents that can be called by other agents, receiving the same interface as any other tool.

Core Concepts

Handoffs vs. Agents as Tools

The SDK offers two multi-agent patterns:

Handoffs: Agent A transfers control to Agent B entirely. Agent A stops processing, and Agent B takes over the conversation. Use this when the task genuinely shifts to a different specialist.

Agents as Tools: Agent A calls Agent B as a tool, receives the result, and continues processing. Agent A remains in control. Use this when a supervisor needs to coordinate multiple specialists.

# agents/as_tools.py
from agents import Agent, Runner


# Define specialist agents
research_agent = Agent(
    name="Research Specialist",
    instructions=(
        "You are a research specialist. Find relevant information "
        "on the given topic using web search and documentation. "
        "Provide comprehensive, well-sourced findings."
    ),
    tools=[web_search_tool, documentation_tool],
)

analysis_agent = Agent(
    name="Analysis Specialist",
    instructions=(
        "You are a data analysis specialist. Analyze the provided "
        "data and extract insights, trends, and patterns. "
        "Present findings with supporting evidence."
    ),
    tools=[data_analysis_tool, visualization_tool],
)

writing_agent = Agent(
    name="Writing Specialist",
    instructions=(
        "You are a writing specialist. Take the provided research "
        "and analysis, and produce clear, well-structured content. "
        "Match the requested tone and format."
    ),
)


# Supervisor that uses specialists as tools
supervisor_agent = Agent(
    name="Research Supervisor",
    instructions=(
        "You coordinate research projects. Use the research specialist "
        "to gather information, the analysis specialist to process data, "
        "and the writing specialist to produce the final output. "
        "Delegate tasks and synthesize results."
    ),
    tools=[
        research_agent.as_tool(
            tool_name="research",
            tool_description="Research a topic and return findings"
        ),
        analysis_agent.as_tool(
            tool_name="analyze",
            tool_description="Analyze data and return insights"
        ),
        writing_agent.as_tool(
            tool_name="write",
            tool_description="Write content based on provided materials"
        ),
    ],
)

Building a Complete Hierarchical System

Let’s build a real-world example: a content production pipeline with research, editing, and publishing agents.

Define the Specialist Agents

# agents/specialists.py
from agents import Agent


# Research agent
research_agent = Agent(
    name="Researcher",
    instructions="""You are a research specialist.
    
    Your job is to gather comprehensive information on a topic:
    1. Search for recent, relevant sources
    2. Extract key facts, statistics, and expert opinions
    3. Identify trends and patterns
    4. Note any conflicting viewpoints
    
    Return your findings as a structured summary with sources.""",
    tools=[web_search, fetch_url, search_academic],
)

# Fact-checking agent
fact_checker_agent = Agent(
    name="Fact Checker",
    instructions="""You are a fact-checking specialist.
    
    Given a set of claims and sources:
    1. Verify each claim against multiple sources
    2. Rate confidence level (verified, likely, unverified, false)
    3. Identify any unsupported assertions
    4. Flag potential misinformation
    
    Return a fact-check report with confidence ratings.""",
    tools=[web_search, verify_source, cross_reference],
)

# Editing agent
editor_agent = Agent(
    name="Editor",
    instructions="""You are a content editor.
    
    Given raw content:
    1. Fix grammar, spelling, and punctuation
    2. Improve clarity and flow
    3. Ensure consistent tone and style
    4. Strengthen arguments and evidence
    5. Add transitions between sections
    
    Return polished, publication-ready content.""",
    tools=[grammar_check, style_guide, readability_analysis],
)

# SEO agent
seo_agent = Agent(
    name="SEO Specialist",
    instructions="""You are an SEO optimization specialist.
    
    Given content and target keywords:
    1. Optimize title and headers for search
    2. Ensure natural keyword integration
    3. Add meta descriptions and alt text suggestions
    4. Identify internal linking opportunities
    5. Suggest content structure improvements
    
    Return SEO-optimized content with recommendations.""",
    tools=[keyword_research, competitor_analysis, seo_audit],
)

Build the Supervisor

# agents/content_pipeline.py
from agents import Agent, Runner


content_supervisor = Agent(
    name="Content Pipeline Supervisor",
    instructions="""You manage the content production pipeline.
    
    Workflow:
    1. RECEIVE: Get the topic, target audience, and content type
    2. RESEARCH: Use the research agent to gather information
    3. FACT-CHECK: Verify claims with the fact-checking agent
    4. WRITE: Draft content using the research and fact-checks
    5. EDIT: Polish with the editor agent
    6. SEO: Optimize with the SEO agent
    
    Always complete each step before moving to the next.
    If fact-checking reveals issues, go back to research.
    Return the final, publication-ready content.""",
    tools=[
        research_agent.as_tool(
            tool_name="research_topic",
            tool_description="Research a topic and gather information"
        ),
        fact_checker_agent.as_tool(
            tool_name="verify_claims",
            tool_description="Fact-check claims and verify accuracy"
        ),
        editor_agent.as_tool(
            tool_name="edit_content",
            tool_description="Edit and polish content"
        ),
        seo_agent.as_tool(
            tool_name="optimize_seo",
            tool_description="Optimize content for search engines"
        ),
    ],
)

Run the Pipeline

# main.py
from agents import Runner


async def produce_content(topic: str, audience: str, content_type: str):
    """Run the content production pipeline."""
    
    prompt = f"""
    Create a {content_type} about "{topic}" for {audience}.
    
    Requirements:
    - Well-researched with current data
    - Fact-checked and accurate
    - Professionally edited
    - SEO optimized
    - Ready for publication
    """
    
    result = await Runner.run(content_supervisor, prompt)
    
    return result.final_output


# Usage
async def main():
    content = await produce_content(
        topic="AI agent governance in 2026",
        audience="technical leaders",
        content_type="blog post",
    )
    
    print(content)

Advanced Patterns: Parallel Execution

When specialist agents don’t depend on each other, run them in parallel for faster execution.

# agents/parallel_pipeline.py
import asyncio
from agents import Agent, Runner


async def parallel_research(topic: str) -> dict:
    """Run multiple research agents in parallel."""
    
    # Define parallel research tasks
    academic_research = Agent(
        name="Academic Researcher",
        instructions="Focus on academic papers, citations, and scholarly sources.",
        tools=[academic_search, citation_database],
    )
    
    industry_research = Agent(
        name="Industry Researcher",
        instructions="Focus on industry reports, case studies, and practical applications.",
        tools=[industry_reports, case_studies],
    )
    
    news_research = Agent(
        name="News Researcher",
        instructions="Focus on recent news, announcements, and trending topics.",
        tools=[news_search, social_media],
    )
    
    # Run all three in parallel
    results = await asyncio.gather(
        Runner.run(academic_research, f"Research academic perspectives on {topic}"),
        Runner.run(industry_research, f"Research industry perspectives on {topic}"),
        Runner.run(news_research, f"Research recent news about {topic}"),
    )
    
    # Combine results
    combined_research = {
        "academic": results[0].final_output,
        "industry": results[1].final_output,
        "news": results[2].final_output,
    }
    
    return combined_research


# Synthesis agent that combines parallel results
synthesis_agent = Agent(
    name="Research Synthesizer",
    instructions=(
        "Combine multiple research sources into a coherent summary. "
        "Identify common themes, conflicting viewpoints, and unique insights."
    ),
)


async def comprehensive_research(topic: str):
    """Run parallel research and synthesize results."""
    research = await parallel_research(topic)
    
    synthesis_prompt = f"""
    Synthesize the following research sources:
    
    ACADEMIC SOURCES:
    {research['academic']}
    
    INDUSTRY SOURCES:
    {research['industry']}
    
    NEWS SOURCES:
    {research['news']}
    
    Create a comprehensive summary that:
    1. Identifies consensus across sources
    2. Highlights disagreements or conflicting data
    3. Notes unique insights from each source type
    4. Provides an overall assessment
    """
    
    result = await Runner.run(synthesis_agent, synthesis_prompt)
    return result.final_output

Error Handling and Recovery

Hierarchical systems need robust error handling. What happens when a specialist fails?

# agents/error_handling.py
from agents import Agent, Runner
from agents.exceptions import AgentError


async def resilient_pipeline(topic: str):
    """Pipeline with error recovery."""
    
    research_agent = Agent(
        name="Researcher",
        instructions="Research the given topic thoroughly.",
        tools=[web_search, fetch_url],
    )
    
    fallback_research_agent = Agent(
        name="Fallback Researcher",
        instructions=(
            "The primary research agent failed. "
            "Research the topic using alternative sources."
        ),
        tools=[alternative_search, cached_results],
    )
    
    try:
        result = await Runner.run(research_agent, f"Research: {topic}")
        return result.final_output
    except AgentError as e:
        print(f"Primary research failed: {e}. Using fallback.")
        result = await Runner.run(
            fallback_research_agent, 
            f"Research: {topic}"
        )
        return result.final_output


# Retry with exponential backoff
async def retry_with_backoff(
    agent: Agent,
    prompt: str,
    max_retries: int = 3,
    base_delay: float = 1.0,
):
    """Run an agent with retry logic."""
    import asyncio
    
    for attempt in range(max_retries):
        try:
            result = await Runner.run(agent, prompt)
            return result
        except AgentError as e:
            if attempt == max_retries - 1:
                raise
            
            delay = base_delay * (2 ** attempt)
            print(f"Attempt {attempt + 1} failed: {e}. Retrying in {delay}s...")
            await asyncio.sleep(delay)
    
    raise RuntimeError("Max retries exceeded")

Observability for Multi-Agent Systems

When you have multiple agents, observability becomes critical. Use tracing to understand execution flow.

# agents/traced_pipeline.py
from agents import Agent, Runner
from agents.tracing import trace, Span


async def traced_pipeline(topic: str):
    """Pipeline with full tracing."""
    
    with trace("content_production", metadata={"topic": topic}):
        # Research phase
        with trace("research_phase"):
            research = await Runner.run(
                research_agent, 
                f"Research: {topic}"
            )
        
        # Analysis phase
        with trace("analysis_phase", metadata={"research_length": len(research.final_output)}):
            analysis = await Runner.run(
                analysis_agent,
                f"Analyze: {research.final_output}"
            )
        
        # Writing phase
        with trace("writing_phase"):
            draft = await Runner.run(
                writing_agent,
                f"Write about: {analysis.final_output}"
            )
        
        # Editing phase
        with trace("editing_phase"):
            final = await Runner.run(
                editor_agent,
                f"Edit: {draft.final_output}"
            )
        
        return final.final_output

Best Practices

  1. Single Responsibility: Each agent should do one thing well. If an agent’s instructions exceed a paragraph, split it.

  2. Clear Interfaces: Agents-as-tools should have clear input/output contracts. The tool description is the interface—make it precise.

  3. Supervisor Simplicity: The supervisor should coordinate, not execute. If the supervisor is doing complex logic, split it into another specialist.

  4. Error Boundaries: Each agent should handle its own errors gracefully. Don’t let one specialist’s failure crash the entire pipeline.

  5. Tracing: Instrument every agent execution. When debugging multi-agent systems, you need to know which agent failed and why.

Common Pitfalls

  • Circular delegation: Agent A calls Agent B, which calls Agent A. Set maximum delegation depth.
  • Context passing overhead: Passing large contexts between agents wastes tokens. Pass summaries, not raw data.
  • Over-delegation: If a task is simple, don’t route it through three agents. Direct execution is sometimes better.
  • Missing handoff criteria: Without clear criteria for when to hand off vs. handle directly, agents waste time deciding.

Conclusion

The agents-as-tools pattern transforms single-agent limitations into multi-agent capabilities. By composing specialized agents hierarchically, you build systems that are more capable, more maintainable, and easier to debug than monolithic alternatives.

The OpenAI Agents SDK makes this pattern accessible with minimal abstractions. The as_tool() method turns any agent into a callable tool, and Runner handles the orchestration. The complexity is in the design, not the implementation.

Start small: identify the most complex part of your current agent, extract it into a specialist, and let your main agent delegate to it. Once you see the pattern work, the rest follows naturally.

Next steps:

  • Start with the OpenAI Agents SDK quickstart
  • Identify one task in your current agent that could be a specialist
  • Implement the agents-as-tools pattern for that task
  • Add tracing to understand execution flow
  • Read the agent orchestration guide for handoffs vs. tools decisions