> ## 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.

# Temporal (Beta)

> Automatic tracing for Temporal workflows and activities with Raindrop

## Installation

```bash npm theme={null}
npm install @raindrop-ai/temporal @temporalio/client @temporalio/worker
```

## Quick Start

### Client Setup

```typescript theme={null}
import { Client, Connection } from "@temporalio/client";
import { createRaindropTemporal } from "@raindrop-ai/temporal";

const raindrop = createRaindropTemporal({
  writeKey: process.env.RAINDROP_WRITE_KEY,
  userId: "user-123",
});

const connection = await Connection.connect();
const client = new Client({
  connection,
  interceptors: {
    workflow: [raindrop.interceptors.client],
  },
});

const handle = await client.workflow.start("processOrder", {
  taskQueue: "my-queue",
  workflowId: "order-123",
  args: [{ orderId: "order-123" }],
});

await raindrop.shutdown();
```

### Worker Setup

```typescript theme={null}
import { Worker } from "@temporalio/worker";
import { createRaindropTemporal } from "@raindrop-ai/temporal";
import * as activities from "./activities";

const raindrop = createRaindropTemporal({
  writeKey: process.env.RAINDROP_WRITE_KEY,
  userId: "worker-1",
});

const worker = await Worker.create({
  taskQueue: "my-queue",
  workflowsPath: require.resolve("./workflows"),
  activities,
  interceptors: {
    activity: [raindrop.interceptors.activityFactory],
    workflowModules: ["@raindrop-ai/temporal/workflow-interceptors"],
  },
  sinks: raindrop.sinks,
});

// Shut down Raindrop when the worker stops
process.on("SIGINT", async () => {
  await worker.shutdown();
  await raindrop.shutdown();
});

await worker.run();
```

## What Gets Traced

* **Workflow triggers** — span created when a client starts a workflow, with workflow type and context propagation
* **Workflow execution** — span covering the full workflow lifecycle
* **Activity execution** — each activity appears as a **tool call** in the dashboard with the activity type as the tool name
* **Child workflows** — nested under their parent workflow with correct span hierarchy
* **Distributed traces** — context propagated across workers via Temporal headers
* **Errors** — captured with error status on both workflow and activity spans, re-thrown to caller

### What shows in the dashboard

* **Events page** — each workflow appears as an event with input (`Workflow: {type}`) and output (`Workflow completed: {type}`)
* **Tool calls** — activities appear in the event's tool calls list with their activity type as the name
* **Traces tab** — full span hierarchy: trigger → workflow → activities, with parent-child nesting for child workflows
* **Properties** — `temporal.workflow_type`, `temporal.workflow_id`, `temporal.run_id`, and child workflow statuses

## Configuration

```typescript theme={null}
const raindrop = createRaindropTemporal({
  writeKey: process.env.RAINDROP_WRITE_KEY, // Optional: omit to disable telemetry
  endpoint: "...",                           // Optional: custom Raindrop API endpoint
  userId: "user-123",                        // Optional: associate events with a user
  convoId: "convo-456",                      // Optional: conversation/thread ID
  projectId: "support-prod",                 // Optional: route events to a specific project (slug)
  debug: false,                              // Optional: enable verbose logging
});
```

## Projects

Route events to a specific [project](/docs/platform/projects) by passing its slug as `projectId`:

```typescript theme={null}
const raindrop = createRaindropTemporal({
  writeKey: process.env.RAINDROP_WRITE_KEY,
  projectId: "support-prod",
});
```

This sets the `X-Raindrop-Project-Id` header on every event. Omit it (or pass `"default"`) to use your org's default **Production** project, which is the existing behavior. Single-project orgs need nothing new.

## Architecture

The integration uses four layers:

1. **Client interceptor** — wraps `client.workflow.start()` to create a root trigger span and inject trace context into workflow headers
2. **Activity interceptor** — creates a span per activity execution, parenting under the workflow span (same-worker) or using header-propagated context (cross-worker)
3. **Workflow interceptors** — propagate trace context from workflows to their activities and child workflows
4. **Sinks** — manage workflow-level spans, tracking start and completion events

## Flushing and Shutdown

```typescript theme={null}
await raindrop.flush();     // flush pending data
await raindrop.shutdown();  // flush + release resources
```

Always call `shutdown()` before your process exits to ensure all telemetry is delivered.

## Known Limitations

* **Abnormally terminated workflows** — if a workflow is externally terminated or cancelled without completing normally, the corresponding event may remain in a pending state.
* **Cross-worker trace nesting** — when an activity runs on a different worker than its workflow, the trace hierarchy may appear flatter than for same-worker activities. The spans are still linked via headers but may not show a deep parent-child tree.
* **TypeScript only** — this integration is currently available for TypeScript. Python support is not yet available.
