Skip to main content

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 found
  • TimeoutError — execution timed out
  • NonZeroExitError — CLI exited with non-zero code (has .exit_code)
  • ParseError — failed to parse CLI output
  • CancelledError — execution cancelled
  • NoResultError — 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

driangle_agentrunner-0.0.1.tar.gz (21.2 kB view details)

Uploaded Source

Built Distribution

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

driangle_agentrunner-0.0.1-py3-none-any.whl (20.5 kB view details)

Uploaded Python 3

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

Hashes for driangle_agentrunner-0.0.1.tar.gz
Algorithm Hash digest
SHA256 09f4d8971b62ef69f384a4766af826996d9dd9ff219130629d2e64c32f2ba13c
MD5 d9a252fda50674c1114c021ee1e12965
BLAKE2b-256 2d287d63abd8a8b3902437f04f22e2d22aa12689c67ce92db5b7644fa30709a4

See more details on using hashes here.

File details

Details for the file driangle_agentrunner-0.0.1-py3-none-any.whl.

File metadata

File hashes

Hashes for driangle_agentrunner-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 5df3f18c62e921b0b0295468257ba7c7c36ea588840b5a2a92176b9c44a13920
MD5 a55f6734aee85ec280e32e9a865a2cb4
BLAKE2b-256 cda799093e942c355a64270f554769f9ec63b6b676c84e4f3ae46124413ca1c0

See more details on using hashes here.

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