Skip to main content

A11

A11 is a Python action and streaming runtime backed by a C++20 implementation. The Python package in a11/ is the public, language-native API; cpp/a11/ contains the native implementation, and cpp/thread/ contains its cooperative fiber runtime.

This guide covers the development build, tests, and release wheel matrix. Run all commands from the repository root.

Python and native architecture

Runtime state lives in C++. Public classes such as Status, Time, Duration, wire records, ChunkStoreReader, ChunkStoreWriter, AsyncNode, NodeMap, Action, ActionRegistry, and Session are the bound native class objects, not parallel Python implementations. Thin modules under a11/ add Python protocols: awaitables and async iteration, subclass-friendly callback adaptation, object serialization, and Pydantic-compatible validation, JSON, copy, and schema methods.

LocalChunkStore is a deliberately thin forwarding adapter around the native in-memory store. Keeping that virtual Python boundary lets applications subclass it for custom stores and fault injection while all storage and synchronization remain native. Python serializer/deserializer callbacks remain in a11.data.serialization; the chunks they consume and produce are native binary values.

Import from the ordinary public modules (a11, a11.actions, a11.data.types, and so on). Synchronous and asynchronous native failures cross the boundary as a11.status.StatusException with structured details preserved.

Prerequisites

The local build needs:

  • Python 3.11 or newer and uv;
  • CMake 3.28 or newer, Ninja, a C++20 compiler, Git, pkg-config, Curl, Make, and Perl;
  • static Boost.Context/Fiber/Thread, OpenSSL, nghttp2, nlohmann-json, and uvw;
  • GoogleTest for the native test build;
  • pybind11 if A11_BUILD_PYTHON=ON in a direct CMake build.

CMake fetches the pinned Abseil version and, when it is not installed, libdatachannel. The latter is only used for WebRTC.

On macOS, a suitable Homebrew setup is:

brew install \
  boost cmake googletest libnghttp2 ninja nlohmann-json openssl@3 \
  pkg-config pybind11 uv uvw

Linux package names vary by distribution. The project can build the main static dependencies reproducibly instead of relying on system packages:

export A11_WHEEL_ARCH="$(uname -m)"
export A11_DEPS_PREFIX="/tmp/a11-editable-deps-${A11_WHEEL_ARCH}"
export CMAKE_PREFIX_PATH="${A11_DEPS_PREFIX}${CMAKE_PREFIX_PATH:+:${CMAKE_PREFIX_PATH}}"
export OPENSSL_ROOT_DIR="${A11_DEPS_PREFIX}"
export PKG_CONFIG_PATH="${A11_DEPS_PREFIX}/lib/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}}"

# Keep this set on macOS so the dependencies and extension have the same
# deployment target.
export MACOSX_DEPLOYMENT_TARGET="${MACOSX_DEPLOYMENT_TARGET:-13.0}"

scripts/bootstrap_wheel_deps.sh

That script builds Boost, OpenSSL, nghttp2, nlohmann-json, and uvw. GoogleTest must still be installed separately for BUILD_TESTING=ON. Keep the exported paths in the shell used for CMake, uv sync, and editable rebuilds.

Editable Python build

Create an environment and install the project in editable mode:

uv venv --python 3.12

export CMAKE_ARGS="-DA11_REQUIRE_STATIC_DEPS=ON -DA11_FETCH_MISSING_DEPS=ON"
uv sync --locked --group dev

Any supported Python from 3.11 onward can replace 3.12. uv sync maps the Python modules directly to a11/, while scikit-build compiles and installs the ABI-specific native modules into .venv. Consequently:

  • edits to .py files are visible to the next Python process immediately;
  • edits to C++ files are not visible until the editable extension is rebuilt.

For an ordinary C++ edit, rebuild and install the extension with the editable loader hook:

.venv/bin/python -c \
  'import a11._native as native; native.__loader__.rebuild()'

Run tests in a new process after this command. The rebuild process imports the old extension to reach its loader, and a loaded native module cannot be replaced within that same process.

The hook only runs cmake --build and cmake --install against the build tree that uv sync already configured under build/editable/<wheel-tag>; it does not configure that tree. When the tree is absent — a fresh clone before the first uv sync, or after build/ was deleted or cleaned (see the note in Native C++ build) — the rebuild fails with:

Error: not a CMake build directory (missing CMakeCache.txt)

Recreating the editable build tree fixes this. The same command is also required after changing pyproject.toml, the CMake install layout, build options, or the Python interpreter, since each invalidates the configured tree or the editable metadata:

uv sync --locked --group dev --reinstall-package a11-kit

