Skip to Content
Rust

Last Updated: 3/5/2026


Rust Client

A Rust client for interacting with the Pie server.

Installation

Add to your Cargo.toml:

[dependencies] pie-client = "0.1" tokio = { version = "1", features = ["full"] } anyhow = "1"

Quick Start

use pie_client::{Client, InstanceEvent}; use anyhow::Result; #[tokio::main] async fn main() -> Result<()> { // Connect to server let client = Client::connect("ws://127.0.0.1:8080").await?; // Authenticate client.authenticate("username", &None).await?; // Launch an inferlet from registry let mut instance = client.launch_instance_from_registry( "text-completion".to_string(), vec!["--prompt".to_string(), "Hello, world!".to_string()], false, // not detached ).await?; // Receive output loop { match instance.recv().await? { InstanceEvent::Stdout(text) => print!("{}", text), InstanceEvent::Completed(_) => break, InstanceEvent::Exception(msg) => { eprintln!("Error: {}", msg); break; } _ => {} } } client.close()?; Ok(()) }

Client

The main client struct for connecting to a Pie server.

Construction

let client = Client::connect("ws://127.0.0.1:8080").await?;

Methods

MethodReturnsDescription
connect(ws_host)Result<Client>Connect to server
close(self)Result<()>Close connection
authenticate(username, key)Result<()>Authenticate with server
internal_authenticate(token)Result<()>Internal token auth
upload_program(bytes)Result<()>Upload WASM program
program_exists(hash)Result<bool>Check if program exists
launch_instance(hash, args, detached)Result<Instance>Launch by hash
launch_instance_from_registry(name, args, detached)Result<Instance>Launch from registry
attach_instance(id)Result<Instance>Attach to existing
list_instances()Result<Vec<InstanceInfo>>List instances
terminate_instance(id)Result<()>Terminate instance
ping()Result<()>Check connectivity

Authentication

use pie_client::crypto::ParsedPrivateKey; // With SSH key let key = ParsedPrivateKey::from_file("~/.ssh/id_ed25519")?; client.authenticate("username", &Some(key)).await?; // Without key (when server auth is disabled) client.authenticate("username", &None).await?;

Instance

Represents a running program instance.

Methods

MethodReturnsDescription
id()InstanceIdGet instance ID
send(message)Result<()>Send string message
upload_blob(bytes)Result<()>Upload binary data
recv()Result<InstanceEvent>Receive next event

Example

let mut instance = client.launch_instance_from_registry( "chat".to_string(), vec![], false, ).await?; // Send a message instance.send("What is 2 + 2?")?; // Receive response match instance.recv().await? { InstanceEvent::Message(text) => println!("{}", text), InstanceEvent::Stdout(text) => print!("{}", text), _ => {} }

InstanceEvent

Events received from instances:

pub enum InstanceEvent { /// Text message from instance Message(String), /// Instance completed successfully Completed(String), /// Instance was aborted Aborted(String), /// Instance raised an exception Exception(String), /// Server-side error ServerError(String), /// Resource limit reached OutOfResources(String), /// Binary data Blob(Vec<u8>), /// Streaming stdout Stdout(String), /// Streaming stderr Stderr(String), }

Pattern Matching

loop { match instance.recv().await? { InstanceEvent::Stdout(text) => { print!("{}", text); std::io::stdout().flush()?; } InstanceEvent::Stderr(text) => { eprint!("{}", text); } InstanceEvent::Completed(msg) => { println!("\nCompleted: {}", msg); break; } InstanceEvent::Exception(err) => { return Err(anyhow!("Inferlet error: {}", err)); } InstanceEvent::ServerError(err) => { return Err(anyhow!("Server error: {}", err)); } _ => {} } }

Upload Custom Inferlet

use pie_client::hash_blob; // Read and upload let wasm_bytes = std::fs::read("my_inferlet.wasm")?; client.upload_program(&wasm_bytes).await?; // Get hash for launching let program_hash = hash_blob(&wasm_bytes); // Launch let mut instance = client.launch_instance( program_hash, vec!["--arg".to_string(), "value".to_string()], false, ).await?;

Detached Instances

// Launch detached let instance = client.launch_instance_from_registry( "long-task".to_string(), vec![], true, // detached ).await?; let instance_id = instance.id(); // Later, reattach let mut attached = client.attach_instance(&instance_id.to_string()).await?; let event = attached.recv().await?;

Error Handling

use anyhow::{Result, Context}; async fn run() -> Result<()> { let client = Client::connect("ws://127.0.0.1:8080") .await .context("Failed to connect to Pie server")?; client.authenticate("username", &None) .await .context("Authentication failed")?; // ... Ok(()) }

Thread Safety

The Client is thread-safe and can be shared across tasks:

use std::sync::Arc; let client = Arc::new(Client::connect("ws://127.0.0.1:8080").await?); let c1 = client.clone(); let h1 = tokio::spawn(async move { // Use c1 }); let c2 = client.clone(); let h2 = tokio::spawn(async move { // Use c2 }); h1.await?; h2.await?;