Python SDK for Pilot Protocol - the network stack for AI agents
Project description
Pilot Protocol Python SDK
Python client library for the Pilot Protocol network — giving AI agents permanent addresses, encrypted P2P channels, and a trust model.
Architecture
Single Source of Truth: The Go pkg/driver package is compiled into a
C-shared library (libpilot.so / .dylib / .dll) and called from Python
via ctypes. Zero protocol reimplementation — every SDK call goes through the
same Go code the CLI uses.
┌─────────────┐ ctypes/FFI ┌──────────────┐ Unix socket ┌────────┐
│ Python SDK │ ───────────────► │ libpilot.so │ ─────────────────► │ Daemon │
│ (client.py)│ │ (Go c-shared)│ │ │
└─────────────┘ └──────────────┘ └────────┘
Installation
pip install pilotprotocol
The installation process will automatically:
- Install the Python SDK package
- Download and install the Pilot Protocol daemon (
pilotctl,pilot-daemon,pilot-gateway) - Set up the daemon as a system service (systemd on Linux, launchd on macOS)
- Configure the default rendezvous server
Platform Support:
- Linux (x86_64, arm64)
- macOS (Intel, Apple Silicon)
- Windows (x86_64) - experimental
How It Works
When you run pip install pilotprotocol:
- The wheel is downloaded and extracted to your Python environment
- Entry points create console scripts:
pilotctl,pilot-daemon,pilot-gateway - Binaries are bundled in the package at
site-packages/pilotprotocol/bin/ - On first command execution,
~/.pilot/config.jsonis automatically created
Binary Library
The SDK includes pre-built libpilot shared libraries for each platform. The library is automatically discovered at runtime from:
~/.pilot/bin/(pip install location via entry points)- The installed package directory (bundled in wheel)
PILOT_LIB_PATHenvironment variable (if set)- Development layout:
<project_root>/bin/ - System library search path
Quick Start
from pilotprotocol import Driver
# The daemon should already be running if installed via pip
# If not, start it: pilotctl daemon start --hostname my-agent
# Connect to local daemon
with Driver() as d:
info = d.info()
print(f"Address: {info['address']}")
print(f"Hostname: {info.get('hostname', 'none')}")
# Set hostname
d.set_hostname("my-python-agent")
# Discover a peer (requires mutual trust)
peer = d.resolve_hostname("other-agent")
print(f"Found peer: {peer['address']}")
# Open a stream connection
with d.dial(f"{peer['address']}:1000") as conn:
conn.write(b"Hello from Python!")
response = conn.read(4096)
print(f"Got: {response}")
First Time Setup
After installation, verify the daemon is running:
pilotctl daemon status
# If not running, start it:
pilotctl daemon start --hostname my-agent
# Check your node info:
pilotctl info
Features
- Single Source of Truth — Go driver compiled as C-shared library
- Synchronous API — No async/await needed; simple blocking calls
- Type safe — Full type hints throughout
- Zero Python dependencies — Only
ctypes(stdlib) + the shared library - Complete API — All daemon commands: info, trust, streams, datagrams
- Context managers —
Driver,Conn, andListenerall supportwith - Cross-platform — Linux (.so), macOS (.dylib), Windows (.dll)
Prerequisites
The daemon should be automatically installed and started when you pip install pilotprotocol.
To verify:
pilotctl daemon status
pilotctl info
If the daemon isn't running:
pilotctl daemon start --hostname my-agent
API Overview
Connection
from pilotprotocol import Driver
# Default socket path
d = Driver()
# Custom socket path
d = Driver("/custom/path/pilot.sock")
# Context manager auto-closes
with Driver() as d:
# ... use driver
Identity & Discovery
info = d.info()
# Returns: {"address": "0:0000.0000.0005", "hostname": "...", ...}
d.set_hostname("my-agent")
d.set_visibility(public=True)
d.set_tags(["python", "ml", "api"])
peer = d.resolve_hostname("other-agent")
# Returns: {"node_id": 7, "address": "0:0000.0000.0007"}
Trust Management
d.handshake(peer_node_id, "collaboration request")
pending = d.pending_handshakes()
d.approve_handshake(node_id)
d.reject_handshake(node_id, "reason")
trusted = d.trusted_peers()
d.revoke_trust(node_id)
Stream Connections
# Client: dial a remote address
with d.dial("0:0001.0000.0002:8080") as conn:
conn.write(b"Hello!")
data = conn.read(4096)
# Server: listen on a port
with d.listen(8080) as ln:
with ln.accept() as conn:
data = conn.read(4096)
conn.write(b"Echo: " + data)
Unreliable Datagrams
# Send datagram (addr format: "N:XXXX.YYYY.YYYY:PORT")
d.send_to("0:0001.0000.0002:9090", b"fire and forget")
# Receive next datagram (blocks)
dg = d.recv_from()
# Returns: {"src_addr": "...", "src_port": 8080, "dst_port": 9090, "data": ...}
Data Exchange Service (Port 1001)
# Send a message (text, JSON, or binary)
result = d.send_message("other-agent", b"hello", msg_type="text")
# Returns: {"sent": 5, "type": "text", "target": "0:0001.0000.0002", "ack": "..."}
# Send a file
result = d.send_file("other-agent", "/path/to/file.txt")
# Returns: {"sent": 1234, "filename": "file.txt", "target": "0:0001.0000.0002", "ack": "..."}
Event Stream Service (Port 1002)
# Publish an event
result = d.publish_event("other-agent", "sensor/temperature", b'{"temp": 25.5}')
# Returns: {"status": "published", "topic": "sensor/temperature", "bytes": 15}
# Subscribe to events (generator)
for topic, data in d.subscribe_event("other-agent", "sensor/*", timeout=30):
print(f"{topic}: {data}")
# Subscribe with callback
def handle_event(topic, data):
print(f"Event: {topic} -> {data}")
d.subscribe_event("other-agent", "*", callback=handle_event, timeout=30)
Task Submit Service (Port 1003)
# Submit a task for execution
task = {
"task_description": "process data",
"parameters": {"input": "data.csv"}
}
result = d.submit_task("other-agent", task)
# Returns: {"status": 200, "task_id": "...", "message": "Task accepted"}
Configuration
d.set_webhook("http://localhost:8080/events")
d.set_task_exec(enabled=True)
d.deregister()
d.disconnect(conn_id)
Error Handling
from pilotprotocol import Driver, PilotError
try:
with Driver() as d:
peer = d.resolve_hostname("unknown")
except PilotError as e:
print(f"Pilot error: {e}")
All errors from the Go layer are raised as PilotError.
Library Discovery
The SDK searches for libpilot.{so,dylib,dll} in this order:
PILOT_LIB_PATHenvironment variable (explicit path)- Same directory as
client.py(pip wheel layout) <project_root>/bin/(development layout)- System library search path
Examples
See examples/python_sdk/ for comprehensive examples:
basic_usage.py— Connection, identity, trust managementdata_exchange_demo.py— Send messages, files, JSONevent_stream_demo.py— Pub/sub patternstask_submit_demo.py— Task delegation and polo scorepydantic_ai_agent.py— PydanticAI integration with function toolspydantic_ai_multiagent.py— Multi-agent collaboration system
Testing
cd sdk/python
python -m pytest tests/ -v
61 tests cover all wrapper methods, error handling, and library discovery.
Development
See CONTRIBUTING.md for:
- Repository structure
- Development setup
- Testing guidelines
- Building and publishing to PyPI
- Code quality standards
Quick commands:
make install-dev # Install with dev dependencies
make test # Run tests
make test-coverage # Run tests with coverage
make coverage-badge # Generate coverage badge
make build # Build wheel and sdist
make publish-test # Publish to TestPyPI
Documentation
- Examples:
examples/python_sdk/README.md - CLI Reference:
examples/cli/BASIC_USAGE.md - Protocol Spec:
docs/SPEC.md - Agent Skills:
docs/SKILLS.md
License
AGPL-3.0 — See LICENSE file
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pilotprotocol-0.1.0.tar.gz.
File metadata
- Download URL: pilotprotocol-0.1.0.tar.gz
- Upload date:
- Size: 8.8 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c0d709d5ee2b4a182935e1942253f4044056f887627d246723eb5a87fe39847d
|
|
| MD5 |
30f6e08e0c7c1bd9b1485065f7d7e7cf
|
|
| BLAKE2b-256 |
68cd67ae69a65b317dac0e75a3eb508a86cf4ee715d8653820b2ee11caed7d93
|
File details
Details for the file pilotprotocol-0.1.0-cp311-cp311-manylinux_2_34_x86_64.manylinux_2_35_x86_64.whl.
File metadata
- Download URL: pilotprotocol-0.1.0-cp311-cp311-manylinux_2_34_x86_64.manylinux_2_35_x86_64.whl
- Upload date:
- Size: 8.9 MB
- Tags: CPython 3.11, manylinux: glibc 2.34+ x86-64, manylinux: glibc 2.35+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
93d4167c99863aa7002093274d668c09506f1a917d3fea4d58a264e49d08683c
|
|
| MD5 |
f03beb6b27050cab7a01257521140eed
|
|
| BLAKE2b-256 |
6c56e5ea7c1c8972ab66e3790c445d5a6e0364f9852fadd0b00d55949ecf5ff7
|
File details
Details for the file pilotprotocol-0.1.0-cp311-cp311-macosx_15_0_universal2.whl.
File metadata
- Download URL: pilotprotocol-0.1.0-cp311-cp311-macosx_15_0_universal2.whl
- Upload date:
- Size: 8.2 MB
- Tags: CPython 3.11, macOS 15.0+ universal2 (ARM64, x86-64)
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fec50e26b6a1b835d7a5046c34533a8359e1cf48cb59ddb2edc0cd94c49a7760
|
|
| MD5 |
9f1752a6ac54b16962829f1eab6cef0d
|
|
| BLAKE2b-256 |
48c3344f12210e58ce7c8fef75aca20eaaa1b4c157ac3881afdce7e4bcde718e
|