Write agentic apps once, run with any LLM provider

Agentic Loops with max_turns

Transform your LLM into an autonomous agent that can plan, execute, and iterate on complex tasks using the max_turns parameter.

🤖 What Makes an Agent?

An agent is an LLM that can autonomously use tools to accomplish goals. With AISuite's max_turns, your LLM becomes an agent that can:

  • Plan: Break down complex tasks into steps
  • Execute: Use tools to perform actions
  • Observe: Process tool outputs and results
  • Iterate: Adjust approach based on results

How max_turns Enables Agents

Without max_turns (Traditional):

You get a single response. If the LLM wants to use a tool, you must manually handle it, call the tool, and make another request.

With max_turns (Agent Mode):

The LLM can use tools multiple times, building on previous results. AISuite handles the entire execution loop automatically.

Example 1: Research Agent

An agent that can search, analyze, summarize, and save information:

Research agent
import aisuite as ai

def search_web(query: str):
    """Search the web for information."""
    # Simulate web search
    return f"Results for: {query}"

def summarize_text(text: str, max_words: int = 100):
    """Summarize text to specified length."""
    # Your summarization logic
    return f"Summary of {len(text)} chars in {max_words} words"

def save_to_file(filename: str, content: str):
    """Save content to a file."""
    with open(filename, 'w') as f:
        f.write(content)
    return f"Saved to {filename}"

client = ai.Client()

# Create a research agent that can search, summarize, and save
response = client.chat.completions.create(
    model="openai:gpt-4o",
    messages=[{
        "role": "user",
        "content": "Research the latest developments in quantum computing, "
                   "summarize the findings, and save to quantum_research.txt"
    }],
    tools=[search_web, summarize_text, save_to_file],
    max_turns=5  # Allow up to 5 tool interactions
)

print(response.choices[0].message.content)

# View the agent's workflow
print("\nAgent workflow:")
for msg in response.choices[0].intermediate_messages:
    if hasattr(msg, 'tool_calls'):
        for call in msg.tool_calls:
            print(f"→ Called {call.function.name}({call.function.arguments})")

Example 2: Data Analysis Agent

An agent that can load data, perform analysis, create visualizations, and generate reports:

Data analysis agent
import aisuite as ai
import json

def load_data(file_path: str):
    """Load data from a CSV or JSON file."""
    # Implementation to load data
    return {"rows": 1000, "columns": ["date", "sales", "region"]}

def analyze_data(data: dict, analysis_type: str):
    """Perform statistical analysis on data."""
    # Your analysis logic
    return {"mean": 45.2, "std": 12.3, "trend": "increasing"}

def create_visualization(data: dict, chart_type: str):
    """Create a data visualization."""
    # Visualization logic
    return f"Created {chart_type} chart"

def generate_report(analysis: dict, charts: list):
    """Generate a comprehensive report."""
    return f"Report with {len(analysis)} analyses and {len(charts)} charts"

client = ai.Client()

# Data analysis agent
response = client.chat.completions.create(
    model="anthropic:claude-3-5-sonnet-20240620",
    messages=[{
        "role": "user",
        "content": "Analyze the sales data in sales_2024.csv, "
                   "create visualizations, and generate a report"
    }],
    tools=[load_data, analyze_data, create_visualization, generate_report],
    max_turns=6  # Complex workflow needs more turns
)

# The agent autonomously:
# 1. Loads the data
# 2. Performs multiple analyses
# 3. Creates appropriate visualizations
# 4. Generates a comprehensive report

Example 3: Self-Improving Code Agent

An agent that can write code, test it, and iteratively fix issues:

Iterative code agent
import aisuite as ai

def run_code(code: str):
    """Execute Python code and return output."""
    try:
        exec_globals = {}
        exec(code, exec_globals)
        return "Code executed successfully"
    except Exception as e:
        return f"Error: {str(e)}"

def fix_code(code: str, error: str):
    """Attempt to fix code based on error message."""
    # Simple fix logic - in practice, could be more sophisticated
    if "NameError" in error:
        return code.replace("print", "print")  # Example fix
    return code

def test_code(code: str, test_cases: list):
    """Run test cases against code."""
    passed = 0
    for test in test_cases:
        # Test logic here
        passed += 1
    return f"{passed}/{len(test_cases)} tests passed"

client = ai.Client()

# Self-improving code agent
response = client.chat.completions.create(
    model="openai:gpt-4o",
    messages=[{
        "role": "user",
        "content": "Write a function to calculate fibonacci numbers, "
                   "test it, and fix any issues until all tests pass"
    }],
    tools=[run_code, fix_code, test_code],
    max_turns=10  # Allow iteration until solution works
)

Understanding max_turns

max_turnsUse CaseExample
1Single tool callWeather check, simple calculation
2-3Sequential operationsSearch then summarize, calculate then format
4-6Complex workflowsData pipeline, multi-step analysis
7-10Iterative processesDebug and fix code, refine results
10+Open-ended tasksResearch projects, complex problem solving

Accessing the Agent's Workflow

The intermediate_messages property gives you full visibility into the agent's decision-making process:

# Access all intermediate messages
for msg in response.choices[0].intermediate_messages:
    if hasattr(msg, 'role'):
        print(f"{msg.role}: {msg.content[:100]}...")
    if hasattr(msg, 'tool_calls'):
        for call in msg.tool_calls:
            print(f"Tool: {call.function.name}")
            print(f"Args: {call.function.arguments}")
    if hasattr(msg, 'tool_call_id'):
        print(f"Tool Result: {msg.content}")

Best Practices for Building Agents

🎯 Clear Instructions

Give agents specific goals and constraints. "Research X and save to file Y" is better than "learn about X".

🔧 Composable Tools

Provide tools that work well together. Each tool should have a clear purpose and return useful information.

⚖️ Balance Autonomy

Set max_turns high enough for task completion but not so high that costs spiral. Monitor usage.

📊 Provide Feedback

Tools should return informative results that help the agent make decisions and track progress.

🛡️ Safety First

Validate tool inputs, limit destructive operations, and implement safeguards for production agents.

📝 Log Everything

Use intermediate_messages to debug agent behavior and understand decision-making patterns.

Common Agent Patterns

Sequential Pipeline

Load → Process → Analyze → Save. Each step depends on the previous one.

Iterative Refinement

Try → Evaluate → Improve → Repeat. Agent improves results through multiple attempts.

Exploration

Search → Investigate → Branch → Synthesize. Agent explores multiple paths to find solutions.

Orchestration

Coordinate multiple tools and services to accomplish complex goals.

Next Steps