Skip to main content

Python Bindings

AutoAgents provides Python bindings built with PyO3 and maturin. The bindings are split into multiple packages so users install only what they need:

PackageExtra keyWhat it provides
autoagents-py(base)Core API — cloud LLM providers (OpenAI, Anthropic, …)
autoagents-guardrails-pyguardrailsGuardrails for wrapping Python LLMProvider instances
autoagents-llamacpp-pyllamacppLocal llama.cpp CPU backend
autoagents-llamacpp-cudallamacpp-cudallama.cpp with CUDA acceleration
autoagents-llamacpp-metalllamacpp-metalllama.cpp with Metal acceleration (macOS)
autoagents-llamacpp-vulkanllamacpp-vulkanllama.cpp with Vulkan acceleration
autoagents-mistral-rs-pymistralrsLocal mistral-rs CPU backend
autoagents-mistral-rs-cudamistralrs-cudamistral-rs with CUDA acceleration
autoagents-mistral-rs-metalmistralrs-metalmistral-rs with Metal acceleration (macOS)

Release wheels for all platforms are published to PyPI by CI on every version tag. For local development and testing, use the repository Makefile targets below.


Installation from PyPI

Install the base package for cloud LLM providers (OpenAI, Anthropic, etc.):

pip install autoagents-py

Install with a local backend using extras:

# llama.cpp
pip install "autoagents-py[llamacpp]" # CPU
pip install "autoagents-py[llamacpp-cuda]" # CUDA (Linux/Windows, requires CUDA Toolkit 12.x)
pip install "autoagents-py[llamacpp-metal]" # Metal (macOS only)
pip install "autoagents-py[llamacpp-vulkan]" # Vulkan

# mistral-rs
pip install "autoagents-py[mistralrs]" # CPU
pip install "autoagents-py[mistralrs-cuda]" # CUDA (Linux/Windows, requires CUDA Toolkit 12.x)
pip install "autoagents-py[mistralrs-metal]" # Metal (macOS only)

# Guardrails
pip install "autoagents-py[guardrails]"

# Combine extras
pip install "autoagents-py[llamacpp-cuda,guardrails]"

Note: CUDA wheels are tagged linux_x86_64 (not manylinux) because they link against CUDA system libraries. They are intended for controlled environments where the CUDA Toolkit is already installed.


Architecture Contract

The stable Python API is intentionally narrow:

  • Rust owns runtime, scheduling, streaming, concurrency, event transport, agent execution, and production memory behavior.
  • Python owns agent specs, prompt/orchestration logic, hooks, and tool implementations.
  • Python tools are first-class in the stable path.

Use the stable package surface for production:

  • BasicAgent
  • CodeActAgent
  • ReActAgent
  • SlidingWindowMemory
  • AgentBuilder
  • Agent / AgentHandle
  • runtime and event APIs

Extension paths are opt-in under autoagents.experimental:

  • ExperimentalAgentBuilder
  • CustomExecutor
  • Python-backed memory adapters

Those APIs are experimental in the Python bindings because they introduce Python-native execution or Python-native memory behavior. The project keeps those paths out of the stable Python surface so Rust remains the production owner of runtime, scheduling, concurrency, streaming, and memory lifecycle.

That does not mean the capability itself is immature. The equivalent Rust-native implementations are the production-grade path. The experimental label applies to the Python extension mechanism, not to the Rust architecture.

Python tool execution semantics

  • Rust owns tool dispatch and lifecycle.
  • Sync Python tools run on Tokio's blocking pool.
  • Async Python tools run through the shared PyO3 async bridge on the single shared Tokio runtime.
  • Tool arguments are validated against the declared JSON schema before the Python callable is invoked.

Prerequisites

ToolMinimum versionInstall
Python3.9python.org
Ruststablecurl https://sh.rustup.rs -sSf | sh
uvlatestcurl -LsSf https://astral.sh/uv/install.sh | sh
maturin1.5uv pip install maturin
pytest + pytest-asyncio + pytest-covlatestuv pip install pytest pytest-asyncio pytest-cov

Local Development Build (Linux)

The recommended local workflow is the repository Makefile. It runs maturin develop, installs the editable packages into the active virtual environment, and cleans stale editable-install artifacts before every build so local imports always resolve to freshly compiled extensions:

# From the repository root
uv venv --python=3.12
source .venv/bin/activate # Windows: .venv\Scripts\activate
uv pip install -U pip maturin pytest pytest-asyncio pytest-cov

# Build and install: base + llamacpp CPU + mistralrs CPU
make python-bindings-build

# Also build CUDA variants (requires CUDA Toolkit 12.x on PATH)
make python-bindings-build-cuda

# Other local variants
make python-bindings-build-metal
make python-bindings-build-vulkan

Manual per-package build

Use this only if you need low-level control over one package. The make targets above are the supported day-to-day development workflow.

# 1. Base package (required first)
cd bindings/python/autoagents
uv pip install -U pip maturin pytest pytest-asyncio pytest-cov
maturin develop --release

# 2. llama.cpp CPU backend (optional)
cd bindings/python/autoagents-llamacpp
maturin develop --release

# 3. guardrails package (optional)
cd bindings/python/autoagents-guardrails
maturin develop --release

# 4. mistral-rs CPU backend (optional)
cd bindings/python/autoagents-mistralrs
maturin develop --release

