# Team Runs

## What is a TeamRun?

A TeamRun represents a sequential execution pipeline of agents. Unlike Teams which define agent groups, TeamRuns manage how agents process data in sequence, with each agent receiving the output of the previous one.

The key aspects are:

- Sequential processing order
- Message flow between agents
- Execution monitoring
- Resource management

## Creating TeamRuns

### From Pool

```python
# Create execution pipeline from agent names
run = pool.create_team_run(["analyzer", "planner", "executor"])
```

### Using Pipeline Operator

```python
# Create sequential pipeline from agents
pipeline = analyzer | planner | executor

def clean_data(msg: str) -> str:
    return f"Cleaned: {msg}"

# With function transformers
pipeline = analyzer | clean_data | planner | execute_plan

# Mixing teams
pipeline = analysis_team | planning_team | execution_team
```

## Running a TeamRun

### Direct Execution

Simple run that waits for completion:
```python
# Run and wait for results
results = await run.execute("Process this task")

# Access results
for response in results:
    print(f"{response.agent_name}: {response.message.content}")
```

### Monitored Execution

Get statistics while the run executes in background:
```python
# Start run and get stats object
stats = run.run_in_background("Process this task")

# Wait for completion when needed
results = await run.wait()
```

For detailed monitoring capabilities, see [Task Monitoring](../advanced/task_monitoring.md).

## Iterating Over Execution

For fine-grained control, you can use `execute_iter()` which yields:

- Connection objects (`Talk`) before they're used
- Responses (`AgentResponse`) after each agent executes

This allows you to:

- Configure routing before messages flow
- Monitor individual results
- Handle errors per agent
- Transform messages between agents

Example:
```python
async for item in run.execute_iter("analyze this"):
    match item:
        case Talk():
            print(f"Next: {item.source.name} -> {item.target.name}")
            # Configure connection if needed
            item.transform = lambda msg: f"Previous: {msg.content}"
        case AgentResponse():
            if item.success:
                print(f"✅ {item.agent_name}: {item.message.content}")
            else:
                print(f"❌ {item.agent_name}: {item.error}")
                break
```

## Resource Management

TeamRuns handle cleanup automatically:

- Background tasks are tracked
- Connections are properly closed
- Resources are released on completion

You can also explicitly control the run:
```python
# Cancel execution
await run.cancel()

# Check status
if run.is_running:
    print("Still processing...")
```

### Content Distribution

The `distribute()` method allows sharing content and capabilities across all team members:

```python
# Share knowledge with all agents
await run.distribute(
    "Context: This is background information all agents should know.",
    tools=["search_docs", "analyze_data"],  # Share specific tools
    resources=["knowledge_base", "guidelines"],  # Share resources
)
```

### Properties and Status

```python
# Access team members
run.agents  # List of agents in the pipeline
run.name    # Team name (defaults to concatenated agent names)

# Check execution state
run.is_running  # Whether execution is active
run.stats      # Current execution statistics
```

## Team Statistics

The `stats` property provides aggregated information about the execution:

```python
stats = run.stats

# Basic information
print(f"Team: {stats.source_names} → {stats.target_names}")
print(f"Active connections: {stats.num_connections}")
print(f"Messages: {stats.message_count}")

# Cost tracking
print(f"Total tokens: {stats.token_count}")
print(f"Total cost: ${stats.total_cost:.4f}")
print(f"Bytes transferred: {stats.byte_count}")

# Message access
for msg in stats.messages:
    print(f"{msg.name}: {msg.content}")

# Error tracking
for agent, error, time in stats.errors:
    print(f"{agent} failed at {time}: {error}")
```

## Running in Background

The base class provides background execution support:

```python
# Start execution
stats = run.run_in_background("Process this")

# Wait for completion later
results = await run.wait()

# Or cancel if needed
await run.cancel()
```

## Resource Management

The base class handles:

- Task tracking and cleanup
- Connection management
- Error propagation
- Background task cancellation

This ensures proper cleanup even in error cases:

```python
try:
    stats = run.run_in_background("Process this")
    # ... do other things ...
    results = await run.wait()
except Exception:
    # Background tasks are automatically cleaned up
    # Connections are properly closed
    await run.cancel()  # Explicit cancellation if needed
```


The combination of sequential processing and monitoring capabilities makes TeamRuns suitable for both simple pipelines and complex multi-agent workflows.
