Pi Agent Python SDK
Use your installed Pi coding agent as a Python API. Stream responses, continue conversations, and control sessions from Python.
Pi is an open-source coding agent that runs in your terminal. This unofficial community SDK launches the Pi CLI in RPC mode and exposes prompts, streaming events, and sessions through typed synchronous and asynchronous Python APIs.
from pi_agent import PiClient
with PiClient() as pi:
print(pi.run("Explain the current project without changing files.").text)
Requires an installed, configured Pi CLI — see Prerequisites.
Prerequisites · Quick start · Streaming · Async · Configuration · Thinking · RPC · Documentation · Troubleshooting · Support
What you can do
- Run prompts from Python — get a final answer, or stream text, thinking, and tool events as they happen.
- Keep conversations going — send follow-ups on the same client, or resume, fork, and clone sessions.
- Control the agent — switch models, set thinking level, steer mid-run, and compact context.
- Reuse your Pi setup — same configuration, tools, and extensions as the CLI, with sync or async clients.
Prerequisites
| Requirement | Notes |
|---|---|
| Python 3.11+ | Package metadata requires 3.11 or newer |
| Node.js 22.19.0+ | Required by Pi 0.86.1 |
| Pi 0.85.1+ | Minimum accepted version; 0.86.1 is the tested baseline |
| Model provider | Required; configure with the Pi CLI (see Quick start) |
Quick start
Install Pi with Node.js 22.19.0 or newer (pin matches the tested baseline):
npm install -g @earendil-works/pi-coding-agent@0.86.1
pi --version
Run pi once to configure your provider and model. The SDK uses that
configuration when it starts Pi.
Install the Python package from PyPI:
python -m pip install pi-agent-python-sdk
The distribution is named pi-agent-python-sdk; import it as
pi_agent.
from pi_agent import PiClient
with PiClient() as pi:
result = pi.run("Explain the current project without changing files.")
print(result.text)
The context manager starts and closes Pi. run() waits for the conversation to
settle. The result includes finalized messages, session identity, elapsed time,
and observed assistant usage.
Continue the conversation with another call on the same client:
from pi_agent import PiClient
with PiClient() as pi:
print(pi.run("Explain this project's entry points without editing files.").text)
print(pi.run("Which of those entry points handles configuration?").text)
Pi keeps the conversation context. Each result contains only the messages and answer from that call; a call with no assistant output has empty text.
Streaming
from pi_agent import PiClient
with PiClient() as pi:
with pi.stream("Explain this project's entry points without editing files.") as stream:
for event in stream:
if event.text_delta is not None:
print(event.text_delta, end="", flush=True)
result = stream.result()
print(f"\nStop reason: {result.stop_reason}")
Streaming details
event.raw contains the full Pi event, including fields the SDK does not yet
recognize. Keep the stream inside its context: leaving early cleans up unfinished
work. See errors and cancellation for handling timeouts and partial
results.
Async usage
Use AsyncPiClient in applications that already run an event loop. Command
arguments and results match the synchronous client.
import asyncio
from pi_agent import AsyncPiClient
async def main() -> None:
async with AsyncPiClient() as pi:
result = await pi.run("Explain the current project without changing files.")
print(result.text)
if __name__ == "__main__":
asyncio.run(main())
Async streaming
Use async with pi.stream(...), async for event in stream, and
await stream.result(). See the complete streaming example.
Configuration
Choose the project directory and whether to save the conversation:
from pi_agent import PiClient
with PiClient(cwd=".", no_session=True) as pi:
print(pi.run("Describe this project without changing files.").text)
Leave no_session unset to preserve Pi's normal session persistence. Use
session= to open an existing session. For model overrides, see
Models and thinking.
More configuration
See constructor options for environment overrides, executable paths, and deadlines.
Extensions are installed and configured through Pi. To load your own extension,
pass extra_args=["--extension", "/absolute/path/to/your-extension.ts"] to
either client. See using your own extensions for details and
extension UI for an interactive example.
Models and thinking
By default the SDK uses whatever model you already configured in the Pi CLI.
Override it when you construct the client, or switch later on the same client.
Set the model and thinking level before run() or stream().
Select a model at construction:
from pi_agent import PiClient
with PiClient(provider="openai", model="gpt-5") as pi:
print(pi.run("Summarise this repo without changing files.").text)
Thinking levels depend on the current model. Query them, set one, then confirm what Pi actually applied:
from pi_agent import PiClient
with PiClient() as pi:
levels = pi.get_available_thinking_levels()
print("available:", levels)
if "high" in levels:
pi.set_thinking_level("high")
print("effective:", pi.get_state()["thinkingLevel"])
print(pi.run("Analyse this project's architecture without changing files.").text)
Replace the example provider/model ids with ones from your Pi install
(pi --list-models or get_available_models()).
List models and switch after start
from pi_agent import PiClient
with PiClient() as pi:
for model in pi.get_available_models():
print(model["provider"], model["id"])
selected = pi.set_model("openai", "gpt-5")
print("using", selected["provider"], selected["id"])
print(pi.run("Summarise this repo without changing files.").text)
RPC access
The SDK speaks Pi's existing JSONL protocol over stdin/stdout:
Your Python application
PiClient / AsyncPiClient
pi --mode rpc
Models · tools · extensions · sessions
Inspect session state without starting a model run:
from pi_agent import PiClient
with PiClient() as pi:
state = pi.get_state()
print(state["sessionId"])
Which interface to use
| You need | Use |
|---|---|
| A completed conversation result | run() |
| Events while a conversation runs | stream() |
| Prompt acknowledgement and your own event handling | prompt() with events() |
| Session events through the next settlement | prompt_and_wait() or collect_events() |
| Every event without retaining history | on_event(callback) |
| A specific Pi operation | get_state(), set_model(), fork(), and other command methods |
| A raw command response envelope | request() |
Python arguments use snake_case; wire dictionaries retain Pi's camelCase
fields. prompt() acknowledges submission, which may be handled entirely by an
extension. It does not wait for a completed answer.
Each client starts its own Pi subprocess. Use one client per conversation and
wait for each run() or stream to finish before starting the next. After using
prompt() for your own event handling, use a fresh client for run() or
stream() so results cannot include delayed events from earlier work.
See RPC structure for the protocol mapping and module layout, and the command reference for every method.
Documentation
| Guide | Contents |
|---|---|
| Usage | Sessions, images, concurrency, events, and extension UI |
| API reference | Constructors, commands, types, and results |
| Errors and cancellation | Deadlines, partial results, cleanup, and recovery |
| RPC structure | How the Python client maps to Pi's protocol |
| Compatibility | Runtime versions and platform validation |
| Examples | Runnable sync, async, streaming, sessions, steering, and UI examples |
| Release notes | Changes included in 0.2.2 |
Examples use your configured Pi and may make provider calls. Development checks use an isolated local test provider; see CONTRIBUTING.md for setup and validation commands.
Troubleshooting
| Symptom | What to check |
|---|---|
pi not found / launch fails |
Ensure the Pi CLI is on PATH, or pass executable= to the client |
| Version rejected | Upgrade to Pi 0.85.1+; prefer the tested baseline 0.86.1 |
| No model / auth errors | Run pi once and complete provider setup |
| Unexpected file or command changes | Review Pi tool/extension settings before automation |
Support
- Open an issue for bugs, questions, or compatibility reports.
- See CONTRIBUTING.md for local setup and pull requests.
- For security reports, open a private security advisory.
License
Metadata
Release files for pi-agent-python-sdk 0.2.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pi_agent_python_sdk-0.2.2.tar.gz | 42.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pi_agent_python_sdk-0.2.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 90.2 kB
Release files / pi_agent_python_sdk-0.2.2.tar.gz
| Download URL | pi_agent_python_sdk-0.2.2.tar.gz |
|---|---|
| Size | 42.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1c407e05276afa7ec7d39fb86f394b1412480cd0cca24297ec6368c517ac8d65
|
|
BLAKE2b-256 checksum How to use checksums |
85879b16ad24f1f98e467bc5d02bcb9d9861bf81cf681339a67f6e22509db7b0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.
Transparency logRelease files / pi_agent_python_sdk-0.2.2-py3-none-any.whl
| Download URL | pi_agent_python_sdk-0.2.2-py3-none-any.whl |
|---|---|
| Size | 48.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
926f28fd2b65d9f0282ca088c8f0f2b2cdbf63385bb3076f17854675699f227c
|
|
BLAKE2b-256 checksum How to use checksums |
680ae4c19ff715704a781f84d4e09bc141a547737ed74b81a3d5abd7e27e5c8c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.
Transparency log