Skip to content

Quickstart

Build with an agent

Paste the instruction into your coding harness, or follow the steps below.

Prompt draft
Download .txt
Read the instruction
Build a small Aster Python service and client in the current workspace.

Sources:
- https://sdk.getaster.now/docs/quickstart/python
- https://sdk.getaster.now/docs/bindings/python
- https://github.com/aster-rpc/aster-rpc

Read the linked Python quickstart before writing code. Use a published package
version compatible with that guide, and record the exact Aster and Python
versions you install. If the published package and guide disagree, identify the
mismatch and stop rather than inventing APIs or using private dependencies.

Create an isolated environment and a project containing request and response
types, a HelloService with a say_hello method, a producer, and a consumer. The
producer should print its Aster address. The consumer should take that address
as configuration, call the service with the name World, and print Hello, World!

Use the guide's development configuration for this local demonstration. Do not
describe it as a production authorization setup. Do not open public firewall
ports, commit credentials, or change machine-wide networking settings.

Start the producer locally, capture its actual address, and run the consumer
against it. Confirm the expected response using the real Aster connection. Add
a short README with installation, startup, consumer, and shutdown commands.
Record dependency versions so the project can be reproduced. Stop the processes
you started after verification unless I ask you to keep them running.

Report the files created, installed versions, commands run, observed response,
and any remaining problems. If network access, native package installation, or
execution is unavailable, report that limit; do not claim the example passed.

This prompt is a draft for the documentation design preview and has not yet been
validated in a coding harness.

This instruction has not yet been tested in a harness. It is included here to review the tutorial format.

Write a service on one machine, call it from another – even if they’re on different networks, behind firewalls, with no shared infrastructure between them. In under two minutes.

  • Python 3.9 – 3.13 (3.14+ is not yet supported)
  • pip, uv, or any PEP 517 installer
Terminal window
pip install aster-rpc

Or with uv:

Terminal window
uv pip install aster-rpc

A service is a class that exposes one or more methods callable by remote consumers. You write it like a regular class; Aster handles the wire format, transport, and remote dispatch.

Create hello_service.py:

from dataclasses import dataclass
from aster import service, rpc
@dataclass
class HelloRequest:
name: str = ""
@dataclass
class HelloResponse:
message: str = ""
@service
class HelloService:
@rpc
async def say_hello(self, req: HelloRequest) -> HelloResponse:
return HelloResponse(message=f"Hello, {req.name}!")

Three decorators: @dataclass (standard Python), @service (marks the class as an Aster service), @rpc (marks a method as a callable endpoint). No schema files, no code generation, no base classes. Wire tags are auto-derived from the class names; for production cross-language services you’ll add explicit @wire_type("ns/Type") decorators – see Defining Services and Types.

A producer is the node that hosts the service.

Create producer.py:

import asyncio
from hello_service import HelloService
from aster import AsterServer
async def main():
async with AsterServer(services=[HelloService()]) as srv:
print("Producer ready at:", srv.address)
await srv.serve()
asyncio.run(main())
Terminal window
python producer.py

In dev mode (no ASTER_* environment variables set), the server:

  • Generates an ephemeral root key and node identity (no files needed).
  • Opens the consumer gate so consumers can connect without credentials.
  • Serves RPC, blobs, docs, and gossip on a single endpoint.
  • Prints an aster1... address for consumers to connect to.

A consumer is the node that calls into a producer’s services. Consumers don’t need access to the service’s source code – they discover methods from the producer’s published contract at runtime, then call them by name.

The producer and consumer don’t have to live on the same machine, or even the same network. Your producer might be in a cloud environment behind a corporate firewall; your consumer might be on your laptop on coffee shop Wi-Fi, or on a Raspberry Pi behind your home router, or on a phone tethered to a 5G connection. No VPN to set up, no firewall rule to add, no port to forward, no DNS entry to register. The address the consumer uses is the producer’s public key – Aster figures out the network path between them, direct if it can and relayed if it has to.

Create consumer.py:

import asyncio
from aster import AsterClient
async def main():
async with AsterClient() as c:
# The dynamic proxy speaks JSON and needs no local type definitions --
# methods are discovered from the producer's published contract.
hello = c.proxy("HelloService")
resp = await hello.say_hello({"name": "World"})
print(resp["message"]) # Hello, World!
asyncio.run(main())

Run it, passing the producer’s address:

Terminal window
# macOS / Linux
ASTER_ENDPOINT_ADDR=<paste from producer output> python consumer.py
Terminal window
# Windows (PowerShell)
$env:ASTER_ENDPOINT_ADDR="<paste from producer output>"; python consumer.py

AsterClient reads ASTER_ENDPOINT_ADDR from the environment and connects to the producer. c.proxy("HelloService") returns a dynamic stub – call methods on it like regular async functions. If you’d rather have typed classes (for IDE autocomplete and static checking), share the service definition module between producer and consumer and use c.client(HelloService) instead – see Defining Services and Types.

Three steps, three things to notice:

  1. The producer is a server process holding HelloService. When it starts, it prints an aster1... address. That address is the node’s public key, not a hostname or an IP – it’s stable, globally unique, and can’t be impersonated.

  2. The consumer connects by that public key. No DNS lookup, no port forwarding, no certificate to trust. The consumer doesn’t even need a copy of the service source code – it asks the producer what methods exist and builds a stub at runtime.

  3. The producer and consumer don’t have to be on the same machine, or even the same network. In this quickstart they’re both on your laptop because that’s the simplest demo. But the address is a public key, so you can run the producer on your homelab, your VPS, or a Raspberry Pi behind your home router, and call it from your laptop on coffee shop Wi-Fi without changing a single line of code. Aster handles NAT traversal and chooses the best network path – direct if it can, relayed if it has to.

To try this for real, run producer.py on one machine and consumer.py on another. Copy the aster1... address from the producer’s output, paste it into the consumer’s ASTER_ENDPOINT_ADDR, and the call will arrive over whatever network path actually exists between the two machines. No tunnels, no proxies, no shared secrets.

Build a real service end-to-end with the Mission Control walkthrough – 30 minutes, six chapters, four streaming patterns, capability-scoped auth, cross-language interop, and a working MCP agent demo at the end.