---
name: agentbyte-ai-driven-orchestration
description: Guide for creating AI-Driven multi-agent orchestration in Agentbyte (Chapter 7.4). Use this when you need LLM-based adaptive agent selection instead of fixed turn sequences.
license: MIT
---

Use this skill when implementing multi-agent collaboration where an LLM intelligently selects which agent should respond next based on conversation context and agent capabilities.

## Pattern: Basic AI-Driven Orchestration

```python
import asyncio
from agentbyte import AIOrchestrator, Agent, UserMessage
from agentbyte.llm import OpenAIChatCompletionClient
from agentbyte.termination import MaxMessageTermination, TextMentionTermination

async def main():
    # 1. Create model client
    client = OpenAIChatCompletionClient.from_api_key(model="gpt-4o-mini")

    # 2. Create agents with clear descriptions (LLM uses these for selection)
    researcher = Agent(
        name="researcher",
        description="Research specialist for factual and contextual information",
        instructions=(
            "You are a research specialist. Provide concise factual insights "
            "and clarify missing context when needed."
        ),
        model_client=client
    )

    writer = Agent(
        name="writer",
        description="Content specialist for polished user-facing writing",
        instructions=(
            "You are a writer. Synthesize available information into concise, "
            "high-quality prose. End with TERMINATE when complete."
        ),
        model_client=client
    )

    # 3. Define termination conditions
    termination = MaxMessageTermination(8) | TextMentionTermination("TERMINATE")

    # 4. Initialize AI orchestrator (requires model_client for selection)
    orchestrator = AIOrchestrator(
        agents=[researcher, writer],
        termination=termination,
        model_client=client,  # Required: LLM for agent selection
        max_iterations=6
    )

    # 5. Run the collaboration
    task = UserMessage(
        content="Write a short note about the benefits of solar energy",
        source="user"
    )
    
    result = await orchestrator.run(task)

    print(f"Stop reason: {result.stop_message.content}")
    print(f"Iterations: {result.pattern_metadata.get('iterations_completed')}")
    print(f"Selector calls: {result.pattern_metadata.get('selector_calls')}")
    print(f"Total tokens: {result.usage.total_tokens}")

asyncio.run(main())
```

## Pattern: Streaming AI-Driven Orchestration

```python
async for item in orchestrator.run_stream(task, verbose=True):
    if isinstance(item, Message):
        print(f"[{item.source}] {item.content}")
    elif isinstance(item, OrchestrationEvent):
        # AgentSelectionEvent includes AI reasoning
        if hasattr(item, 'reason'):
            print(f"Selection reason: {item.reason}")
    elif isinstance(item, OrchestrationResponse):
        print(f"Complete: {item.stop_message.content}")
```

## How AI Selection Works

1. **Structured Output:** The orchestrator uses LLM with structured output (`AgentSelection` schema) to select the next agent
2. **Context Awareness:** The LLM sees conversation history and all agent descriptions
3. **Reasoning Included:** Selection events include the LLM's reasoning for why it chose that agent
4. **Fallback Safety:** If LLM selection fails or returns invalid agent name, falls back to round-robin

## Configuration Options

```python
orchestrator = AIOrchestrator(
    agents=[agent1, agent2, agent3],     # Required: List of agents
    termination=termination_condition,    # Required: When to stop
    model_client=selection_model_client,  # Required: LLM for agent selection
    max_iterations=10,                    # Optional: Safety limit (default: 10)
    verbose=False                         # Optional: Enable event logging
)
```

## Pattern Metadata

After completion, `result.pattern_metadata` contains:
- `iterations_completed`: Total agent executions
- `selector_calls`: Number of LLM selection calls made
- `fallback_count`: How many times round-robin fallback was used
- `final_reason`: Why orchestration stopped

## Usage Tracking

The orchestrator tracks token usage from:
- All agent executions
- All selector LLM calls (agent selection)

Final `result.usage` includes comprehensive totals across all LLM interactions.

## Agent Description Best Practices

The LLM uses agent descriptions to make selection decisions. Write clear, specific descriptions:

✅ **Good:**
```python
description="Research specialist for factual and contextual information"
description="Content specialist for polished user-facing writing"
description="Code reviewer that checks for bugs and style issues"
```

❌ **Avoid:**
```python
description="A helpful agent"  # Too vague
description="Agent 1"  # No capability info
```

## Guardrails

- **Model Client Required:** `AIOrchestrator` needs a `model_client` parameter for agent selection (unlike `RoundRobinOrchestrator`).
- **Clear Descriptions:** Write specific agent descriptions—the LLM uses these to decide who should respond.
- **Termination Required:** Always provide termination conditions to prevent infinite loops.
- **Safety Fallback:** If LLM selection fails, orchestrator falls back to round-robin (check `fallback_count` in metadata).
- **Usage Accounting:** Final usage includes both agent tokens AND selector tokens.
- **Case Insensitive:** Agent name matching is case-insensitive for robustness.
- **Event Observability:** Use `verbose=True` with `run_stream()` to see AI selection reasoning.

## When to Use AI-Driven vs Round-Robin

| Use AI-Driven When | Use Round-Robin When |
|--------------------|----------------------|
| Agent roles are specialized | Agents always alternate (poet/critic) |
| Order should adapt to context | Fixed workflow is desired |
| You have 3+ agents | You have exactly 2 agents |
| Complexity requires smart routing | Simple back-and-forth suffices |
| You want LLM to decide flow | You want deterministic order |

## Common Use Cases

1. **Research → Write → Review:** LLM decides when research is sufficient, when to write, when to review
2. **Multi-Specialist Teams:** Route to the right expert (data analyst, writer, coder, reviewer)
3. **Adaptive Workflows:** Let LLM determine optimal agent sequence based on task complexity
4. **Dynamic Collaboration:** Agents with overlapping capabilities—LLM picks best fit
5. **Question Routing:** Route user questions to the most appropriate agent based on content

## Examples

- Basic: `examples/orchestration/ai_driven_basic.py`
- Streaming: `examples/orchestration/ai_driven_stream.py`
- With OTel: `examples/orchestration/ai_driven_with_otel.py`

## OpenTelemetry Integration

For observability with Jaeger:

```python
import os
# Set BEFORE importing agentbyte
os.environ["AGENTBYTE_ENABLE_OTEL"] = "true"
os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = "http://localhost:4318"
os.environ["OTEL_SERVICE_NAME"] = "my-ai-orchestration"

from agentbyte import AIOrchestrator
# ... rest of code
```

Traces will show:
- Orchestration span (parent)
- Selector LLM calls (for agent selection)
- Individual agent execution spans
- Token usage aggregated at orchestration level
