Python agent loop
Project description
TinyAgent
A small, modular agent framework for building LLM-powered applications in Python.
Inspired by smolagents and Pi — borrowing the minimal-abstraction philosophy from the former and the conversational agent loop from the latter.
Beta — TinyAgent is usable but not production-ready. APIs may change between minor versions.
Note: The optional
tinyagent._alchemybinding now lives inhttps://github.com/tunahorse/tinyagent-alchemyand is not built from this repo.
Overview
TinyAgent provides a lightweight foundation for creating conversational AI agents with tool use capabilities. It features:
- Streaming-first architecture: All LLM interactions support streaming responses
- Tool execution: Define and execute tools with structured outputs
- Event-driven: Subscribe to agent events for real-time UI updates
- Provider agnostic: Works with any OpenAI-compatible
/chat/completionsendpoint (OpenRouter, OpenAI, Chutes, local servers) - Prompt caching: Reduce token costs and latency with Anthropic-style cache breakpoints
- Provider paths: Optional external alchemy binding adapter plus proxy integration
- Type-safe: Full type hints throughout
Quick Start
This example uses the optional tinyagent._alchemy binding via
tinyagent.alchemy_provider. Install that binding from the external repo first,
or use the proxy path instead.
import asyncio
from tinyagent import Agent, AgentOptions
from tinyagent.alchemy_provider import OpenAICompatModel, stream_alchemy_openai_completions
# Create an agent
agent = Agent(
AgentOptions(
stream_fn=stream_alchemy_openai_completions,
session_id="my-session"
)
)
# Configure
agent.set_system_prompt("You are a helpful assistant.")
agent.set_model(
OpenAICompatModel(
provider="openrouter",
id="anthropic/claude-3.5-sonnet",
base_url="https://openrouter.ai/api/v1/chat/completions",
)
)
# Optional: any OpenAI-compatible /chat/completions endpoint
# agent.set_model(OpenAICompatModel(provider="openai", id="gpt-4o-mini", base_url="https://api.openai.com/v1/chat/completions"))
# Simple prompt
async def main():
response = await agent.prompt_text("What is the capital of France?")
print(response)
asyncio.run(main())
Installation
pip install tiny-agent-os
Optional binding:
- PyPI wheels may include the compiled
tinyagent._alchemyextension for supported platforms, but the source distribution does not. - Install/build
tinyagent._alchemyfromhttps://github.com/tunahorse/tinyagent-alchemyif you wantstream_alchemy_openai_completionsand no matching wheel is available. - Otherwise, use the proxy path in
tinyagent.proxy.
Core Concepts
Agent
The Agent class is the main entry point. It manages:
- Conversation state (messages, tools, system prompt)
- Streaming responses
- Tool execution
- Event subscription
Messages
Messages are Pydantic models (use attribute access):
UserMessage: Input from the userAssistantMessage: Response from the LLMToolResultMessage: Result from tool execution
Tools
Tools are functions the LLM can call:
from tinyagent import AgentTool, AgentToolResult, TextContent
async def calculate_sum(tool_call_id: str, args: dict, signal, on_update) -> AgentToolResult:
result = args["a"] + args["b"]
return AgentToolResult(
content=[TextContent(text=str(result))]
)
tool = AgentTool(
name="sum",
description="Add two numbers",
parameters={
"type": "object",
"properties": {
"a": {"type": "number"},
"b": {"type": "number"}
},
"required": ["a", "b"]
},
execute=calculate_sum
)
agent.set_tools([tool])
Events
The agent emits events during execution:
AgentStartEvent/AgentEndEvent: Agent run lifecycleTurnStartEvent/TurnEndEvent: Single turn lifecycleMessageStartEvent/MessageUpdateEvent/MessageEndEvent: Message streamingToolExecutionStartEvent/ToolExecutionUpdateEvent/ToolExecutionEndEvent: Tool execution
Subscribe to events:
def on_event(event):
print(f"Event: {event.type}")
unsubscribe = agent.subscribe(on_event)
Prompt Caching
TinyAgent supports Anthropic-style prompt caching to reduce costs on multi-turn conversations. Enable it when creating the agent:
agent = Agent(
AgentOptions(
stream_fn=stream_alchemy_openai_completions,
session_id="my-session",
enable_prompt_caching=True,
)
)
Cache breakpoints are automatically placed on user message content blocks so the prompt prefix stays cached across turns. See Prompt Caching for details.
Optional Binding: tinyagent._alchemy
This repo keeps tinyagent/alchemy_provider.py as a compatibility adapter for the
optional external tinyagent._alchemy extension. The binding source, build
instructions, and low-level binding API now live in:
https://github.com/tunahorse/tinyagent-alchemy
The compiled path is still useful when you want OpenAI-compatible streaming without routing through a separate proxy, but it is no longer bundled or built from this repository.
Using via TinyAgent
You don't need to call the Rust binding directly. Use the alchemy_provider module:
from tinyagent import Agent, AgentOptions
from tinyagent.alchemy_provider import OpenAICompatModel, stream_alchemy_openai_completions
agent = Agent(
AgentOptions(
stream_fn=stream_alchemy_openai_completions,
session_id="my-session",
)
)
agent.set_model(
OpenAICompatModel(
provider="openrouter",
id="anthropic/claude-3.5-sonnet",
base_url="https://openrouter.ai/api/v1/chat/completions",
)
)
MiniMax global:
agent.set_model(
OpenAICompatModel(
provider="minimax",
id="MiniMax-M2.5",
base_url="https://api.minimax.io/v1/chat/completions",
# api is optional here; inferred as "minimax-completions"
)
)
MiniMax CN:
agent.set_model(
OpenAICompatModel(
provider="minimax-cn",
id="MiniMax-M2.5",
base_url="https://api.minimax.chat/v1/chat/completions",
# api is optional here; inferred as "minimax-completions"
)
)
Smoke validation after installing the external binding:
uv run python scripts/smoke_rust_tool_calls_three_providers.py
Limitations
- The optional binding currently dispatches only
openai-completionsandminimax-completions. - Image blocks are not yet supported (text and thinking blocks work).
next_event()is blocking and runs in a thread viaasyncio.to_thread-- this adds slight overhead compared to a native async generator, but keeps the GIL released during the native work.
Documentation
- Architecture: System design and component interactions
- API Reference: Detailed module documentation
- Prompt Caching: Cache breakpoints, cost savings, and provider requirements
- OpenAI-Compatible Endpoints: Using
OpenAICompatModel.base_urlwith OpenRouter/OpenAI/Chutes-compatible backends - Usage Semantics: Canonical
usageschema across provider flows - Harness Rules: ast-grep rules for the live tool-call harness
- Changelog: Release history
- Shipping the alchemy binding: Release workflow for wheels that include
tinyagent._alchemy
Project Structure
tinyagent/
├── agent.py # Agent class
├── agent_loop.py # Core agent execution loop
├── agent_tool_execution.py # Tool execution helpers
├── agent_types.py # Type definitions
├── caching.py # Prompt caching utilities
├── alchemy_provider.py # Adapter for the optional external binding
├── proxy.py # Proxy server integration
└── proxy_event_handlers.py # Proxy event parsing
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tiny_agent_os-1.2.25-cp310-abi3-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: tiny_agent_os-1.2.25-cp310-abi3-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 2.5 MB
- Tags: CPython 3.10+, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
57b07f6f83aee9083e56514603abe045858de3b60ad5bda194f1c1726cc258c8
|
|
| MD5 |
465fc0056b604ed285fd1f40806ca0cf
|
|
| BLAKE2b-256 |
b333478e3074e88ced01fb4caccba456ce5103d95596ca487cf6232ee4d21047
|
File details
Details for the file tiny_agent_os-1.2.25-cp310-abi3-macosx_11_0_universal2.whl.
File metadata
- Download URL: tiny_agent_os-1.2.25-cp310-abi3-macosx_11_0_universal2.whl
- Upload date:
- Size: 2.1 MB
- Tags: CPython 3.10+, macOS 11.0+ universal2 (ARM64, x86-64)
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9e0d27e06e00d4d749b7ebc39c326df1703b93b9845f14be44e070b6fa716cf2
|
|
| MD5 |
e4cc67a8c19fedf1a9e5f5ccf726545a
|
|
| BLAKE2b-256 |
4becf9dcd77eeb122c49e8b4e4a167e16633c292d6b4c1f8b98c214770684dd4
|