skills/opper-ai/opper-skills/opper-python-agents

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:

  1. Think: The LLM analyzes the goal and available tools
  2. Act: It selects and executes a tool
  3. Observe: Results are added to the conversation history
  4. 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 use await.
  • 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_iterations to prevent runaway agents.

Additional Resources

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:

  1. 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/
  2. Source code: https://github.com/opper-ai/opperai-agent-sdk
  3. Documentation: https://docs.opper.ai
Weekly Installs
5
GitHub Stars
1
First Seen
Feb 2, 2026
Installed on
codex5
opencode5
pi4
claude-code4
gemini-cli3
antigravity3