car-runtime (Python)
Python bindings for Common Agent Runtime (CAR) — a deterministic execution layer for AI agents. Models propose; the runtime validates and executes.
As of v0.8, this package is a thin daemon client: every method
proxies to a singleton car-server daemon over WebSocket. Inference,
the per-session memory graph, and tool dispatch all live on the
daemon side. Start car-server once per host before using the
bindings (car-server ships in the same wheel; see "Start the
daemon" below).
Pre-built wheels (abi3, Python 3.9+) for:
macosx_15_0_arm64— macOS 15+ on Apple Silicon (Intel Macs dropped — see CHANGELOG)manylinux_2_17_x86_64,manylinux_2_28_aarch64
Building from source on macOS: set MACOSX_DEPLOYMENT_TARGET=15.0 when
invoking maturin build. MLX's bundled Metal shaders don't compile against
the default 11.0 target, and our release wheels target 15.0 because the
compiled extension pulls in libc++ symbols (notably
std::exception_ptr::__from_native_exception_pointer) that only exist on
macOS 15+. A lower target produces a wheel whose tag doesn't match what the
binary actually requires at dlopen time.
Install
From a release wheel (substitute the current version for X.Y.Z):
pip install https://github.com/Parslee-ai/car-releases/releases/download/vX.Y.Z/car_runtime-X.Y.Z-cp39-abi3-macosx_15_0_arm64.whl
Or build from source:
pip install maturin
cd car-rs/crates/car-ffi-pyo3
maturin develop --release
The import name is car_runtime (matching the PyPI package name).
Call the daemon
The same five-line Node example appears in every package landing page and in the Node scaffold so it cannot drift from the agent-facing skill:
async function daemonCallExample() {
// BEGIN CALL_DAEMON_FIVE_LINES
const { CarRuntime } = (await import('car-runtime')).default;
const car = new CarRuntime();
car.registerDaemonHandler('tools.execute', async () => JSON.stringify({ ok: true }));
const methods = JSON.parse(await car.daemonCall('capabilities.list', '{}'));
return { car, methods, agents: JSON.parse(await car.agentsList('{}')) };
// END CALL_DAEMON_FIVE_LINES
}
Python uses the equivalent daemon_call, agents_list, and
register_daemon_handler names; the complete runnable Python block is in the
car-capabilities skill.
Start the daemon
# The car-server binary ships inside the wheel. Default port 9100;
# auth on by default. Foreground (Ctrl-C to stop):
python -m car_runtime.server
# Or background:
python -m car_runtime.server &
# Override the URL the bindings use:
export CAR_DAEMON_URL=ws://127.0.0.1:9100
On macOS the SwiftUI menubar host (CAR Host.app) launches the
daemon for you. Install it once from the .pkg installer on the
latest GitHub release; from then on it supervises car-server and
keeps itself up to date via Sparkle.
Quickstart
import json
from car_runtime import CarRuntime, verify
rt = CarRuntime() # lazy-connects to ws://127.0.0.1:9100/
# Tools + policies — proxied to the daemon's per-session runtime
# and persist for the lifetime of this CarRuntime's WS connection.
rt.register_tool("shell")
rt.register_policy(
"no_rm",
"deny_tool_param",
target="shell",
key="command",
pattern="rm -rf",
)
# Ground with facts (proxied to the daemon's per-session memgine).
rt.add_fact("project_language", "Python", "pattern")
# Static verification — runs on the daemon side, no model needed.
proposal = json.dumps({
"actions": [{
"id": "a1",
"type": "tool_call",
"tool": "shell",
"parameters": {"command": "ls"},
"dependencies": [],
}],
})
check = json.loads(rt.verify_proposal(proposal))
if not check["valid"]:
raise RuntimeError(f"invalid proposal: {check['issues']}")
# For a complete agent cycle, use the packaged helper shown below. It wires
# register_tool_handler + submit_proposal for you.
Packaged agent loop
Do not copy a harness into each agent. Import the versioned loop and keep the project entry file declarative:
from car_runtime.agent_loop import main
main({
"agent_name": "Lookup Agent",
"identity": "Use lookup before answering; never guess.",
"tool_schemas": [{
"name": "lookup", "description": "Look up one key",
"parameters": {"type": "object", "properties": {"key": {"type": "string"}},
"required": ["key"]},
}],
"tools": {"lookup": lambda p: {"key": p["key"], "value": lookup(p["key"])}},
"policies": [],
"max_turns": 8,
})
run_agent(config, goal) is also exported for embedding and tests. Its
AgentOutcome["run_id"] is the durable key accepted by runs_get_trace; it is
None when an older daemon has no runs.* surface or did not acknowledge the
start. run_chat_turn keeps returning bare text by default; pass
include_run_id=True to receive {"text": str, "run_id": str | None}.
main(config) provides --task, --json, and --serve. The loop adds
finish, statically verifies every proposal before submit_proposal, preserves
tool-call/result IDs, honors per-schema timeoutMs, traces task and chat runs,
and uses request-shaped inference with prompt-cache breakpoints. Importing
car_runtime.agent_loop has no daemon side effect; running it requires
car-server. The wheel includes car_runtime/agent_loop.pyi, while the
top-level car_runtime.pyi advertises the submodule.
Streaming inference
Streaming is WebSocket-only. Connect to car-server, call the
infer_stream JSON-RPC method, and consume inference.stream.event
notifications. CarRuntime.infer_stream remains only as an ABI-compatibility
stub; it always raises RuntimeError and never invokes its callback. See
the streaming cookbook.
Multi-agent coordination
import json
from car_runtime import register_agent_runner, run_swarm
def agent_fn(spec_json: str, task: str) -> str:
spec = json.loads(spec_json)
# Call your LLM of choice, returning an AgentOutput JSON.
return json.dumps({"name": spec["name"], "response": "...", "tool_calls": []})
# Option A: register once, then call run_* without passing agent_fn each time.
register_agent_runner(agent_fn)
result = run_swarm(
"parallel",
json.dumps([
{"name": "researcher", "role": "gather facts", "model": "gpt-5"},
{"name": "writer", "role": "compose summary", "model": "claude-opus-4-7"},
]),
"summarize the CAR paper",
)
# Option B: pass agent_fn per call.
result = run_swarm("parallel", agents_json, task, agent_fn=agent_fn)
API surface
The runtime (CarRuntime) exposes:
- State:
state_set,state_get,state_exists,state_snapshot,state_keys - Memory:
add_fact,query_facts,fact_count,build_context,build_context_fast,persist_memory,load_memory,consolidate - Skills:
ingest_skill,find_skill,report_outcome,distill_skills,ingest_distilled_skills,list_skills,domains_needing_evolution,repair_skill,evolve_skills - Tools + policies:
register_tool,register_agent_basics,register_policy,set_replan_config - Inference:
infer,infer_tracked,infer_tracked_with_request(request-shapedGenerateRequest, includingparams.strict_model),infer_with_context,infer_with_context_tracked,embed,rerank,classify,prepare_speech_runtime,transcribe,synthesize - Models:
list_models,pull_model,remove_model,list_models_unified,register_model,route_model,model_stats - Execution:
event_count,verify_proposal,execute_proposal
Module-level standalone functions:
- Verification:
verify,simulate,optimize,equivalent - Stateless execute:
execute(creates a fresh Runtime; for long-lived use, preferCarRuntime.execute_proposal) - Multi-agent:
register_agent_runner,run_swarm,run_pipeline,run_supervisor,run_map_reduce,run_vote - Scheduler:
create_task,run_task,run_task_loop,ensure_dream_task - Planner:
rank_proposals
Compatibility-only method: infer_stream (always raises; use WebSocket).
Structured returns are JSON-encoded strings — json.loads them on the Python
side. This keeps the FFI surface stable across binding and protocol changes.
Type stubs
The wheel ships the canonical car_runtime.pyi plus a
byte-identical package mirror (car_runtime/__init__.pyi) and package-local
py.typed marker (PEP 561). mypy, pyright, Pylance, and similar tools pick
up the full native method signatures and the typed agent_loop submodule — no
extra install needed.
If you're editing the source tree, update crates/car-ffi-pyo3/car_runtime.pyi
and copy it to car_runtime/__init__.pyi. scripts/check-ffi-parity.sh rejects
drift between them and continues to check the canonical stub against
src/lib.rs. See CLAUDE.md for the FFI-bindings parity rule.
Offline reference docs
The wheel also ships a car_runtime_docs/ directory alongside the compiled
extension (find it with python3 -c "import car_runtime, pathlib; print(pathlib.Path(car_runtime.__file__).parent / 'car_runtime_docs')" if
your install layout differs) — SPEC.md, GUIDE.md, CLI.md, ASSISTANT.md,
MCP.md, agent-ir-spec.md. So an agent with pip install car-runtime and no
network access can still read how the car CLI, the flagship assistant's
tools, and car-mcp actually work, not just the typed surface above.
car_runtime_docs/websocket-protocol.md is a short pointer, not the full
reference (~510KB, deliberately not bundled) — read the real thing at
https://car.parslee.ai/websocket-protocol.md.
Development
# Install dev deps.
pip install maturin pytest
# Build and install in editable mode.
cd car-rs/crates/car-ffi-pyo3
maturin develop
# Run the smoke tests.
pytest tests/ -v
Architecture
This package is a thin PyO3 client to the singleton car-server
daemon over WebSocket — CarRuntime() lazy-connects, every method
proxies through the JSON-RPC dispatcher, and the daemon owns
inference / memory / tool dispatch / per-session state.
Pre-v0.8 (the RuntimeMode::Embedded path) the wheel hosted an
in-process car-engine + car-memgine and ran inference under
py.allow_threads(...). That path was retired to close the
multi-tenant overcommit hazard CAR-issue #139 was opened for —
two FFI consumers in different processes each spawned a fresh
admission semaphore + model cache, and concurrent runs could
overwhelm the host. v0.8 takes the harder path: one daemon per
host, every client attaches.
See the car-releases README for the broader CAR architecture.
License
Free for any use including commercial; free to redistribute unmodified.
Modification, reverse engineering, and derivative works are not permitted.
See LICENSE for the full text. Copyright © 2026 Parslee AI.
Metadata
Release files for car-runtime 0.55.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| car_runtime-0.55.0-cp39-abi3-win_amd64.whl | CPython 3.9 | abi3 | Windows x86-64 | Details |
| car_runtime-0.55.0-cp39-abi3-manylinux_2_28_x86_64.whl | CPython 3.9 | abi3 | Linux glibc 2.28+ x86-64 | Details |
| car_runtime-0.55.0-cp39-abi3-macosx_15_0_arm64.whl | CPython 3.9 | abi3 | macOS 15.0+ ARM64 | Details |
Total release size: 113.0 MB
Release files / car_runtime-0.55.0-cp39-abi3-win_amd64.whl
| Download URL | car_runtime-0.55.0-cp39-abi3-win_amd64.whl |
|---|---|
| Size | 35.7 MB |
| Tags | CPython 3.9 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
aa108d8fe044b9fe63ff5ee893bf7bdc1b6cfe29baa100d8f0c7171a3b6aed3d
|
|
BLAKE2b-256 checksum How to use checksums |
19f7f58bda33051baf47d798e88eac35b71b48596894d1346bb230d52b7e550e
|
| 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 / car_runtime-0.55.0-cp39-abi3-manylinux_2_28_x86_64.whl
| Download URL | car_runtime-0.55.0-cp39-abi3-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 44.9 MB |
| Tags | CPython 3.9 Linux glibc 2.28+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
1ccd5f3d8b947cb40a5b45d1b429d2e6dae68f70a5b70917f59a9e9edd470a27
|
|
BLAKE2b-256 checksum How to use checksums |
1b005c03f83b7c509087891143e2331eb0df581b3bc058cd831561a5f2f33265
|
| 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 / car_runtime-0.55.0-cp39-abi3-macosx_15_0_arm64.whl
| Download URL | car_runtime-0.55.0-cp39-abi3-macosx_15_0_arm64.whl |
|---|---|
| Size | 32.3 MB |
| Tags | CPython 3.9 abi3 macOS 15.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
9244be08eb6f9afa7bdeee84ca71c6a3c1c2a883868815cab9cd744699db7596
|
|
BLAKE2b-256 checksum How to use checksums |
ba00d2f25e370a58cdd81867cb14236a8e7ca6f9423f7f22d0f79a06ade6aeac
|
| 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