Skip to main content
Beta. The Java SDK is at 0.0.3. The wire contract against the Raindrop ingestion API is stable and verified end-to-end against the live backend on every push, but the public API may still change in minor ways before 0.1.0. Pin an exact version in your build file.

Installation

The SDK requires Java 17+. The artifact coordinates are ai.raindrop:raindrop-java. Gradle:
Maven:
Smallest possible program:
Raindrop implements AutoCloseable, so try-with-resources flushes and stops the client for short-lived programs:

Single-Shot Tracking (trackAi)

For simple request-response interactions, call trackAi() directly. At least one of input or output is required, along with userId and event. It returns the event id (or null if the event was invalid or the client is disabled):
For new code we recommend the begin() → finish() interaction API below: it buffers a pending event immediately and links any spans you create into the same trace.
Use track() for non-AI product events:

Interactions

begin() opens an interaction (a trace) and immediately ships a pending event so it appears in the Events tab right away. Update it as work progresses, then finish() records the final output:
setInput, setOutput, setModel, setProperty, and setError return the interaction, so they chain. Call finish() exactly once; it finalizes the event and closes the root span.

Tracing

Tracing captures detailed execution information — multi-step pipelines, tool calls, and subagents — so you can visualize the full execution flow, debug prompt chains, and understand the intermediate steps behind a response.

Tool and task spans

Spans created from an interaction inherit its userId, convoId, and event, so the dashboard groups them under the same user, conversation, and event. Use startTool for tool calls and startTask for other units of work:
setInput, setOutput, setError (which accepts a Throwable or a String), and setAttribute all return the span for chaining. Always end() a span — a try/finally guarantees it even when the work throws.

Nested spans & subagents

Spans are nestable: a span started from another span is parented to it, so subagent and tool trajectories form the correct tree in the trace view. Use startSpan(SpanOptions) for a generic span (for example a subagent with a custom operationId), and startTool / startTask for the common cases:
You can also start a free-standing tool span that is not tied to an interaction with raindrop.startToolSpan("name").

Signals

Signals capture quality ratings on AI events. Use trackSignal() with the same event id returned by begin() or trackAi():

Self-diagnostics

selfDiagnose() reports a signal that surfaces in the dashboard’s Self Diagnostics tab — useful when your agent detects that it is stuck or degraded:

Identifying Users


Attachments

Attachments include extra context — documents, images, code, or embedded content — with an event. Add them to a trackAi() or track() event via the builder:
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

Call raindrop.close() (or shutdown()) before your process exits to flush buffered events and spans under a bounded deadline. If writeKey is empty and no local Workshop is configured, the client is a no-op (zero HTTP calls) rather than an error. Local Workshop mirroring is enabled when RAINDROP_LOCAL_DEBUGGER is set to a URL, when RAINDROP_WORKSHOP is a truthy value or URL, or when the SDK can reach the default Workshop daemon at http://localhost:5899/v1/.

Application Git provenance

The SDK reports raindrop.app.commit_sha, with optional raindrop.app.commit_dirty and raindrop.app.branch. Application Git discovery runs once on a bounded daemon thread; telemetry, flush, and shutdown do not wait, so early operations may omit metadata. Branch discovery is opt-in. Java uses application injection, explicit environment, or the configured application source and never dependency/JAR metadata as the application revision. Use .appGit(false) to disable client enrichment without removing canonical properties explicitly supplied on an operation. .autoDetect(false) or RAINDROP_GIT_AUTO_DETECT=false disables automatic sources but retains explicit config, canonical operation properties, and RAINDROP_COMMIT_SHA, RAINDROP_COMMIT_DIRTY, and RAINDROP_BRANCH. RAINDROP_GIT_SOURCE_DIRECTORY selects the AUT source; RAINDROP_GIT_DETECT_BRANCH=true enables branch discovery. The explicit values are a full 40- or 64-character hexadecimal SHA, true or false dirty state, and an ordinary branch string, respectively. Existing canonical properties always win, including invalid values, and an overridden SHA does not acquire inferred branch or dirty state from another source. The metadata is for reporting/filtering, not simulation checkout selection or release/SDK identity. Client config wins over explicit Raindrop environment values, which win over reliable deployment, application Git, and provider-marked CI sources. A non-empty .sourceDirectory(...) or RAINDROP_GIT_SOURCE_DIRECTORY is resolved and captured at client initialization. It exclusively selects the automatic AUT checkout after explicit config and RAINDROP_* identity values. If that repository is unavailable, metadata stays absent; ambient build, deployment, and CI identity is not substituted. Discovery remains background work, so pending operations omit it without blocking.
This API requires the SDK release containing Git reporting. No version is documented until that release is published.

Projects

Pass .projectId(...) on the builder to scope every event from a client to a specific project. Under the hood this sets the X-Raindrop-Project-Id header on each request.
A project slug is up to 63 lowercase letters, digits, and hyphens, and it must start and end with a letter or digit (^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$). An invalid slug is ignored with a warning and no header is sent, so a typo never breaks ingestion. Omitting .projectId(...) (or passing "default") sends to the default Production project, which is the existing behavior, so single-project orgs need nothing here. See Projects for isolation, archival, and the full behavior table.

Reliability

Raindrop is designed never to slow down or crash your application. The SDK is a strict no-op when Raindrop is unreachable, slow, rate-limited, or misconfigured:
  • All network I/O runs on a background daemon thread. trackAi, track, trackSignal, identify, begin / finish, and span start/end only enqueue work and return immediately on the caller’s thread. flush() is non-blocking too.
  • Oversized payloads cost the cap, not the payload. Text fields and structured span/property values are bounded before serialization, so a multi-MB input is O(cap) on the caller.
  • Bounded waits everywhere. Connect/read timeouts, a capped retry count with clamped backoff, and a bounded flush-on-shutdown deadline — close() returns promptly even against a black-hole endpoint.
  • Exceptions never escape. Serialization or transport failures are swallowed and rate-limited-logged; your code path is unaffected.
The SDK is manual-only — it does not monkey-patch or auto-instrument your LLM client libraries — so it cannot interfere with your application’s runtime.

Local development with Workshop

Workshop is the local-first trace debugger. Point the SDK at it (or just run on localhost with RAINDROP_WORKSHOP=1) and events + spans stream into the UI with no write key: