Python library for programmatically invoking AI coding agents
Project description
agentrunner (Python)
Python library for programmatically invoking AI coding agents. Part of the agentrunner monorepo.
Supported CLIs
| Runner | CLI Version | Status |
|---|---|---|
| Claude Code | >= 1.0.12 | ✅ |
Requirements
- Python >= 3.11
- Claude Code CLI >= 1.0.12
Installation
pip install agentrunner
Quick Start
import asyncio
from agentrunner.claudecode import create_claude_runner, ClaudeRunOptions
runner = create_claude_runner()
async def main():
# Simple run
result = await runner.run("What files are in this directory?", ClaudeRunOptions(
working_dir="/path/to/project",
skip_permissions=True,
))
print(result.text)
# Streaming
stream = await runner.run_stream("Explain this codebase")
async for message in stream:
print(message.type, message.raw)
asyncio.run(main())
API
create_claude_runner(config?)
Creates a runner for the Claude Code CLI.
Config options (ClaudeRunnerConfig):
| Field | Type | Default | Description |
|---|---|---|---|
binary |
str |
"claude" |
CLI binary name or path |
spawn |
SpawnFn |
— | Custom spawn function (for testing) |
logger |
Logger |
— | Logger for debug output (opt-in) |
runner.run(prompt, options?)
Execute a prompt and return the final Result.
runner.run_stream(prompt, options?)
Execute a prompt and stream messages as they arrive. Returns AsyncIterable[Message].
runner.start(prompt, options?)
Launch an agent process and return a Session for full lifecycle control.
Run Options
Common options (RunOptions):
| Field | Type | Description |
|---|---|---|
model |
str |
Model name or alias |
system_prompt |
str |
System prompt override |
append_system_prompt |
str |
Appended to default system prompt |
working_dir |
str |
Working directory for subprocess |
env |
dict[str, str] |
Additional environment variables |
max_turns |
int |
Maximum agentic turns |
timeout |
float |
Timeout in milliseconds |
skip_permissions |
bool |
Skip permission prompts |
Claude-specific options (ClaudeRunOptions extends RunOptions):
| Field | Type | Description |
|---|---|---|
allowed_tools |
list[str] |
Tools the agent may use |
disallowed_tools |
list[str] |
Tools the agent may not use |
mcp_config |
str |
Path to MCP server config |
json_schema |
str |
JSON Schema for structured output |
max_budget_usd |
float |
Cost limit in USD |
resume |
str |
Session ID to resume |
continue_session |
bool |
Continue most recent session |
session_id |
str |
Specific session ID |
include_partial_messages |
bool |
Stream partial/incremental messages |
on_message |
callable |
Callback for each streamed message |
Result
| Field | Type | Description |
|---|---|---|
text |
str |
Final response text |
is_error |
bool |
Whether the run ended in error |
exit_code |
int |
Process exit code |
usage |
Usage |
Token counts |
cost_usd |
float |
Estimated cost in USD |
duration_ms |
float |
Wall-clock duration in ms |
session_id |
str |
Session ID for resumption |
Session
| Attribute | Type | Description |
|---|---|---|
messages |
AsyncIterable[Message] |
Iterate messages as they arrive |
result |
Future[Result] |
Resolves when the agent finishes |
abort() |
— | Terminate the agent process |
send() |
— | Reserved (raises RuntimeError) |
Error Classes
All errors extend RunnerError:
NotFoundError— CLI binary not foundTimeoutError— execution timed outNonZeroExitError— CLI exited with non-zero code (has.exit_code)ParseError— failed to parse CLI outputCancelledError— execution cancelledNoResultError— stream ended without a result message
from agentrunner import TimeoutError
try:
await runner.run("complex task", ClaudeRunOptions(timeout=30_000))
except TimeoutError:
print("Timed out!")
Usage Examples
Session Resume
# First run — capture the session ID.
result = await runner.run("Set up the project structure")
session_id = result.session_id
# Resume the same session later.
result = await runner.run("Now add tests", ClaudeRunOptions(resume=session_id))
Session Object
session = runner.start("Explain this code", ClaudeRunOptions(max_turns=1, timeout=30_000))
async for msg in session.messages:
print(f"[{msg.type}] {msg.raw[:80]}")
result = await session.result
print(f"Response: {result.text}")
Streaming with Partial Messages
from agentrunner.claudecode import parse
stream = await runner.run_stream("List fun facts", ClaudeRunOptions(
include_partial_messages=True,
))
async for msg in stream:
if msg.type == "assistant":
parsed = parse(msg.raw)
if parsed.type == "stream_event":
import json
raw = json.loads(msg.raw)
delta = raw.get("event", {}).get("delta", {})
if delta.get("type") == "text_delta":
print(delta["text"], end="", flush=True)
Development
cd python
pip install -e ".[dev]" # install with dev dependencies
ruff check src/ tests/ # lint
python -m pytest # run tests
Or from the repo root:
make check-python # build + lint + test
make check # all libraries
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 Distribution
Built Distribution
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 driangle_agentrunner-0.0.1.tar.gz.
File metadata
- Download URL: driangle_agentrunner-0.0.1.tar.gz
- Upload date:
- Size: 21.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
09f4d8971b62ef69f384a4766af826996d9dd9ff219130629d2e64c32f2ba13c
|
|
| MD5 |
d9a252fda50674c1114c021ee1e12965
|
|
| BLAKE2b-256 |
2d287d63abd8a8b3902437f04f22e2d22aa12689c67ce92db5b7644fa30709a4
|
File details
Details for the file driangle_agentrunner-0.0.1-py3-none-any.whl.
File metadata
- Download URL: driangle_agentrunner-0.0.1-py3-none-any.whl
- Upload date:
- Size: 20.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5df3f18c62e921b0b0295468257ba7c7c36ea588840b5a2a92176b9c44a13920
|
|
| MD5 |
a55f6734aee85ec280e32e9a865a2cb4
|
|
| BLAKE2b-256 |
cda799093e942c355a64270f554769f9ec63b6b676c84e4f3ae46124413ca1c0
|