Skip to main content

Minimal, streaming-first, protocol-driven foundation for LLM-powered agents

Project description

axio

PyPI Python License: MIT

Minimal, streaming-first, protocol-driven foundation for LLM-powered agents.

One dependency (pydantic). Three protocols. An agent loop that just works.

Features

  • Streaming agent looprun_stream() yields typed events as they arrive; no buffering, no polling
  • Three clean protocolsCompletionTransport, ContextStore, PermissionGuard; swap any piece without touching the rest
  • Concurrent tool dispatch — all tool calls in a turn run via asyncio.gather automatically
  • Context compactioncompact_context() summarises old history to stay within token limits
  • Testing helpersStubTransport, make_tool_use_response(), make_echo_tool() ship in axio.testing
  • Plugin-ready — entry-point groups (axio.tools, axio.transport, axio.guards) for drop-in extensions

Installation

pip install axio

Quick start

import asyncio
from axio import Agent
from axio.context import MemoryContextStore
from axio.tool import Tool, ToolHandler

# 1. Define a tool
class Greet(ToolHandler):
    """Return a greeting for the given name."""
    name: str

    async def __call__(self) -> str:
        return f"Hello, {self.name}!"

greet_tool = Tool(name="greet", description="Greet someone by name", handler=Greet)

# 2. Wire up the agent (transport comes from an axio-transport-* package)
from axio_transport_openai import OpenAITransport

transport = OpenAITransport(api_key="sk-...", model="gpt-4o-mini")
agent = Agent(system="You are helpful.", tools=[greet_tool], transport=transport)

# 3. Run
async def main() -> None:
    ctx = MemoryContextStore()
    async for event in agent.run_stream("Please greet Alice", ctx):
        print(event)

asyncio.run(main())

Architecture

  User message
       │
       ▼
  ┌─────────┐   stream()    ┌─────────────────────┐
  │  Agent  │ ────────────▶ │ CompletionTransport  │
  │  loop   │ ◀──────────── │ (Anthropic, OpenAI, …) │
  └─────────┘  StreamEvent  └─────────────────────┘
       │
       │ tool_use?
       ▼
  ┌──────────┐   check()   ┌─────────────────┐
  │   Tool   │ ──────────▶ │ PermissionGuard │
  │ handler  │             │ (path, LLM, …)  │
  └──────────┘             └─────────────────┘
       │
       ▼
  ┌──────────────┐
  │ ContextStore │  append() / get_history() / fork() / compact()
  └──────────────┘

Protocols

CompletionTransport

from typing import Protocol, runtime_checkable
from collections.abc import AsyncIterator
from axio.events import StreamEvent
from axio.messages import Message
from axio.tool import Tool

@runtime_checkable
class CompletionTransport(Protocol):
    def stream(
        self, messages: list[Message], tools: list[Tool], system: str
    ) -> AsyncIterator[StreamEvent]: ...

ContextStore

class ContextStore(ABC):
    async def append(self, message: Message) -> None: ...
    async def get_history(self) -> list[Message]: ...
    async def fork(self) -> ContextStore: ...   # branch conversation
    async def clear(self) -> None: ...
    async def close(self) -> None: ...

PermissionGuard

@runtime_checkable
class PermissionGuard(Protocol):
    async def check(self, handler: ToolHandler) -> ToolHandler: ...

Stream events

Event Description
TextDelta Incremental assistant text chunk
ToolUseStart Tool call begins (name + id)
ToolInputDelta Streaming JSON fragment for tool arguments
ToolResult Tool execution result
IterationEnd One LLM round complete — carries Usage + StopReason
Error Transport or tool exception
SessionEndEvent Agent loop finished — carries total Usage

Tools

from axio.tool import Tool, ToolHandler

class Summarise(ToolHandler):
    """Summarise the given text in one sentence."""
    text: str
    max_words: int = 20

    async def __call__(self) -> str:
        # your implementation
        return "..."

tool = Tool(
    name="summarise",
    description="Summarise text",   # overrides docstring if set
    handler=Summarise,
    concurrency=4,                   # max parallel executions
)

Testing

from axio.testing import (
    StubTransport,
    make_tool_use_response,
    make_text_response,
    make_ephemeral_context,
    make_echo_tool,
)

async def test_agent_calls_tool():
    transport = StubTransport([
        make_tool_use_response("echo", tool_input={"msg": "hi"}),
        make_text_response("Done"),
    ])
    agent = Agent(system="", tools=[make_echo_tool()], transport=transport)
    result = await agent.run("say hi", make_ephemeral_context())
    assert result == "Done"

Plugin entry points

[project.entry-points."axio.tools"]
my_tool = "my_package:MyHandler"

[project.entry-points."axio.transport"]
my_backend = "my_package:MyTransport"

[project.entry-points."axio.guards"]
my_guard = "my_package:MyGuard"

Ecosystem

Package Purpose
axio-transport-anthropic Anthropic Claude transport
axio-transport-openai OpenAI-compatible transport
axio-transport-nebius Nebius AI Studio transport
axio-transport-codex ChatGPT OAuth transport
axio-tools-local Shell, file, Python tools
axio-tools-mcp MCP server bridge
axio-tools-docker Docker sandbox tools
axio-tui Textual TUI application
axio-tui-rag RAG / semantic search plugin
axio-tui-guards Permission guard plugins

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

axio-0.4.0.tar.gz (59.5 kB view details)

Uploaded Source

Built Distribution

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

axio-0.4.0-py3-none-any.whl (20.1 kB view details)

Uploaded Python 3

File details

Details for the file axio-0.4.0.tar.gz.

File metadata

  • Download URL: axio-0.4.0.tar.gz
  • Upload date:
  • Size: 59.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for axio-0.4.0.tar.gz
Algorithm Hash digest
SHA256 f2e61e8b198f9b9db906a9631486abadd2c468a4459b91a734430a2f2b39d32f
MD5 d112c0e21accee8235745abbb96c45b6
BLAKE2b-256 3f08c3e8693ae1850d620b170ff4fe2c4c4104e935f300c376ead920fde0ecbf

See more details on using hashes here.

Provenance

The following attestation bundles were made for axio-0.4.0.tar.gz:

Publisher: publish.yml on axio-agent/monorepo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file axio-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: axio-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 20.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for axio-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6d274f85f102e8301d77cf1875601c8aca18ba1a1bbe58081423cc5b4e216778
MD5 bd129fe27765e3373bc00a64666f393d
BLAKE2b-256 7126ab1799c36ca73fd51ea06bcf588fa84acd592394a51964381c1ee0336b62

See more details on using hashes here.

Provenance

The following attestation bundles were made for axio-0.4.0-py3-none-any.whl:

Publisher: publish.yml on axio-agent/monorepo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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