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

# OpenRouter Agent SDK (Beta)

> Automatic tracing for OpenRouter Agent SDK applications with Raindrop

Raindrop automatically instruments the [OpenRouter Agent SDK](https://openrouter.ai/docs/agent-sdk/overview) (`@openrouter/agent`) to capture events and traces for model calls, tool execution, and multi-turn agent loops.

## Installation

<CodeGroup>
  ```bash npm theme={null}
  npm install @raindrop-ai/openrouter-agent @openrouter/agent
  ```

  ```bash pnpm theme={null}
  pnpm add @raindrop-ai/openrouter-agent @openrouter/agent
  ```

  ```bash yarn theme={null}
  yarn add @raindrop-ai/openrouter-agent @openrouter/agent
  ```

  ```bash bun theme={null}
  bun add @raindrop-ai/openrouter-agent @openrouter/agent
  ```
</CodeGroup>

## Quick Start

```typescript theme={null}
import { OpenRouter, tool } from "@openrouter/agent";
import { z } from "zod";
import { createRaindropOpenRouterAgent } from "@raindrop-ai/openrouter-agent";

const raindrop = createRaindropOpenRouterAgent({
  writeKey: "your-write-key",
  userId: "user-123",
  convoId: "convo-456",
});

const openrouter = raindrop.wrap(
  new OpenRouter({ apiKey: process.env.OPENROUTER_API_KEY }),
);

const getWeather = tool({
  name: "get_weather",
  description: "Get the weather for a city.",
  inputSchema: z.object({ city: z.string() }),
  outputSchema: z.object({ forecast: z.string() }),
  execute: async ({ city }) => ({ forecast: `Sunny in ${city}` }),
});

const result = openrouter.callModel({
  model: "openai/gpt-4o-mini",
  input: "Use get_weather for San Francisco, then answer briefly.",
  tools: [getWeather] as const,
});

console.log(await result.getText());

await raindrop.shutdown();
```

Telemetry is finalized when the `ModelResult` is consumed with `getText()`, `getResponse()`, or a stream method.

## Standalone `callModel`

If you import OpenRouter's standalone `callModel` helper, wrap that function once and call the wrapped version:

```typescript theme={null}
import { OpenRouter, callModel } from "@openrouter/agent";
import { createRaindropOpenRouterAgent } from "@raindrop-ai/openrouter-agent";

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

const trackedCallModel = raindrop.wrapCallModel(callModel);
const openrouter = new OpenRouter({ apiKey: process.env.OPENROUTER_API_KEY });

const result = trackedCallModel(openrouter, {
  model: "openai/gpt-4o-mini",
  input: "Hello from OpenRouter",
});

console.log(await result.getText());

await raindrop.shutdown();
```

## What Gets Traced

* **Agent calls** - input, output, model, response ID, response status, and token usage when OpenRouter returns it
* **Tool calls** - client tool executions captured as `ai.toolCall` trace spans linked to the root event
* **Conversation grouping** - pass `convoId` to group related agent calls
* **Errors** - failed OpenRouter calls finalize an error event before re-throwing to your application
* **Signals and users** - use the included `signals.track` and `users.identify` APIs alongside automatic events

Tool spans are linked to the root event so you can inspect the full execution path in the Trace tab.

## Configuration

```typescript theme={null}
const raindrop = createRaindropOpenRouterAgent({
  writeKey: "your-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](/platform/projects) by passing its slug as `projectId`:

```typescript theme={null}
const raindrop = createRaindropOpenRouterAgent({
  writeKey: "your-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.

## Identify Users

Associate traits with a user for filtering and trajectories:

```typescript theme={null}
await raindrop.users.identify({
  userId: "user-123",
  traits: {
    plan: "pro",
    company: "Acme",
  },
});
```

## Track Signals

Attach feedback, labels, or other signals to the most recently captured event:

```typescript theme={null}
if (raindrop.lastEventId) {
  await raindrop.signals.track({
    eventId: raindrop.lastEventId,
    name: "thumbs_up",
    type: "feedback",
    sentiment: "POSITIVE",
  });
}
```

## Flushing and Shutdown

Always call `flush()` or `shutdown()` before your process exits to ensure all telemetry is shipped:

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

## Known Limitations

* Creating a `ModelResult` without consuming it does not ship an event.
* Client tool spans wrap the local tool execution function, so their timing reflects local tool runtime.
* Server-executed OpenRouter tools are represented from response items when OpenRouter returns them after the provider response completes. Client function tools have the richest live trace data.
