Unified LLM provider abstraction and agent framework for Python
pi-python is a Python port of the LLM and agent packages from pi-mono by Mario Zechner. It provides a clean, typed interface for building LLM-powered applications with streaming, tool calling, and autonomous agents.
| Package | Description | Install |
|---|---|---|
| pi-llm | Typed streaming interface for LLM calls — tool calling, extended thinking, cost tracking | pip install pi-llm |
| pi-llm-agent | Stateful agent framework — multi-turn tool execution, hooks, event streaming | pip install pi-llm-agent |
pip install pi-llm pi-llm-agent
export OPENAI_API_KEY=sk-...import asyncio
from pi_llm import get_model, complete_simple, Context, UserMessage
from pi_llm.providers import register_builtin_providers
register_builtin_providers()
async def main():
model = get_model("openai", "gpt-4o")
context = Context(
system_prompt="You are a helpful assistant.",
messages=[UserMessage(content="Hello!", timestamp=0)],
)
message = await complete_simple(model, context)
print(message.content[0].text)
asyncio.run(main())import asyncio
from pi_llm_agent import Agent, AgentOptions, InitialAgentState, AgentTool, AgentToolResult
from pi_llm import get_model, TextContent, stream_simple
from pi_llm.providers import register_builtin_providers
register_builtin_providers()
class GreetTool(AgentTool):
def __init__(self):
super().__init__(
name="greet", label="Greet",
description="Greet someone by name",
parameters={
"type": "object",
"properties": {"name": {"type": "string"}},
"required": ["name"],
},
)
async def execute(self, tool_call_id, params, cancellation=None, on_update=None):
return AgentToolResult(content=[TextContent(text=f"Hello, {params['name']}!")])
async def main():
agent = Agent(AgentOptions(
initial_state=InitialAgentState(
model=get_model("openai", "gpt-4o"),
system_prompt="You have a greet tool. Use it when asked to greet someone.",
tools=[GreetTool()],
),
stream_fn=stream_simple,
get_api_key=lambda _: None,
))
def on_event(event, cancellation):
if event.type == "message_update" and hasattr(event.assistant_message_event, "delta"):
print(event.assistant_message_event.delta, end="", flush=True)
elif event.type == "tool_execution_start":
print(f"\n [calling {event.tool_name}]")
elif event.type == "agent_end":
print()
agent.subscribe(on_event)
await agent.prompt("Please greet Alice and Bob")
asyncio.run(main())Most Python LLM libraries either lock you into one provider or bury you in abstraction layers. pi-python gives you:
- Typed streaming events — 12 event types you can
async forover, not string parsing - Real tool execution — JSON Schema validation, before/after hooks, sequential or parallel
- Agent state you control — inspect messages, pending tool calls, and streaming state at any point
- Extended thinking — 5 reasoning levels from
minimaltoxhigh - Cost awareness — token usage and dollar cost tracking for 42 OpenAI models
flowchart LR
A[User Prompt] --> B[Agent]
B --> C[LLM Call<br/>stream_simple]
C --> D{Tool calls?}
D -- Yes --> E[Execute Tools]
E --> F[Tool Results]
F --> C
D -- No --> G[Final Response]
style B fill:#4f46e5,color:#fff
style C fill:#0891b2,color:#fff
style E fill:#059669,color:#fff
pi-llm handles the LLM call (streaming events, tool validation, cost tracking). pi-llm-agent manages the loop — calling the LLM, executing tools, and repeating until done.
|
|
Full documentation at yuramalna.github.io/pi-python
| Getting Started | Install, first LLM call, first agent |
| pi-llm Concepts | Streaming, events, tools, thinking, cost tracking |
| pi-llm-agent Concepts | Agent lifecycle, loop, hooks, steering, cancellation |
| API Reference | Auto-generated from source docstrings |
git clone https://github.com/yuramalna/pi-python.git
cd pi-python
python -m venv .venv && source .venv/bin/activate
# Install both packages in dev mode
pip install -e "packages/pi_llm[dev]"
pip install -e "packages/pi_llm_agent[dev]"
# Install docs dependencies
pip install mkdocs-material 'mkdocstrings[python]' mkdocs-gen-files mkdocs-section-index
# Run tests (324 total)
pytest packages/pi_llm/tests/ --ignore=packages/pi_llm/tests/integration
pytest packages/pi_llm_agent/tests/ --ignore=packages/pi_llm_agent/tests/integration
# Lint
ruff check packages/pi_llm/src/ packages/pi_llm_agent/src/
# Serve docs locally
mkdocs serveThis project is a Python port of the @anthropic/pi-ai and @anthropic/pi-agent TypeScript packages from pi-mono by Mario Zechner. The original pi-mono is a comprehensive AI agent toolkit featuring a coding agent CLI, unified LLM API, TUI & web UI libraries, and more. We're grateful for his excellent architecture and open-source work that made this port possible.