Documentation Index
Fetch the complete documentation index at: https://raindrop.ai/docs/llms.txt
Use this file to discover all available pages before exploring further.
Beta. The Rust SDK is at
0.0.1. The wire contract against the Raindrop ingestion API is stable and verified end-to-end against the live backend on every push, but the crate API may still change in minor ways before 0.1.0. We recommend pinning the git tag in your Cargo.toml.Installation
The Rust SDK is hosted on GitHub (not on crates.io). Add it to yourCargo.toml:
src/main.rs and runs:
The Rust SDK requires Rust 1.88+ (MSRV). It is
async-first and uses tokio. Most fallible methods return Result<_, Error> — track_ai, track_event, identify, track_signal, the Interaction mutators (set_input, set_property, set_properties, add_attachments, patch, finish), and Client::flush / Client::close. Propagate errors with ? as you would for any fallible call. The two constructors — Client::begin(...).await and Client::resume_interaction(...) — are infallible: they always return an Interaction (a no-op handle when the client is disabled), so don’t put a ? on those.Quick Start: Interaction API
The Interaction API uses a simple three-step pattern:begin()– Create an interaction and log the initial user input- Update – Optionally call
set_property,set_properties,set_input, oradd_attachments finish()– Record the AI’s final output and close the interaction
Example: Chat Completion
Updating an Interaction
Update an interaction at any point usingset_property, set_properties, set_input, or add_attachments:
Resuming an Interaction
If you no longer have the interaction object returned frombegin(), resume it with resume_interaction():
Single-Shot Tracking (track_ai)
For simple request-response interactions, you can use track_ai() directly:
We recommend usingUsebegin()→finish()for new code to take advantage of partial-event buffering and tracing.
track_event() for non-AI events:
Tracking Signals (Feedback)
Signals capture quality ratings on AI events. Usetrack_signal() with the same event ID from begin() or track_ai():
| Field | Type | Description |
|---|---|---|
event_id | String | The ID of the AI event you’re evaluating |
name | String | Signal name (e.g. "thumbs_up", "thumbs_down") |
kind | String | One of SignalKind::{DEFAULT, STANDARD, FEEDBACK, EDIT, AGENT, AGENT_INTERNAL}. Defaults to "default". |
sentiment | String | "POSITIVE" or "NEGATIVE" |
comment | String | Merged into properties.comment for feedback signals |
after | String | Merged into properties.after for edit signals |
attachment_id | String | Optional attachment ID to associate the signal with |
properties | BTreeMap<String, _> | Additional metadata |
Identifying Users
Attachments
Attachments let you include additional context — documents, images, code, or embedded content — with your events. They work with bothbegin() interactions and track_ai() calls.
| Field | Type | Description |
|---|---|---|
kind | String | "code", "text", "image", or "iframe" (serialized as type on the wire) |
role | String | "input" or "output" |
name | String | Optional display name |
value | String | Content or URL |
language | String | Programming language (only meaningful for "code" attachments) |
attachment_id | String | Optional UUID. Backend auto-assigns one if empty. Set explicitly to round-trip with Signal::attachment_id. |
The dashboard’s attachment viewer renders
text, image, and iframe attachments. code attachments survive ingestion and are searchable, but are not currently displayed in the visual attachments tab.Configuration
| Builder method | Description | Default |
|---|---|---|
.write_key(&str) | Your Raindrop API key. Empty/missing key → SDK becomes a no-op. | — |
.endpoint(&str) | Override the API endpoint | https://api.raindrop.ai/v1/ |
.debug(bool) | Verbose debug logging via tracing | false |
.partial_flush_interval(Duration) | Periodic event flush. Duration::ZERO disables periodic flush | 1s |
.trace_flush_interval(Duration) | Periodic span flush. Duration::ZERO disables periodic flush | 1s |
.trace_max_batch_size(usize) | Max spans per trace export request | 50 |
.trace_max_queue_size(usize) | Max spans buffered before back-pressuring | 5000 |
.max_attempts(u32) | HTTP retries. 1 disables retries. | 3 |
.base_delay(Duration) | Backoff base (exponential, ±20% jitter) | 1s |
.jitter_fraction(f64) | Backoff jitter fraction (0.0–1.0) | 0.2 |
.service_name(&str) | OTLP resource.service.name | "raindrop.rust-sdk" |
.library_name(&str) | $context.library.name reported with each event | "raindrop-rust" |
.library_version(&str) | $context.library.version | crate version |
.http_client(reqwest::Client) | Inject a custom reqwest::Client | new client w/ 10s timeout |
client.close().await? before your process exits to flush buffered events and spans. If write_key is empty, the client becomes a no-op (zero HTTP calls) instead of failing.
Tracing
Tracing captures detailed execution information from your AI pipelines — multi-model interactions, chained prompts, and tool calls. This helps you:- Visualize the full execution flow of your AI application
- Debug and optimize prompt chains
- Understand the intermediate steps that led to a response
Manual Spans
Build trees of spans by passing a parent intoSpanOptions::parent:
Interaction automatically inherit its user_id, convo_id, and event as traceloop.association.properties.* attributes, so the dashboard groups them under the same user, conversation, and event:
Plain
client.start_span(...) calls only need name + event_id. The SDK automatically emits traceloop.association.properties.event_id so the span survives the backend’s ingestion filter. For non-event-bound spans, set operation_id (e.g. "ai.workflow") or pass properties so the span has at least one of ai.operationId, traceloop.span.kind, traceloop.workflow.name, traceloop.association.properties.*, or gen_ai.* — otherwise it will be dropped server-side.Closure-style helpers
If you prefer scoped instrumentation,with_span runs a closure inside a span and automatically marks the span as failed on Err:
Tool Spans
Tool spans use the dedicated wire format (traceloop.span.kind=tool) so they surface in the dashboard’s event.toolCalls[] array.
| Field | Type | Description |
|---|---|---|
name | String | Tool name |
input | Option<Value> | JSON input |
output | Option<Value> | JSON output |
duration | Option<Duration> | Total duration |
start_time | Option<OffsetDateTime> | When the tool started (defaults to now - duration) |
end_time | Option<OffsetDateTime> | When the tool ended |
error | Option<String> | Error message; sets status=ERROR |
parent | Option<Span> | Parent span for nesting |
properties | BTreeMap<String, _> | Additional metadata |
with_tool and with_tool_async free helpers that run a closure inside a tool span and JSON-serialize the result onto traceloop.entity.output:
Standalone Tracer
UseClient::tracer() for batch jobs or non-conversation work where you still want spans and tool traces:
Span Attributes
The SDK provides typed helpers for OTLP-compatible attributes:Known Limitations
- No automatic LLM-client instrumentation. Unlike the Python and TypeScript SDKs, the Rust SDK does not auto-hook into LLM frameworks. Create spans manually via
start_span,start_tool_span,with_span,with_tool, ortrack_tool. - No PII redaction. The Python SDK exposes
set_redact_piiand the TypeScript SDK hasredactPii. The Rust SDK does not yet implement client-side redaction. Redact at the call site or upstream oftrack_ai/track_eventif needed. - No local debugger mirroring. The TypeScript SDK supports
RAINDROP_LOCAL_DEBUGGERto mirror traces and partial events to a local Workshop instance. The Rust SDK currently ships only to the configuredendpoint. - Oversized payload guard. Payloads larger than 1 MiB after JSON serialization are dropped client-side (matching the JS / Python SDKs) to avoid 413s on the gateway. The drop is logged via
tracing::warn!so production callers can detect it.
That’s it! You’re ready to explore your events in the Raindrop dashboard. Ping us on Slack or email us if you get stuck!