Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

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-shaped GenerateRequest, including params.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, prefer CarRuntime.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.dev20260921

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for car-runtime 0.55.0.dev20260921
File Interpreter ABI Platform
car_runtime-0.55.0.dev20260921-cp39-abi3-win_amd64.whl CPython 3.9 abi3 Windows x86-64 Details
car_runtime-0.55.0.dev20260921-cp39-abi3-manylinux_2_28_x86_64.whl CPython 3.9 abi3 Linux glibc 2.28+ x86-64 Details
car_runtime-0.55.0.dev20260921-cp39-abi3-macosx_15_0_arm64.whl CPython 3.9 abi3 macOS 15.0+ ARM64 Details

Total release size: 105.6 MB

Release files / car_runtime-0.55.0.dev20260921-cp39-abi3-win_amd64.whl

Download URL car_runtime-0.55.0.dev20260921-cp39-abi3-win_amd64.whl
Size 35.7 MB
Tags CPython 3.9 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
5a147da747abc765d11b5e55391187c7602cca9f0a075ff7717b723599291f68
BLAKE2b-256 checksum
How to use checksums
3478a2b1a1c6a0c4b93c024da2751e5c20949f001706e66cb914f109f2c6a624
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

Release files / car_runtime-0.55.0.dev20260921-cp39-abi3-manylinux_2_28_x86_64.whl

Download URL car_runtime-0.55.0.dev20260921-cp39-abi3-manylinux_2_28_x86_64.whl
Size 40.2 MB
Tags CPython 3.9 Linux glibc 2.28+ x86-64 abi3
SHA-256 checksum
How to use checksums
2c4ac8efb7a6e3ff6453cd6c751b1d1a2ce40505eab794574527e573dec4a7a4
BLAKE2b-256 checksum
How to use checksums
14d22485289d2abcae210842ac963fd06f32d94cc0d41a1350c87ae85abdf066
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

Release files / car_runtime-0.55.0.dev20260921-cp39-abi3-macosx_15_0_arm64.whl

Download URL car_runtime-0.55.0.dev20260921-cp39-abi3-macosx_15_0_arm64.whl
Size 29.7 MB
Tags CPython 3.9 abi3 macOS 15.0+ ARM64
SHA-256 checksum
How to use checksums
adb0494db2a2847b3c63a0c60f328f56a48ca29eb433ee94452e6b788d5f0635
BLAKE2b-256 checksum
How to use checksums
efce79417e12b00c7427f3eb422963d62c53ba7b72154d10be46d681c4d0281b
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

Release history Release notifications | RSS feed

0.57.4

3 release files

0.57.2

3 release files

0.55.0

3 release files

This release

0.54.0

3 release files

0.53.0

3 release files

0.51.0

3 release files

0.50.0

3 release files

0.49.0

3 release files

0.48.0

3 release files

0.43.0

3 release files

0.42.0

3 release files

0.40.0

3 release files

0.39.1

3 release files

0.39.0

3 release files

0.38.0

3 release files

0.37.0

3 release files

0.36.0

3 release files

0.31.0

3 release files

0.30.0

3 release files

0.29.0

3 release files

0.28.0

3 release files

0.27.0

3 release files

0.26.0

3 release files

0.25.0

3 release files

0.24.1

3 release files

0.24.0

3 release files

0.20.0

3 release files

0.19.0

3 release files

0.18.0

3 release files

0.17.0

3 release files

0.16.1

3 release files

0.16.0

3 release files

0.15.2

3 release files

0.15.1

3 release files

0.15.0

3 release files

0.14.0

3 release files

0.13.0

3 release files

0.12.0

3 release files

0.11.1

3 release files

0.11.0

3 release files

0.10.1

3 release files

0.10.0

3 release files

0.9.0

3 release files

0.8.2

4 release files

0.8.1

4 release files

0.8.0

4 release files

0.7.0

4 release files

0.6.1

4 release files

0.6.0

4 release files

0.5.1

4 release files

0.4.9

4 release files

0.4.8

4 release files

0.4.7

4 release files

0.4.3

2 release files

0.4.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page