Agent runtime
agent-runtime-py provides detached Claude Code workers that applications can reconnect to after restarting. Import it as agent_runtime. It uses the official Claude Agent SDK and your installed Claude Code executable, loading native user and project settings, hooks, skills, and MCP servers.
This repository is under active development. The current implementation supports macOS and Linux and has been exercised with Claude Code 2.1.281 and Claude Agent SDK 0.2.159. Windows is not supported.
from pathlib import Path
from agent_runtime import ClaudeRuntime, LaunchOptions
runtime = ClaudeRuntime(Path.home() / ".local/state/example/claude")
execution = await runtime.start(
"Inspect this project's tests.",
message_id="request-123",
launch_id="conversation-456:request-123",
options=LaunchOptions(cwd=Path.cwd()),
)
The default permission mode is Claude's ordinary permission behavior. Pending approvals and questions are persisted in runtime.store.interactions(execution_id) and remain pending until the application supplies an explicit answer. Applications must present these requests to the user; this library does not auto-approve them.
Lifetime and delivery
- Each execution is a detached Python worker owning one native Claude SDK connection. Destroying the application client does not stop the worker.
- A native session can have several executions after explicit stop and resume. A process lease prevents two managed workers from resuming it simultaneously.
- Message IDs are idempotent within a session. Reusing an ID with different text is an error. A launch ID also fixes the initial prompt and launch configuration.
acceptedmeans privately journaled,dispatchingmeans sent or being sent, anddeliveredrequires Claude to echo the exact input UUID. A crash before that acknowledgement producesuncertain; the runtime never silently replays that input.- Process identity includes PID and process creation time. Restarting a dead worker requires an explicit resume request. A process restart does not imply resubmitting previously delivered work.
- Events have durable increasing cursors across executions. Native SDK messages are retained as
claude.message; presentation events includeagent.message,agent.turn.completed, andwork.settled. - A normal turn result leaves the worker available for more requests. The idle timeout applies only when there is no active request or tracked background task or running monitor. Set it to zero to keep the worker open until explicitly stopped.
- Private SQLite state and logs contain conversation content. Environment variables are passed to the child without being serialized into launch configuration.
runtime.stop(execution_id) requests shutdown. runtime.attach(execution_id) returns an interactive resume command only after the managed worker has stopped, preventing concurrent native ownership. It must be launched from the recorded working directory.
Monitors and local peer messages
Install agent-runtime-hooks using a typed-agent-hooks Collection for both providers. The hooks register native process identities and current permission modes. Claude hooks start a private delivery child whose inherited native inbox token remains in memory; it is never written to the registry or used for messages to another session.
agent_runtime.operations supplies monitor_start, monitor_list, monitor_get, monitor_stop, monitor_events, agents, and send. Codex operations delegate to the installed codexr CLI. Claude monitors run a detached foreground Bash command and retain stdout observations in SQLite; stderr goes to a private log. A 1 MiB output limit stops an overly verbose monitor. Delivery batches retain each monitor's launch permission class. Native Claude receives these as peer context and applies its own admission policy, including holding messages if permission modes require approval. transport-written confirms only a socket write, not admission or model processing. Interrupted writes remain uncertain and are not replayed automatically.
A normal Claude monitor stops when its owning native process exits or its deadline expires. A persistent monitor has no deadline and continues collecting output after CLI exit; resuming the exact native session starts a new delivery child for pending observations. This does not keep a plain claude -p process open or restart processes after a host reboot. Interactive sessions and managed SDK workers receive observations between turns. A managed worker's idle timeout does not end a running monitor.
Cross-session sends identify their source and never use the destination's own-event token. Unknown source permission modes fail closed. Codex receipts preserve its native delivered/queued meanings; Claude socket receipts are transport-only. Native policy or a stopped process can prevent delivery.
Goals use Claude's native /goal, including its evaluator, retry limits and resume behavior. There is no second goal store or emulated Codex goal API. An objective can survive native resume while usage baselines reset; unrecoverable errors can clear it. See Claude goals.
Development
Run uv run pytest -q. The integration tests use the real Claude Agent SDK and detached worker processes against a deterministic fake native CLI. They cover application reconnection, stop/resume, duplicate admission, lost acknowledgement, explicit permission decisions, actual shell monitor failure, process-tree shutdown, deadlines, retained observations across native-owner exit/resume, and peer permission labels. They require no model account or API credentials.
Release publishing uses GitHub Actions trusted publishing. Configure a pending PyPI publisher with project agent-runtime-py, owner nimashoghi, repository agent-runtime, workflow release.yml, and environment pypi. Publishing a GitHub release whose tag matches v<package-version> builds and publishes the package.
Metadata
Release files for agent-runtime-py 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| agent_runtime_py-0.1.1.tar.gz | 77.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| agent_runtime_py-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 102.9 kB
Release files / agent_runtime_py-0.1.1.tar.gz
| Download URL | agent_runtime_py-0.1.1.tar.gz |
|---|---|
| Size | 77.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0c6dd9ecdcefcf45fb26e3ef5bc4cd6010e8c9ee477408ac3a747e9669b470a0
|
|
BLAKE2b-256 checksum How to use checksums |
9487f97cc6420ac3eae7b64f752746556924af46e6f3b13c955c57cfd78919f2
|
| 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 24, 2026.
Transparency logRelease files / agent_runtime_py-0.1.1-py3-none-any.whl
| Download URL | agent_runtime_py-0.1.1-py3-none-any.whl |
|---|---|
| Size | 25.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4405b93ab176fd2e706027fd39425a7c6acf63ec173cb86f04c8ded8f02608a0
|
|
BLAKE2b-256 checksum How to use checksums |
b2a59232aaa37cd0990dedf43fc9e7a8aa3eeb17db6deb96377dd0bf27f22da1
|
| 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 24, 2026.
Transparency log