Flux
A Python-first Agentic AI Framework
Provider-agnostic · Async-first · Middleware-driven · Zero core dependencies
Quick Start
import asyncio
from flux import Agent, Runner
# 3 lines to get started
agent = Agent(name="assistant", instructions="You are helpful")
result = asyncio.run(Runner.run(agent, "Hello!"))
print(result.final_output)
Features
- Provider Agnostic — Ollama, OpenAI, Anthropic, Groq, DeepSeek, OpenRouter
- Async First — Non-blocking by default, sync wrappers available
- Protocol Based — Structural typing, no inheritance required
- Middleware — Composable middleware stack (logging, caching, retry, rate-limiting)
- Event Driven — Decoupled event bus for observability
- Tools —
@tooldecorator, tool registry, built-in tools - Handoffs — Agent-to-agent routing
- Guardrails — Input/output validation
- Sessions — Conversation persistence (in-memory, SQLite)
- Memory — Short-term and long-term memory
- Streaming — Real-time token streaming
- Tracing — Console and file-based tracing
Installation
# Core framework (zero dependencies)
pip install flux-agents
# With providers
pip install flux-agents[ollama] # Ollama
pip install flux-agents[openai] # OpenAI
pip install flux-agents[anthropic] # Anthropic
pip install flux-agents[full] # All providers
Usage
Basic Agent
from flux import Agent, Runner
agent = Agent(
name="assistant",
instructions="You are a helpful assistant",
model="ollama/llama3.2",
)
result = Runner.run_sync(agent, "What is the capital of France?")
print(result.final_output)
With Tools
from flux import Agent, Runner, tool
@tool
def get_weather(city: str) -> str:
"""Get weather for a city."""
return f"Sunny in {city}"
agent = Agent(
name="weather_bot",
instructions="You help with weather queries",
tools=[get_weather],
)
result = Runner.run_sync(agent, "What's the weather in NYC?")
print(result.final_output)
With Handoffs
from flux import Agent, Runner
router = Agent(
name="router",
instructions="Route to the right specialist",
handoffs=[
Agent(name="coder", instructions="You write code"),
Agent(name="writer", instructions="You write content"),
],
)
result = Runner.run_sync(router, "Write a Python function to sort a list")
print(result.final_output)
Streaming
import asyncio
from flux import Agent, Runner
async def main():
agent = Agent(name="assistant", instructions="You are helpful")
stream = await Runner.run_streamed(agent, "Tell me a story")
async for event in stream:
if hasattr(event, "delta"):
print(event.delta, end="", flush=True)
asyncio.run(main())
With Guardrails
from flux import Agent, Runner, LengthGuardrail, PIIGuardrail
agent = Agent(
name="safe_assistant",
instructions="You are helpful",
guardrails=[
LengthGuardrail(max_chars=5000),
PIIGuardrail(),
],
)
With Middleware
from flux import Agent, Runner, LoggingMiddleware, RetryMiddleware
# Middleware wraps every request
runner = Runner(middlewares=[
LoggingMiddleware(),
RetryMiddleware(max_retries=3),
])
With Sessions
from flux import Agent, Runner, InMemorySession
session = InMemorySession()
agent = Agent(name="assistant", instructions="You remember our conversation")
# First turn
result1 = Runner.run_sync(agent, "My name is Alice", session=session)
# Second turn — agent remembers context
result2 = Runner.run_sync(agent, "What's my name?", session=session)
print(result2.final_output) # "Your name is Alice"
Custom Model
from flux import Agent, Runner
from flux.models.ollama import OllamaModel
model = OllamaModel(model="llama3.2", base_url="http://localhost:11434")
agent = Agent(name="local", instructions="You run locally", model=model)
result = Runner.run_sync(agent, "Hello!")
Custom Provider
from flux.models.base import Model, ModelRequest, ModelResponse
class MyCustomModel:
async def complete(self, request: ModelRequest) -> ModelResponse:
# Your custom implementation
return ModelResponse(content="Hello from custom model!")
async def stream(self, request: ModelRequest):
yield # Your streaming implementation
agent = Agent(name="custom", instructions="Custom model", model=MyCustomModel())
Architecture
flux/
├── agent.py # Agent (immutable dataclass)
├── runner.py # Runner (execution engine)
├── context.py # RunContext, ToolContext
├── config.py # Global configuration
├── exceptions.py # Exception hierarchy
├── models/ # LLM providers (Ollama, OpenAI, Anthropic)
├── tools/ # Tool protocol, @tool decorator, registry
├── handoffs/ # Agent-to-agent routing
├── guardrails/ # Input/output validation
├── sessions/ # Conversation persistence
├── memory/ # Long-term memory
├── streaming/ # Stream event types
├── middleware/ # Composable middleware
├── events/ # Event bus
├── tracing/ # Observability
└── utils/ # JSON schema, tokens, pretty print
Design Principles
- Protocol over ABC — Structural typing, no inheritance required
- Async first — Non-blocking by default
- Zero core deps — Base framework needs no third-party packages
- Middleware over hooks — Composable, testable, standard pattern
- Immutable agents — Thread-safe, cloneable
- Event-driven — Decoupled observability
License
MIT
Metadata
Release files for flux-agents 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| flux_agents-0.2.0.tar.gz | 44.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| flux_agents-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 88.6 kB
Release files / flux_agents-0.2.0.tar.gz
| Download URL | flux_agents-0.2.0.tar.gz |
|---|---|
| Size | 44.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f3ec56cb83c393f849e91eebe7651c9839230a7246c5ce074dcb25edbde790f1
|
|
BLAKE2b-256 checksum How to use checksums |
c1b6155039d103ac44a135e7c4cdf19ad1d922f9b688a3111ee78237441e2ed1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.10
|
Release files / flux_agents-0.2.0-py3-none-any.whl
| Download URL | flux_agents-0.2.0-py3-none-any.whl |
|---|---|
| Size | 44.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
df3867b08e2f6b03e5888855a9caf73ce80102c1040685d82bfd0f0e31383f35
|
|
BLAKE2b-256 checksum How to use checksums |
bcaf4b409e81d18c537096aa8737621a7fc5986855f5e4f4a8ccbd88022bff92
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.10
|