This guide is for teams embedding Pi as a Rust library and migrating from the TypeScript SDK surface.
[dependencies]
pi = { path = "." }
futures = "0.3"| TypeScript surface | Rust SDK surface |
|---|---|
createAgentSession(options) |
pi::sdk::create_agent_session(SessionOptions) |
session.prompt(text, onEvent) |
AgentSessionHandle::prompt(text, on_event) |
session.subscribe(listener) |
AgentSessionHandle::subscribe(listener) |
unsubscribe() |
AgentSessionHandle::unsubscribe(subscription_id) |
session.setModel(provider, model) |
AgentSessionHandle::set_model(provider, model) |
session.setThinkingLevel(level) |
AgentSessionHandle::set_thinking_level(level) |
session.compact() |
AgentSessionHandle::compact(on_event) |
session.abort() |
AgentSessionHandle::new_abort_handle() + prompt_with_abort(...) |
session.steer(...), session.followUp(...) |
RpcTransportClient::steer(...), RpcTransportClient::follow_up(...) |
| RPC bridge client | RpcTransportClient / SessionTransport::RpcSubprocess |
use futures::executor::block_on;
use pi::sdk::{AgentEvent, SessionOptions, create_agent_session};
fn main() -> pi::sdk::Result<()> {
let mut session = block_on(create_agent_session(SessionOptions {
provider: Some("openai".to_string()),
model: Some("gpt-4o".to_string()),
api_key: Some(std::env::var("OPENAI_API_KEY").unwrap_or_default()),
no_session: true,
..SessionOptions::default()
}))?;
let message = block_on(session.prompt("Summarize src/sdk.rs", |event: AgentEvent| {
eprintln!("{event:?}");
}))?;
println!("{message:#?}");
Ok(())
}use futures::executor::block_on;
use pi::sdk::{SessionOptions, create_agent_session};
use std::sync::Arc;
fn main() -> pi::sdk::Result<()> {
let options = SessionOptions {
on_tool_start: Some(Arc::new(|tool, args| eprintln!("tool start: {tool} {args}"))),
on_tool_end: Some(Arc::new(|tool, output, is_error| {
eprintln!("tool end: {tool}, error={is_error}, output={output:?}");
})),
on_stream_event: Some(Arc::new(|ev| eprintln!("stream: {ev:?}"))),
..SessionOptions::default()
};
let mut session = block_on(create_agent_session(options))?;
let sub_id = session.subscribe(|event| eprintln!("session event: {event:?}"));
let _ = block_on(session.prompt("read Cargo.toml", |_| {}))?;
let _removed = session.unsubscribe(sub_id);
Ok(())
}use futures::executor::block_on;
use pi::sdk::{AgentSessionHandle, SessionOptions, create_agent_session};
fn main() -> pi::sdk::Result<()> {
let mut session = block_on(create_agent_session(SessionOptions::default()))?;
let (abort_handle, abort_signal) = AgentSessionHandle::new_abort_handle();
let fut = session.prompt_with_abort("long running prompt", abort_signal, |_| {});
abort_handle.abort();
let _ = block_on(fut);
Ok(())
}use futures::executor::block_on;
use pi::model::ThinkingLevel;
use pi::sdk::{SessionOptions, create_agent_session};
fn main() -> pi::sdk::Result<()> {
let mut session = block_on(create_agent_session(SessionOptions::default()))?;
block_on(session.set_model("openai", "gpt-4o"))?;
block_on(session.set_thinking_level(ThinkingLevel::Low))?;
let state = block_on(session.state())?;
println!("provider={} model={}", state.provider, state.model_id);
Ok(())
}use futures::executor::block_on;
use pi::sdk::{SessionOptions, create_agent_session};
use std::path::PathBuf;
fn main() -> pi::sdk::Result<()> {
let session = block_on(create_agent_session(SessionOptions {
extension_paths: vec![PathBuf::from("extensions/my_extension.js")],
extension_policy: Some("safe".to_string()),
repair_policy: Some("ask".to_string()),
..SessionOptions::default()
}))?;
if session.has_extensions() {
eprintln!("extensions loaded");
}
Ok(())
}use futures::executor::block_on;
use pi::sdk::{RpcTransportClient, RpcTransportOptions};
fn main() -> pi::sdk::Result<()> {
let mut rpc = RpcTransportClient::connect(RpcTransportOptions::default())?;
let state = block_on(rpc.get_state())?;
println!("rpc session id: {}", state.session_id);
let events = block_on(rpc.prompt("Hello from RPC"))?;
println!("received {} rpc events", events.len());
rpc.shutdown()?;
Ok(())
}use futures::executor::block_on;
use pi::sdk::{SessionOptions, SessionTransport};
fn main() -> pi::sdk::Result<()> {
let mut transport = block_on(SessionTransport::in_process(SessionOptions::default()))?;
let _result = block_on(transport.prompt("Status?", |_event| {}))?;
let _state = block_on(transport.state())?;
transport.shutdown()?;
Ok(())
}SessionOptions::default().no_sessionistrue(ephemeral by default).- In-process
AgentSessionHandlecurrently exposes prompt/state/model/thinking/compaction flows; queue controls likesteer/follow_upare onRpcTransportClient. SessionTransport::promptreturnsSessionPromptResult, which isInProcess(AssistantMessage)orRpcEvents(Vec<Value>)depending on backend.- Extension loading is opt-in via
extension_paths, withextension_policy/repair_policycontrols.
src/sdk.rstests/sdk_api.rstests/sdk_unit.rstests/sdk_integration.rs