Python
Python is the reference implementation for Aster. It provides the full RPC framework, trust model, and iroh networking stack as an async Python library.
Status
Section titled “Status”Shipping 0.1.2 on PyPI as aster-rpc. The Python binding is the first-class implementation and defines the reference behavior for cross-language interop. All features documented on this site are available in Python.
Installation
Section titled “Installation”pip install aster-rpc # frameworkpip install aster-cli # optional: shell, contract gen, trust commandsRequirements: Python 3.9 – 3.13, macOS / Linux / Windows.
The package includes a native extension (compiled Rust via PyO3), so wheels are provided for common platforms. Building from source requires a Rust toolchain and maturin.
Quick example
Section titled “Quick example”import asynciofrom dataclasses import dataclassfrom aster import AsterServer, AsterClient, service, rpc
@dataclassclass HelloRequest: name: str = ""
@dataclassclass HelloResponse: message: str = ""
@serviceclass HelloService: @rpc async def say_hello(self, req: HelloRequest) -> HelloResponse: return HelloResponse(message=f"Hello, {req.name}!")
async def main(): # Producer async with AsterServer(services=[HelloService()]) as srv: addr = srv.address
# Consumer async with AsterClient(address=addr) as client: hello = await client.client(HelloService) resp = await hello.say_hello(HelloRequest(name="World")) print(resp.message) # "Hello, World!"
asyncio.run(main())API surface
Section titled “API surface”Decorators
Section titled “Decorators”Define services and methods with decorators on plain Python classes:
| Decorator | Purpose |
|---|---|
@service |
Mark a class as an Aster RPC service. |
@rpc |
Unary RPC method. |
@server_stream |
Server-streaming method (async generator). |
@client_stream |
Client-streaming method. |
@bidi_stream |
Bidirectional streaming method. |
@wire_type("ns/Type") |
Stable wire identity for a dataclass. |
Server
Section titled “Server”| API | Purpose |
|---|---|
AsterServer(services=[...]) |
High-level declarative producer. Handles admission, hooks, and ALPN routing. |
Server(endpoint, services=[...]) |
Lower-level server. Manual endpoint and connection management. |
Client
Section titled “Client”| API | Purpose |
|---|---|
AsterClient(address="aster1...") |
High-level declarative consumer. Handles admission and service discovery. |
create_client(ServiceClass, connection=conn) |
Lower-level client. Wraps an existing QUIC connection. |
Configuration
Section titled “Configuration”| API | Purpose |
|---|---|
AsterConfig |
Unified configuration dataclass. Loads from env vars, TOML files, or code. |
AsterConfig.from_env() |
Build config from ASTER_* environment variables. |
AsterConfig.from_file("aster.toml") |
Build config from TOML file with env overrides. |
config.print_config() |
Display resolved config with provenance. |
| API | Purpose |
|---|---|
generate_root_keypair() |
Generate an ed25519 root keypair (offline use). |
sign_credential(...) |
Sign an enrollment credential with the root private key. |
ConsumerEnrollmentCredential |
Dataclass representing a signed enrollment token. |
Interceptors
Section titled “Interceptors”Built-in middleware chain:
| Interceptor | Purpose |
|---|---|
DeadlineInterceptor |
Enforce and propagate call deadlines. |
AuthInterceptor |
Token-based authentication. |
RetryInterceptor |
Automatic retry for idempotent methods. |
CircuitBreakerInterceptor |
Circuit breaker pattern for failing endpoints. |
AuditLogInterceptor |
Log all RPC calls for audit. |
MetricsInterceptor |
Collect call latency and error metrics. |
CapabilityInterceptor |
Enforce requires capability checks. |
Sessions
Section titled “Sessions”| API | Purpose |
|---|---|
@service(scoped="session") |
Producer-side: per-connection service instances (the class __init__ receives a peer argument). |
await client.session("ServiceName") |
Consumer-side: open a multiplexed session against a session-scoped service. Returns a SessionProxyClient whose method calls share one bidi stream. |
Architecture
Section titled “Architecture”The Python binding is structured as a four-layer stack:
Python (aster package) Pure Python: decorators, server, client, codec, interceptors, trust, sessions | | PyO3 vRust bindings (PyO3) Thin wrappers exposing async methods as Python awaitables | vcore crate (Rust) Authoritative backend: all transport logic, QUIC endpoint management | viroh crates iroh, iroh-blobs, iroh-docs, iroh-gossipThe PyO3 module starts a single shared Tokio runtime. All async Rust functions are bridged to Python awaitables via pyo3-async-runtimes. The Python layer uses asyncio for all async operations.
Testing
Section titled “Testing”Tests use pytest with pytest-asyncio (auto mode):
pip install pytest pytest-asyncio pytest-timeoutpytest tests/python/ -v --timeout=30The conftest.py provides fixtures for common setups: node, node_pair, endpoint_pair.
Further reading
Section titled “Further reading”- Hello Service – complete walkthrough of the simplest service
- Define a Service – decorators, wire types, streaming, sessions
- Dial a Service – connecting, admission, error handling
- Configuration – full AsterConfig reference
- CLI Reference – command-line tools