opper-python-agents
SKILL.md
Opper Python Agents
Build AI agents with think-act reasoning loops, typed tools, multi-agent composition, memory, and full observability.
Installation
pip install opper-agents
Set your API key:
export OPPER_API_KEY="your-api-key"
Get your API key from platform.opper.ai.
Core Pattern: Agent with Tools
Define tools with the @tool decorator, create an agent, and run it:
from opper_agents import Agent, tool
@tool
def get_weather(city: str) -> str:
"""Get the current weather for a city."""
return f"The weather in {city} is 22°C and sunny"
@tool
def get_population(city: str) -> int:
"""Get the population of a city."""
populations = {"Paris": 2_161_000, "London": 8_982_000}
return populations.get(city, 0)
agent = Agent(
name="CityBot",
instructions="Help users with city information using available tools.",
tools=[get_weather, get_population],
)
result = await agent.process("What's the weather and population of Paris?")
print(result)
# "Paris has a population of 2,161,000 and the weather is 22°C and sunny."
How the Agent Loop Works
The agent follows a Think-Act-Observe loop:
- Think: The LLM analyzes the goal and available tools
- Act: It selects and executes a tool
- Observe: Results are added to the conversation history
- Loop/Return: Repeat until the goal is met, then return the final answer
The loop runs up to max_iterations times (default: 25).
Structured Output
Use Pydantic models to get typed, validated results:
from pydantic import BaseModel, Field
from typing import List
class CityReport(BaseModel):
city: str
temperature_c: float
population: int
summary: str = Field(description="One-sentence summary")
agent = Agent(
name="CityReporter",
instructions="Generate a city report using available tools.",
tools=[get_weather, get_population],
output_schema=CityReport,
)
result = await agent.process("Report on London")
# result is a CityReport instance
print(result.city) # "London"
print(result.temperature_c) # 18.0
print(result.population) # 8982000
Model Selection
Specify which LLM the agent uses for reasoning:
agent = Agent(
name="SmartAgent",
instructions="You are a helpful assistant.",
tools=[my_tool],
model="anthropic/claude-4-sonnet",
)
# With fallback chain
agent = Agent(
name="ResilientAgent",
instructions="You are a helpful assistant.",
tools=[my_tool],
model=["anthropic/claude-4-sonnet", "openai/gpt-4o"],
)
Async Tools
For I/O-bound operations, define async tools:
import httpx
@tool
async def fetch_url(url: str) -> str:
"""Fetch content from a URL."""
async with httpx.AsyncClient() as client:
response = await client.get(url)
return response.text[:1000]
Multi-Agent Composition
Use agents as tools within other agents for delegation:
math_agent = Agent(
name="MathAgent",
instructions="Solve math problems step by step.",
tools=[add, multiply],
)
research_agent = Agent(
name="ResearchAgent",
instructions="Answer factual questions.",
tools=[search_web],
)
coordinator = Agent(
name="Coordinator",
instructions="Delegate tasks to specialist agents.",
tools=[math_agent.as_tool(), research_agent.as_tool()],
)
result = await coordinator.process("What is 15 * 23, and who invented calculus?")
MCP Integration
Connect to MCP servers for external tool access:
from opper_agents import mcp, MCPServerConfig
filesystem_server = MCPServerConfig(
name="filesystem",
transport="stdio",
command="npx",
args=["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
)
agent = Agent(
name="FileAgent",
instructions="Use filesystem tools to manage files.",
tools=[mcp(filesystem_server)],
)
Hooks
Monitor agent lifecycle events:
from opper_agents import hook
from opper_agents.base.context import AgentContext
@hook("agent_start")
async def on_start(context: AgentContext, agent):
print(f"Agent {agent.name} starting: {context.goal}")
@hook("tool_result")
async def on_tool(context: AgentContext, tool_name: str, result):
print(f"Tool {tool_name} returned: {result}")
agent = Agent(
name="ObservedAgent",
instructions="Do the task.",
tools=[my_tool],
hooks=[on_start, on_tool],
)
Execution Stats
Access usage information after running:
result = await agent.process("Solve this problem")
# Access stats from the agent context
print(f"Iterations: {agent.context.iteration}")
print(f"Total tokens: {agent.context.usage.total_tokens}")
Common Mistakes
- Forgetting
await:agent.process()is async. Always useawait. - Missing tool docstrings: The agent uses docstrings to understand what tools do. Always provide descriptive docstrings.
- Too many tools: Agents work best with 5-10 focused tools. Use multi-agent composition for more.
- No
output_schema: Without it, results are unstructured strings. Use Pydantic models for reliable parsing. - Infinite loops: Set
max_iterationsto prevent runaway agents.
Additional Resources
- For advanced tool patterns and context, see references/TOOLS.md
- For MCP server configuration, see references/MCP.md
- For multi-agent composition patterns, see references/COMPOSITION.md
- For lifecycle hooks reference, see references/HOOKS.md
- For persistent memory, see references/MEMORY.md
- For migrating from OpenRouter, see references/MIGRATION.md
Related Skills
- opper-python-sdk: Use for single-shot task completion without agent loops — simpler when you don't need multi-step reasoning.
- opper-node-agents: Use when building agents in TypeScript instead of Python.
Upstream Sources
When this skill's content may be outdated, resolve using this priority:
- Installed package source — check the user's project first, as it reflects the exact version in use:
.venv/**/site-packages/opper_agents/or**/site-packages/opper_agents/ - Source code: https://github.com/opper-ai/opperai-agent-sdk
- Documentation: https://docs.opper.ai
Weekly Installs
5
Repository
opper-ai/opper-skillsGitHub Stars
1
First Seen
Feb 2, 2026
Security Audits
Installed on
codex5
opencode5
pi4
claude-code4
gemini-cli3
antigravity3