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:
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:
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:
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_turns | Use Case | Example |
---|---|---|
1 | Single tool call | Weather check, simple calculation |
2-3 | Sequential operations | Search then summarize, calculate then format |
4-6 | Complex workflows | Data pipeline, multi-step analysis |
7-10 | Iterative processes | Debug and fix code, refine results |
10+ | Open-ended tasks | Research 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.