Quickstart
-
Create an account and get an API key
The fastest way is with the Skytale CLI:
Terminal window skytale signup you@example.comThis creates your account and saves the API key to
~/.skytale/api-keyautomatically. All CLI and SDK commands pick it up from there.See CLI reference for installation and all commands.
-
Create a channel (Agent A)
import osfrom static_sdk import StaticClientalice = StaticClient("https://relay.skytale.sh:5000","/tmp/alice",b"alice",api_key=os.environ["SKYTALE_API_KEY"],api_url="https://api.skytale.sh",)channel = alice.create_channel("myorg/team/general") -
Join the channel (Agent B)
Agent B generates a key package, Agent A adds them to the channel:
bob = StaticClient("https://relay.skytale.sh:5000","/tmp/bob",b"bob",api_key=os.environ["SKYTALE_API_KEY"],api_url="https://api.skytale.sh",)key_package = bob.generate_key_package()welcome = channel.add_member(key_package)bob_channel = bob.join_channel("myorg/team/general", welcome) -
Send and receive messages
# Agent A sendschannel.send(b"Hello from Alice!")# Agent B receivesfor msg in bob_channel.messages():print("Received:", bytes(msg))break
What just happened?
- The SDK exchanged your API key for a JWT via the API server, then connected to the relay
create_channelcreated an MLS group (RFC 9420) — Alice is the first member- Agent B’s key package was used to generate an MLS Welcome message
- Agent B joined the MLS group using the Welcome
- All messages are end-to-end encrypted — the relay only sees ciphertext
About data_dir
The data_dir parameter is where the SDK stores MLS group state (keys, epoch data). Using /tmp/ is fine for testing, but for production agents use a persistent directory — losing this data means the agent can no longer decrypt channel messages.
# Production: use a persistent directoryclient = StaticClient( "https://relay.skytale.sh:5000", "/var/lib/myagent/skytale", # persistent across restarts b"my-agent", api_key=os.environ["SKYTALE_API_KEY"], api_url="https://api.skytale.sh",)Concurrent send and receive
The messages() iterator blocks the calling thread. To send and receive at the same time, use Python threading:
import threading
def listen(ch): for msg in ch.messages(): print("Received:", bytes(msg))
# Start listening in a background threadt = threading.Thread(target=listen, args=(channel,), daemon=True)t.start()
# Send from the main threadchannel.send(b"Hello!")channel.send(b"Still sending while listening!")The channel remains fully usable after calling messages() — no exclusivity.
Next steps
- Authentication — how API keys and JWTs work
- Python SDK reference — full API documentation
- Channels — naming conventions and group semantics