--reinstall-package takes the distribution name (a11-kit, from pyproject.toml's [project] name), not the import name (a11). Passing a11 matches nothing, so uv sync silently reports Checked N packages and does not recreate the build tree — the next native.__loader__.rebuild() still fails with the same CMakeCache.txt error. There is no warning when this happens, so always double-check with:

ls build/editable/*/CMakeCache.txt

The active files can be checked without relying on shell activation:

.venv/bin/python - <<'PY'
from pathlib import Path
import a11
import a11._native

root = Path.cwd().resolve()
python_source = Path(a11.__file__).resolve()
native_module = Path(a11._native.__file__).resolve()

print("Python source:", python_source)
print("native module:", native_module)
assert python_source.is_relative_to(root)
PY

It is expected for the editable native module to live under .venv; the explicit rebuild above installs the current C++ output there.

Native C++ build

Use a separate Debug tree for C++ tests. Turning the Python module off here keeps this build independent of the editable extension; the editable workflow above compiles and tests the binding layer separately.

This Debug tree and the editable extension's tree both live under build/ (build/ itself and build/editable/<wheel-tag>, respectively). Removing or cleaning build/ — for example to reconfigure this Debug tree from scratch — therefore also destroys the editable tree, so the next native.__loader__.rebuild() reports a missing CMakeCache.txt. Recreate the editable tree with uv sync --locked --group dev --reinstall-package a11-kit afterward (use the distribution name a11-kit, not the import name a11 — see the note in Editable Python build).

cmake -S . -B build -G Ninja \
  -DCMAKE_BUILD_TYPE=Debug \
  -DBUILD_TESTING=ON \
  -DA11_BUILD_PYTHON=OFF \
  -DA11_REQUIRE_STATIC_DEPS=ON \
  -DA11_FETCH_MISSING_DEPS=ON

cmake --build build -j 8
ctest --test-dir build --output-on-failure

If CMAKE_PREFIX_PATH was not exported, pass the dependency prefix explicitly while configuring:

cmake -S . -B build -G Ninja \
  -DCMAKE_PREFIX_PATH="${A11_DEPS_PREFIX}" \
  -DOPENSSL_ROOT_DIR="${A11_DEPS_PREFIX}" \
  -DCMAKE_BUILD_TYPE=Debug \
  -DBUILD_TESTING=ON \
  -DA11_BUILD_PYTHON=OFF

The native suite consists of thread_test, which exercises the cooperative runtime, and a11_core_test, which aggregates the A11 component tests. A focused test can be run directly with a GoogleTest filter, for example:

build/cpp/thread/thread_test \
  --gtest_filter='ThreadSelectTest.*:ThreadFiberTest.*'

To verify that the installed CMake package can be consumed outside the source tree, run:

scripts/smoke_cmake_install.sh build

When changing toolchains or dependency prefixes, rerun the full configure command above with cmake --fresh in place of cmake. A normal source edit only needs cmake --build.

Testing both layers

pytest alone does not rebuild C++. For a change that touches C++ or a binding, use this sequence:

# 1. Compile and test the C++ implementation.
cmake --build build -j 8
ctest --test-dir build --output-on-failure

# 2. Compile and install that source revision for the editable Python package.
#    This command must finish before pytest starts in its separate process.
#    If it reports a missing CMakeCache.txt, the editable build tree is not
#    configured — recreate it with the reinstall command in "Editable Python
#    build", then rerun this step.
.venv/bin/python -c \
  'import a11._native as native; native.__loader__.rebuild()'

# 3. Exercise the cross-language boundary, then the complete Python contract.
.venv/bin/python -m pytest -q a11/tests/test_native_bindings.py
.venv/bin/python -m pytest -q

# 4. Check exported native targets when public headers or linkage changed.
scripts/smoke_cmake_install.sh build

Use the following minimum checks for each kind of change:

Changed files Required checks
a11/**/*.py Full pytest suite
cpp/thread/** Rebuild; thread_test; editable native rebuild; full pytest
cpp/a11/** Rebuild; a11_core_test; editable native rebuild; full pytest
cpp/python/** Editable native rebuild; native binding tests; full pytest
Public headers or CMake linkage Native suites and install smoke test
pyproject.toml or wheel scripts Editable reinstall and at least one wheel build/audit

Formatting and lock-file checks are:

find cpp -type f \( -name '*.cc' -o -name '*.h' \) \
  -exec clang-format --dry-run --Werror {} +
.venv/bin/python -m black --check a11 scripts
uv lock --check
bash -n scripts/bootstrap_wheel_deps.sh scripts/smoke_cmake_install.sh

Building wheels

The matrix is configured in pyproject.toml and orchestrated by scripts/build_wheels.py:

  • CPython 3.11, 3.12, 3.13, 3.14, and 3.15;
  • macOS x86_64 and arm64;
  • manylinux x86_64 and aarch64.

The wheels are architecture-specific. Do not create universal2 wheels: Boost.Context includes architecture-specific assembly.

Install the development tools first:

uv sync --locked --group dev

macOS wheels are built against the official python.org CPython framework builds, which carry the correct deployment target for portable wheels. cibuildwheel uses them in place and refuses to install them system-wide outside CI, so install each targeted version from python.org before building on macOS — CPython 3.11, 3.12, 3.13, 3.14, and 3.15, under /Library/Frameworks/Python.framework/Versions/. The uv-managed interpreters in .venv cannot stand in for them. Confirm what is present with:

ls /Library/Frameworks/Python.framework/Versions/

To iterate on a subset locally without every framework installed, skip the missing macOS versions (this produces an incomplete matrix, not a release):

CIBW_SKIP="cp311-macosx_* cp314-macosx_*" \
  .venv/bin/python scripts/build_wheels.py --platform macos

Then build the host-required matrix:

.venv/bin/python scripts/build_wheels.py

On macOS, this builds both macOS architectures and both Linux architectures. Docker must be running for Linux builds. On Linux, it builds the Linux matrix only. Building a non-native Linux architecture requires Docker with the appropriate binfmt/QEMU support.

Build only one platform when iterating:

.venv/bin/python scripts/build_wheels.py --platform macos
.venv/bin/python scripts/build_wheels.py --platform linux

Linux cannot build the macOS matrix. An alternative output directory can be selected with --output-dir; the default is dist/:

.venv/bin/python scripts/build_wheels.py \
  --platform linux --output-dir dist/linux

List the builds without compiling them:

.venv/bin/python -m cibuildwheel \
  --print-build-identifiers --platform macos
.venv/bin/python -m cibuildwheel \
  --print-build-identifiers --platform linux

Python 3.15 is enabled through cibuildwheel's cpython-prerelease group until stable images are available. Each platform/architecture gets an isolated static dependency prefix and ABI-specific build/wheel/<wheel-tag> directory, while editable builds use build/editable/<wheel-tag>. A temporary wheel interpreter therefore cannot invalidate the editable rebuild tree, and a native module from one interpreter cannot leak into another wheel.

Every wheel is tested by scripts/audit_wheel.py inside cibuildwheel's clean test environment. The audit:

  • imports a11._native and the Abseil status caster;
  • requires exactly one ABI-specific a11/_native module;
  • rejects universal wheels;
  • rejects non-system dynamic dependencies; and
  • rejects absolute or otherwise non-relocatable RPATH/RUNPATH entries.

Cross-compiled macOS wheels cannot be executed on the opposite host architecture, so their runtime test is skipped there. Run the matrix on both macOS architectures when release policy requires a native execution test for each wheel.

Download files

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

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

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

a11_kit-0.1.2-cp314-cp314-macosx_13_0_x86_64.whl (5.3 MB view details)

Uploaded CPython 3.14macOS 13.0+ x86-64

a11_kit-0.1.2-cp314-cp314-macosx_13_0_arm64.whl (5.4 MB view details)

Uploaded CPython 3.14macOS 13.0+ ARM64

a11_kit-0.1.2-cp313-cp313-macosx_13_0_x86_64.whl (5.3 MB view details)

Uploaded CPython 3.13macOS 13.0+ x86-64

a11_kit-0.1.2-cp313-cp313-macosx_13_0_arm64.whl (5.4 MB view details)

Uploaded CPython 3.13macOS 13.0+ ARM64

a11_kit-0.1.2-cp312-cp312-macosx_13_0_x86_64.whl (5.3 MB view details)

Uploaded CPython 3.12macOS 13.0+ x86-64

a11_kit-0.1.2-cp312-cp312-macosx_13_0_arm64.whl (5.4 MB view details)

Uploaded CPython 3.12macOS 13.0+ ARM64

a11_kit-0.1.2-cp311-cp311-macosx_13_0_x86_64.whl (5.2 MB view details)

Uploaded CPython 3.11macOS 13.0+ x86-64

a11_kit-0.1.2-cp311-cp311-macosx_13_0_arm64.whl (5.3 MB view details)

Uploaded CPython 3.11macOS 13.0+ ARM64

File details

Details for the file a11_kit-0.1.2-cp314-cp314-macosx_13_0_x86_64.whl.

File metadata

File hashes

Hashes for a11_kit-0.1.2-cp314-cp314-macosx_13_0_x86_64.whl
Algorithm Hash digest
SHA256 195a68995979cb765c98b4d4b4a277eaf3277b66ec5a8dcc18daf59d739e8994
MD5 c8a3cffcae32835aaf21bd849dd76db9
BLAKE2b-256 5188c9d2bf9b645328bd5ed38ac8db680603da012fb766f57853fd20f6d081bb

See more details on using hashes here.

File details

Details for the file a11_kit-0.1.2-cp314-cp314-macosx_13_0_arm64.whl.

File metadata

File hashes

Hashes for a11_kit-0.1.2-cp314-cp314-macosx_13_0_arm64.whl
Algorithm Hash digest
SHA256 07bca8145d96ec6083c5503ca7f361280f292f1d27592b8f40c7182ea15b1be0
MD5 a2591168fbcbdca636d9409f38679b0a
BLAKE2b-256 00331cfd809494fee6502fed33f44b46f022cb3df367bc8b3c04390fcc0ce9d6

See more details on using hashes here.

File details

Details for the file a11_kit-0.1.2-cp313-cp313-macosx_13_0_x86_64.whl.

File metadata

File hashes

Hashes for a11_kit-0.1.2-cp313-cp313-macosx_13_0_x86_64.whl
Algorithm Hash digest
SHA256 f419c3122eaa41c175343846e25fdeedc2d1e2118e070e6b6abb34ee65d13682
MD5 ee0907588b387cc417f770bb213aadac
BLAKE2b-256 4c58dbe2fc7dac9a61d729fbbba9b9ba6b3318b34d3a06e53e9093b7ce389ab2

See more details on using hashes here.

File details

Details for the file a11_kit-0.1.2-cp313-cp313-macosx_13_0_arm64.whl.

File metadata

File hashes

Hashes for a11_kit-0.1.2-cp313-cp313-macosx_13_0_arm64.whl
Algorithm Hash digest
SHA256 562b18176441c98dd9bf46fc0747c1fa13a21f5166acbf268605e72686c69440
MD5 4d8934244fd6d13d43f5cda8a25d96c0
BLAKE2b-256 45131e1566bb42593442c72e534e7407899ee0883aeed40e032a7fc0ae40b874

See more details on using hashes here.

File details

Details for the file a11_kit-0.1.2-cp312-cp312-macosx_13_0_x86_64.whl.

File metadata

File hashes

Hashes for a11_kit-0.1.2-cp312-cp312-macosx_13_0_x86_64.whl
Algorithm Hash digest
SHA256 c03051d11106e7d66e3e874998a33f5091abb5e76c49661c23e36570ba313b65
MD5 8f816034d2fd890ec97b6ea55e8a6e36
BLAKE2b-256 e63fbf8353c88306810066494ea6a27723d068f21caa58dd254aa5bb42f06bf1

See more details on using hashes here.

File details

Details for the file a11_kit-0.1.2-cp312-cp312-macosx_13_0_arm64.whl.

File metadata

File hashes

Hashes for a11_kit-0.1.2-cp312-cp312-macosx_13_0_arm64.whl
Algorithm Hash digest
SHA256 feecff7df90367b98384d20527fcf9a29ba9325d6f105993195db71c65eec05c
MD5 ed68d010675d9993600c7aed5e44e488
BLAKE2b-256 f70d3d7b46b0ffb7e6f628205b787f3f906ba24ae343293d58897ae6ed54f7c1

See more details on using hashes here.

File details

Details for the file a11_kit-0.1.2-cp311-cp311-macosx_13_0_x86_64.whl.

File metadata

File hashes

Hashes for a11_kit-0.1.2-cp311-cp311-macosx_13_0_x86_64.whl
Algorithm Hash digest
SHA256 23ac0b80b1a6488f5f62140207faa808e5bad1cf1dda640a39862ee8de941441
MD5 9b58ce1f01eabb633fcc381f27e824b6
BLAKE2b-256 7d90fdbef9fae5e9df29ff6304ee7609dbe24a8c54e96b4582b106d18b4cd50c

See more details on using hashes here.

File details

Details for the file a11_kit-0.1.2-cp311-cp311-macosx_13_0_arm64.whl.

File metadata

File hashes

Hashes for a11_kit-0.1.2-cp311-cp311-macosx_13_0_arm64.whl
Algorithm Hash digest
SHA256 dbed9af4e34e2e1d6c2dbcc1af289ffb978ff9b9f05e0f6be620721746943d53
MD5 41e4f4fa18b0f84f6c2f6d14642f362d
BLAKE2b-256 5479f459512965d2b55e5d7ec0823376f4f5660069c22e3fba855fbf1d18cbe6

See more details on using hashes here.

Release history Release notifications | RSS feed

0.5.6

17 files

0.5.5

17 files

0.5.4

17 files

0.5.3

17 files

0.5.2

17 files

0.5.1

17 files

0.5.0

17 files

0.4.6

17 files

0.4.4

17 files

0.4.2

17 files

0.4.1

17 files

0.3.3

17 files

0.3.2

17 files

0.3.1

17 files

0.3.0

17 files

0.2.5

17 files

0.2.3

17 files

0.2.2

17 files

0.2.1

17 files

0.2.0

17 files

0.1.8

17 files

0.1.7

17 files

0.1.6

17 files

0.1.5

16 files

0.1.4

16 files

0.1.3

8 files

This release

0.1.2 This release

8 files

0.1.1

17 files

0.1.0

3 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