Verify the install

python -c "import autoagents_py; print('OK')"

Running Tests Locally

Tests live in bindings/python/autoagents/tests/.

FileRequires API keyWhat it tests
test_unit.pyNoSchema inference, @tool decorator, builder/output schema wiring, error types, Topic

Unit tests — no API key needed

Run from anywhere after make python-bindings-build:

PYTHONPATH=bindings/python/autoagents \
pytest bindings/python/autoagents/tests/test_unit.py -v

Unit tests cover schema inference (Optional, List, Dict, Literal, Enum, dataclass, Pydantic), structured output schema registration, and exception hierarchy. All pass with no keys set.

Protocol Events

Every agent run emits typed protocol events. Access them via the event stream or from the run() result:

import asyncio
from autoagents_py import (
Agent,
LLMBuilder,
ToolCallCompleted,
ToolCallRequested,
TurnStarted,
tool,
)
from autoagents_py.prebuilt import BasicAgent, SlidingWindowMemory

@tool(description="Add two numbers")
def add(a: float, b: float) -> float:
return a + b

async def main():
llm = LLMBuilder("openai").api_key("sk-...").model("gpt-4o-mini").build()
executor = BasicAgent("calc", "Calculator").tools([add])
agent = Agent(executor, llm=llm, memory=SlidingWindowMemory(window_size=20))

# Option A: get events from run() result
result = await agent.run("What is 2 + 3?")
for event in result.get("events", []):
if isinstance(event, TurnStarted):
print(f"Turn {event.turn_number}/{event.max_turns}")
elif isinstance(event, ToolCallRequested):
print(f"Calling {event.tool_name}({event.arguments})")
elif isinstance(event, ToolCallCompleted):
print(f"Result: {event.result}")

# Option B: async event stream (concurrent with run)
async for event in agent.events():
print(event)

asyncio.run(main())

Available event types (all importable from autoagents):

ClassKey attributes
NewTaskactor_id, prompt, system_prompt
TaskStartedsub_id, actor_id, actor_name, task_description
TaskCompletesub_id, actor_id, actor_name, result
TaskErrorsub_id, actor_id, error
SendMessageactor_id, message
ToolCallRequestedsub_id, actor_id, id, tool_name, arguments
ToolCallCompletedsub_id, actor_id, id, tool_name, result
ToolCallFailedsub_id, actor_id, id, tool_name, error
TurnStartedsub_id, actor_id, turn_number, max_turns
TurnCompletedsub_id, actor_id, turn_number, final_turn
CodeExecutionStartedsub_id, actor_id, execution_id, language, source
CodeExecutionConsolesub_id, actor_id, execution_id, message
CodeExecutionCompletedsub_id, actor_id, execution_id, result, duration_ms
CodeExecutionFailedsub_id, actor_id, execution_id, error, duration_ms
StreamChunksub_id, chunk
StreamToolCallsub_id, tool_call
StreamCompletesub_id

Examples

# Cloud provider (requires OPENAI_API_KEY)
OPENAI_API_KEY=sk-... python bindings/python/autoagents/examples/openai_agent.py
OPENAI_API_KEY=sk-... python bindings/python/autoagents/examples/code_mode.py
OPENAI_API_KEY=sk-... python bindings/python/autoagents/examples/actor_agent.py
OPENAI_API_KEY=sk-... python bindings/python/autoagents/examples/protocol_event_streaming.py
OPENAI_API_KEY=sk-... python bindings/python/autoagents/examples/custom_pipeline_layer.py
OPENAI_API_KEY=sk-... python bindings/python/autoagents-guardrails/examples/pipeline_guardrails.py

# llama.cpp (requires `make python-bindings-build`)
python bindings/python/autoagents-llamacpp/examples/llamacpp_agent.py

# mistral-rs (requires `make python-bindings-build`)
python bindings/python/autoagents-mistralrs/examples/mistral_rs_agent.py

# CUDA variants (requires `make python-bindings-build-cuda`)
python bindings/python/autoagents-llamacpp-cuda/examples/llamacpp_cuda_agent.py
python bindings/python/autoagents-mistralrs-cuda/examples/mistral_rs_cuda_agent.py

Experimental extension examples:

OPENAI_API_KEY=sk-... python bindings/python/autoagents/examples/custom_executor.py
OPENAI_API_KEY=sk-... python bindings/python/autoagents/examples/custom_memory.py

The actor example mirrors the Rust runtime model: create a Runtime, register it with an Environment, build the actor against the runtime, listen on the environment event stream, then publish a Task to the topic.

The CodeAct example mirrors the Rust examples/code_mode sample: it exposes typed Python tools to the LLM, lets the model write sandboxed TypeScript, and prints the captured execution trace after the run.


Troubleshooting

ImportError: No module named 'autoagents' The Rust extension has not been compiled yet. Run make python-bindings-build from the repository root.

maturin develop fails with linker errors on Linux Install build essentials: sudo apt install build-essential pkg-config

CUDA build fails: nvcc: command not found CUDA Toolkit is not on PATH. Source the CUDA environment or add /usr/local/cuda/bin to PATH.

block_in_place panic on import / register_runtime Ensure you are using the bindings built from the current source. Older builds may not include the fix. Rebuild with make python-bindings-build; the target cleans stale editable-install binaries before compiling.