Rust SDK (floopy-sdk)
Overview
Section titled “Overview”floopy-sdk is the official Floopy SDK for Rust. It wraps the official async-openai crate and points it at the Floopy gateway, so chat/embeddings/models stay a 1:1 drop-in while Floopy-only features (audit, experiments, constraints, decision export, feedback, routing dry-run, sessions) get first-class typed async methods.
Prefer the zero-SDK approach? The Rust page shows how to use the raw async-openai crate with Floopy headers. Use floopy-sdk when you also want the typed Floopy resources and a single client for both.
The crate is published as floopy-sdk and imported as floopy. It is fully async (Tokio). Requires Rust >= 1.82.
Installation
Section titled “Installation”cargo add floopy-sdk async-openai tokio --features tokio/macros,tokio/rt-multi-threadasync-openai is re-exported as floopy::async_openai, so you can also depend on floopy-sdk alone and reach the request/response types through it.
Quick start
Section titled “Quick start”use floopy::Floopy;use floopy::async_openai::types::chat::{ ChatCompletionRequestUserMessageArgs, CreateChatCompletionRequestArgs,};
#[tokio::main]async fn main() -> Result<(), Box<dyn std::error::Error>> { let client = Floopy::new(std::env::var("FLOOPY_API_KEY")?)?;
let request = CreateChatCompletionRequestArgs::default() .model("gpt-4o") .messages(vec![ChatCompletionRequestUserMessageArgs::default() .content("Hello from Floopy!") .build()? .into()]) .build()?;
let response = client.openai().chat().create(request).await?; println!("{:?}", response.choices[0].message.content); Ok(())}Set FLOOPY_API_KEY in your environment. You can create one in the dashboard.
Migrating from async-openai
Section titled “Migrating from async-openai”use async_openai::{Client, config::OpenAIConfig};let client = Client::with_config( OpenAIConfig::new().with_api_key(std::env::var("OPENAI_API_KEY")?),);use floopy::Floopy;let fl = Floopy::new(std::env::var("FLOOPY_API_KEY")?)?;let client = fl.openai();
let response = client.chat().create(request).await?;client.openai() returns a lazily-built async_openai::Client pre-pointed at the gateway, so types and runtime behaviour are identical. Upstream updates reach you on cargo update without forks or parity drift.
Floopy options
Section titled “Floopy options”FloopyOptions map to Floopy-* headers and are forwarded to every request (both OpenAI-compat calls and Floopy-only ones). Per-call overrides go through a trailing RequestOptions argument on every resource method.
use floopy::{Floopy, FloopyOptions, CacheOptions};
let client = Floopy::builder(std::env::var("FLOOPY_API_KEY")?) .options(FloopyOptions { cache: Some(CacheOptions { enabled: Some(true), bucket_max_size: Some(3) }), prompt_id: Some("cd4249d5-44d5-46c8-8961-9eb3861e1f7e".into()), prompt_version: Some("1".into()), llm_security_enabled: Some(true), }) .build()?;| Option | Header | Purpose |
|---|---|---|
cache.enabled | Floopy-Cache-Enabled | Toggle exact + semantic cache |
cache.bucket_max_size | Floopy-Cache-Bucket-Max-Size | Max entries per semantic bucket |
prompt_id | Floopy-Prompt-Id | Stored prompt to resolve |
prompt_version | Floopy-Prompt-Version | Pinned version for prompt_id |
llm_security_enabled | floopy-llm-security-enabled | LLM firewall pre-check |
See the Headers Reference for the full list.
Floopy-only resources
Section titled “Floopy-only resources”Each resource maps to a public /v1/* gateway endpoint and is typed end-to-end. Pagination and export are futures::Streams.
use floopy::types::*;use futures::StreamExt;
// Feedbackclient.feedback().submit( FeedbackSubmitParams { score: 9, useful: true, session_id: None }, None,).await?;
// Decisions (paginated Streams)let d = client.decisions().get("req_123", None).await?;let stream = client.decisions().iter(DecisionListParams::default(), None);futures::pin_mut!(stream);while let Some(decision) = stream.next().await { let _ = decision?; }
// Experiments (auto X-Floopy-Confirm: experiments header)let exp = client.experiments().create(ExperimentCreateParams { name: "cost-vs-quality".into(), variant_a_routing_rule_id: "rule_a".into(), variant_b_routing_rule_id: "rule_b".into(), description: None, split_percentage: None,}, None).await?;client.experiments().rollback(&exp.id, None).await?;
// Constraints (full-replace PUT)client.constraints().put( &OrgConstraints { cost_limit_monthly_usd: Some(100.0), ..Default::default() }, None,).await?;
// Export (streamed JSONL + trailer)let mut export = client.export() .decisions_with_trailer(ExportDecisionsParams::new("a", "b"), None);while let Some(row) = export.next().await { let _ = row?; }println!("{:?}", export.trailer());
// Evaluationslet run = client.evaluations().create(EvaluationCreateParams { dataset_id: "ds_1".into(), model: "gpt-4o".into(), prompt_id: None, config: None,}, None).await?;
// Routing dry-run (Pro plan)let explain = client.routing() .explain(RoutingExplainParams::new("gpt-4o", vec![]), None).await?;
// Sessions — restore a stored conversationlet session = client.sessions().get("sess_1", None).await?;Error handling
Section titled “Error handling”Every Floopy-only call returns Result<T, floopy::Error>:
use floopy::{Error, Floopy};use floopy::types::DecisionListParams;
match client.decisions().list(&DecisionListParams::default(), None).await { Ok(page) => { /* ... */ } Err(Error::RateLimit(d)) => { let secs = d.retry_after_seconds.unwrap_or(1); tokio::time::sleep(std::time::Duration::from_secs(secs)).await; } Err(Error::Plan(d)) => eprintln!("upgrade plan: feature {:?} not in plan", d.feature), Err(e) => eprintln!("{e}"),}Error::status(), Error::request_id(), Error::feature() and Error::retry_after_seconds() are available on every variant. Errors from chat/embeddings are emitted by async-openai (async_openai::error::OpenAIError), not this crate.
Security
Section titled “Security”- The API key is only ever sent in the
Authorizationheader and is never rendered byDebug; the SDK never logs request or response bodies. - TLS certificate verification is on by default (rustls + webpki-roots).
- Releases are published to crates.io via Trusted Publishing (OIDC) — no long-lived registry token in the publishing path.
See the Security guide for gateway-side controls.
- crates.io: https://crates.io/crates/floopy-sdk
- API docs: https://docs.rs/floopy-sdk
- Source + full README: https://github.com/FloopyAI/floopy-rust
- Zero-SDK alternative: Rust
- API reference: API Reference