Skip to main content

A Python-first Agentic AI Framework — provider-agnostic, async-first, middleware-driven

Project description

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

flux_agents-0.1.3.tar.gz (44.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

flux_agents-0.1.3-py3-none-any.whl (44.6 kB view details)

Uploaded Python 3

File details

Details for the file flux_agents-0.1.3.tar.gz.

File metadata

  • Download URL: flux_agents-0.1.3.tar.gz
  • Upload date:
  • Size: 44.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for flux_agents-0.1.3.tar.gz
Algorithm Hash digest
SHA256 01e04fe374eafd66d1b91cfa62de15718078dc9e8a4f2215d04e4f80440c46b8
MD5 98ab48dc885ea4ca7da088b7fa46c82b
BLAKE2b-256 d9fd6aaeb2c852eb4564c9c175f2bf43687313964785d70253a0eca7457d6d5e

See more details on using hashes here.

File details

Details for the file flux_agents-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: flux_agents-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 44.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for flux_agents-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 f8c3bf34b5e350d14b8d6672b04cd33ceb2465f706d05107613bc0315e189bd9
MD5 07bbc2b30fcadd094a8bffa9640fe6db
BLAKE2b-256 85c2398e699ab4f4ae87e8955fb5384b9bb3924fe4ab78e7e887ed8e87835977

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page