Skip to main content
Batch Agents execute multiple agent instances in parallel, either returning the first successful result or collecting all results.

Overview

Run multiple agents concurrently with different strategies:
batch_agent.py
import asyncio
from notte_sdk import NotteClient
from notte_sdk.endpoints.agents import BatchRemoteAgent

client = NotteClient()

async def run_batch():
    with client.Session() as session:
        batch_agent = BatchRemoteAgent(
            session=session,
            max_steps=15,
            _client=client
        )

        # Run 3 agents in parallel, return first success
        result = await batch_agent.run(
            task="Find and extract pricing information",
            n_jobs=3,
            strategy="first_success"
        )

        return result

result = asyncio.run(run_batch())
print(f"Success: {result.success}")
print(f"Answer: {result.answer}")

Why Use Batch Agents?

Improved Success Rate

Agents can fail due to:
  • Timing issues
  • Random page behavior
  • Rate limiting
  • Network issues
Running multiple attempts in parallel increases success probability:
# Single agent: 70% success rate
# 3 parallel agents: 97% success rate (1 - 0.3^3)

Faster Time-to-Success

Return as soon as any agent succeeds:
# Single agent: might take 60 seconds and fail
# 3 parallel agents: first success in ~20 seconds

Strategies

First Success

Return immediately when any agent succeeds:
batch_agent = BatchRemoteAgent(
    session=session,
    max_steps=10,
    _client=client
)

# Run 3 agents, return first success
result = await batch_agent.run(
    task="Complete task",
    n_jobs=3,
    strategy="first_success"  # Default
)

print(result.success)  # True if any agent succeeded
print(result.answer)   # Answer from successful agent
When to use:
  • Non-deterministic pages
  • Tasks prone to failures
  • Time-sensitive operations
  • You only need one successful result

All Finished

Wait for all agents to complete:
# Run 5 agents, wait for all
results = await batch_agent.run(
    task="Extract data",
    n_jobs=5,
    strategy="all_finished"
)

# Returns list of results
for i, result in enumerate(results):
    print(f"Agent {i+1}: Success={result.success}")
When to use:
  • Comparing agent outputs
  • Gathering multiple perspectives
  • Testing different approaches
  • Statistical analysis

Configuration

Session Parameters

Batch agents create multiple sessions with the same configuration:
with client.Session(
    headless=True,
    proxies="us",
    browser_type="chrome"
) as session:
    batch_agent = BatchRemoteAgent(
        session=session,
        reasoning_model="gemini/gemini-2.0-flash",
        max_steps=15,
        use_vision=True,
        _client=client
    )

    # All parallel agents use same session config
    result = await batch_agent.run(task="Task", n_jobs=3)

Number of Jobs

Control parallelism with n_jobs:
# Light parallelism (2-3 agents)
result = await batch_agent.run(task="Task", n_jobs=2)

# Medium parallelism (3-5 agents)
result = await batch_agent.run(task="Task", n_jobs=5)

# Heavy parallelism (5-10 agents)
result = await batch_agent.run(task="Task", n_jobs=10)
Cost consideration: Each agent incurs full costs, so n_jobs=5 costs 5x a single agent.

Agent Parameters

Pass any agent parameter:
batch_agent = BatchRemoteAgent(
    session=session,
    reasoning_model="anthropic/claude-3.5-sonnet",
    max_steps=20,
    use_vision=True,
    vault=vault,
    persona=persona,
    _client=client
)

Use Cases

1. Unreliable Pages

Pages with random failures:
# Page sometimes has timing issues
with client.Session() as session:
    batch_agent = BatchRemoteAgent(
        session=session,
        max_steps=10,
        _client=client
    )

    # Run 3 attempts
    result = await batch_agent.run(
        task="Click the submit button that appears after 2 seconds",
        n_jobs=3,
        strategy="first_success"
    )

    # Much higher success rate than single agent

2. Rate-Limited Sites

Avoid rate limit failures:
# Some agents might get rate limited
with client.Session(proxies="residential") as session:
    batch_agent = BatchRemoteAgent(
        session=session,
        max_steps=15,
        _client=client
    )

    # Run 5 agents from different IPs
    result = await batch_agent.run(
        task="Extract product data",
        n_jobs=5,
        strategy="first_success"
    )

3. A/B Testing

