Skip to main content

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 — @tool decorator, 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

  1. Protocol over ABC — Structural typing, no inheritance required
  2. Async first — Non-blocking by default
  3. Zero core deps — Base framework needs no third-party packages
  4. Middleware over hooks — Composable, testable, standard pattern
  5. Immutable agents — Thread-safe, cloneable
  6. 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)

Source distribution for flux-agents 0.2.0
File Size Uploaded
flux_agents-0.2.0.tar.gz 44.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for flux-agents 0.2.0
File Interpreter ABI Platform
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

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.3

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page