Test which model works best:
# Test different models
models = [
    "gemini/gemini-2.0-flash",
    "anthropic/claude-3.5-sonnet",
    "openai/gpt-4o"
]

results = []
for model in models:
    batch_agent = BatchRemoteAgent(
        session=session,
        reasoning_model=model,
        _client=client
    )

    result = await batch_agent.run(
        task="Complex task",
        n_jobs=3,
        strategy="first_success"
    )

    results.append({
        "model": model,
        "success": result.success,
        "steps": len(result.steps)
    })

# Compare which model performed best

4. Consensus Results

Get multiple agent opinions:
batch_agent = BatchRemoteAgent(
    session=session,
    max_steps=10,
    _client=client
)

# Get results from all agents
results = await batch_agent.run(
    task="Extract the company's revenue",
    n_jobs=5,
    strategy="all_finished"
)

# Find consensus
revenues = [r.answer for r in results if r.success]
consensus = max(set(revenues), key=revenues.count)

Performance

Execution Time

With first_success strategy:
# Single agent: 40 seconds average
# Batch of 3: ~13 seconds (first success)
# Speedup: ~3x faster for successful case

Cost

Batch agents cost more:
# Single agent: $0.02
# Batch of 3: $0.06 (3x cost)
# Batch of 5: $0.10 (5x cost)

# But: Higher success rate means fewer retries

Success Rate

Probability of at least one success:
Single Agent Success2 Parallel3 Parallel5 Parallel
50%75%87.5%96.9%
70%91%97.3%99.8%
80%96%99.2%99.97%

Best Practices

1. Start with 2-3 Parallel Agents

Balance cost and reliability:
# Good starting point
result = await batch_agent.run(
    task="Task with ~70% success rate",
    n_jobs=3,  # 97% combined success
    strategy="first_success"
)

2. Use for Critical Tasks

Worth the cost for important operations:
# Critical: Use batch
with client.Session() as session:
    batch_agent = BatchRemoteAgent(session=session, _client=client)
    result = await batch_agent.run(
        task="Process payment",
        n_jobs=3
    )

# Non-critical: Use single agent
agent = client.Agent(session=session)
result = agent.run(task="Nice-to-have data")

3. Monitor Success Rates

Track if batch execution is needed:
import asyncio

# Test single agent success rate
successes = 0
for _ in range(10):
    result = agent.run(task="Test task")
    if result.success:
        successes += 1

success_rate = successes / 10

if success_rate < 0.8:
    # Use batch for low success rates
    batch_agent = BatchRemoteAgent(session=session, _client=client)
    result = await batch_agent.run(task="Test task", n_jobs=3)

4. Use Appropriate Strategy

Choose based on your needs:
# Need one good result quickly
strategy="first_success"

# Need to compare multiple results
strategy="all_finished"

# Need statistical confidence
strategy="all_finished"

5. Set Reasonable Timeouts

Prevent hanging:
async def run_with_timeout():
    batch_agent = BatchRemoteAgent(session=session, _client=client)

    try:
        result = await asyncio.wait_for(
            batch_agent.run(task="Task", n_jobs=3),
            timeout=120  # 2 minute timeout
        )
        return result
    except asyncio.TimeoutError:
        print("Batch execution timed out")
        raise

result = await run_with_timeout()

Limitations

Resource Usage

Batch agents consume more resources:
  • Sessions: Creates n separate sessions
  • Browsers: Opens n browser instances
  • Memory: n times single agent memory
  • API calls: n times single agent calls

Concurrency Limits

Account for rate limits:
# May hit account concurrency limit
result = await batch_agent.run(
    task="Task",
    n_jobs=20  # Might exceed concurrent session limit
)

# Safer approach
result = await batch_agent.run(
    task="Task",
    n_jobs=5  # Within typical limits
)

Cost Scaling

Costs multiply with n_jobs:
# Single agent task: $0.02
# n_jobs=3: $0.06
# n_jobs=10: $0.20

# Use batch only when success rate justifies cost

Async Only

Batch agents require async execution:
import asyncio

async def run_batch():
    batch_agent = BatchRemoteAgent(session=session, _client=client)
    result = await batch_agent.run(task="Task", n_jobs=3)
    return result

# Must use asyncio.run
result = asyncio.run(run_batch())

# Or in async context
result = await run_batch()

Next Steps