npm package: @revenium/anthropic
Description: Transparent TypeScript middleware for automatic Revenium usage tracking with Anthropic Claude AI
Author: Revenium
Latest version: 1.1.4

# Revenium Middleware for Anthropic (Node.js)

[![npm version](https://img.shields.io/npm/v/@revenium/anthropic.svg)](https://www.npmjs.com/package/@revenium/anthropic)
[![Node Versions](https://img.shields.io/node/v/@revenium/anthropic.svg)](https://www.npmjs.com/package/@revenium/anthropic)
[![Documentation](https://img.shields.io/badge/docs-revenium.io-blue)](https://docs.revenium.io)
[![Website](https://img.shields.io/badge/website-revenium.ai-blue)](https://www.revenium.ai)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

Automatically track and meter your Anthropic Claude API usage with Revenium. This middleware provides seamless integration with **Anthropic Claude SDK**, requiring minimal code changes and featuring native TypeScript support.

## Features

- **Seamless Integration**: Drop-in replacement with zero code changes required
- **Complete Metering**: Track tokens, costs, and performance metrics automatically
- **Prompt Capture**: Optional capture of prompts and responses with automatic credential sanitization
- **Custom Metadata**: Add business context with native TypeScript support
- **Streaming Support**: Real-time streaming with comprehensive analytics
- **Tool Use Support**: Full support for Anthropic's function calling and tools
- **Multi-modal Support**: Works with text, images, and all Claude capabilities
- **Type Safe**: Complete TypeScript support with no type casting required
- **Fire-and-forget**: Never blocks your application flow
- **Analytics**: Detailed usage analytics and reporting

## Getting Started

### 1. Create Project Directory

```bash
# Create and navigate to project directory
mkdir my-anthropic-project
cd my-anthropic-project

# Initialize npm project
npm init -y

# Install dependencies
npm install @revenium/anthropic @anthropic-ai/sdk dotenv tsx
npm install --save-dev typescript @types/node
```

### 2. Configure Environment Variables

Create a `.env` file:

```bash
REVENIUM_METERING_API_KEY="hak_your_revenium_key"
ANTHROPIC_API_KEY="sk-ant-your_anthropic_key"
```

> **Note**: `REVENIUM_METERING_BASE_URL` defaults to `https://api.revenium.ai` and doesn't need to be set unless using a different environment.

### 3. Run Your First Example

Run the [getting started example](https://github.com/revenium/revenium-middleware-anthropic-node/blob/HEAD/examples/getting_started.ts):

```bash
npx tsx node_modules/@revenium/anthropic/examples/getting_started.ts
```

Or with debug logging:

```bash
# Linux/macOS
REVENIUM_DEBUG=true npx tsx node_modules/@revenium/anthropic/examples/getting_started.ts

# Windows (PowerShell)
$env:REVENIUM_DEBUG="true"; npx tsx node_modules/@revenium/anthropic/examples/getting_started.ts
```

**For more examples and TypeScript patterns, see [examples/README.md](https://github.com/revenium/revenium-middleware-anthropic-node/blob/HEAD/examples/README.md).**

## Requirements

- Node.js 18+
- TypeScript 5.0+ (for TypeScript projects)
- Anthropic SDK (@anthropic-ai/sdk) v0.20.0+
- Revenium API key

## What Gets Tracked

The middleware automatically captures:

- **Token Usage**: Input and output tokens for accurate billing
- **Request Duration**: Total time for each API call
- **Model Information**: Which Claude model was used
- **Operation Type**: Chat completion, streaming, tool use, etc.
- **Error Tracking**: Failed requests and error details
- **Streaming Metrics**: Time to first token for streaming responses
- **Custom Metadata**: Business context you provide

## Terminal Summary Output

The middleware can print a usage summary to the terminal after each API request. This is useful for development, debugging, and cost monitoring.

### Configuration

Enable via environment variables:

```bash
# Human-readable format (with emojis)
REVENIUM_PRINT_SUMMARY=true

# JSON format (for automation/log parsing)
REVENIUM_PRINT_SUMMARY=json

# Team ID for cost retrieval (optional)
REVENIUM_TEAM_ID=your-team-id
```

Or configure programmatically:

```typescript
import { configure } from "@revenium/anthropic";

configure({
  reveniumApiKey: "hak_your_key",
  reveniumBaseUrl: "https://api.revenium.ai", // optional, this is the default
  printSummary: "human", // or "json" or true
  teamId: "your-team-id", // optional, for cost data
});
```

### Output Formats

**Human-readable format** (`printSummary: true` or `printSummary: 'human'`):

```
============================================================
📊 REVENIUM USAGE SUMMARY
============================================================
🤖 Model: claude-sonnet-4-20250514
🏢 Provider: Anthropic
⏱️  Duration: 1.23s

💬 Token Usage:
   📥 Input Tokens:  150
   📤 Output Tokens: 75
   📊 Total Tokens:  225

💰 Cost: $0.001234
============================================================
```

**JSON format** (`printSummary: 'json'`):

```json
{
  "model": "claude-sonnet-4-20250514",
  "provider": "Anthropic",
  "durationSeconds": 1.23,
  "inputTokenCount": 150,
  "outputTokenCount": 75,
  "totalTokenCount": 225,
  "cost": 0.001234
}
```

> **Note**: Cost data requires `teamId` to be configured. Without it, the summary will show token usage but not cost.
>
> **Optional fields**: The JSON output may include additional fields depending on the context:
>
> - `costStatus`: `"pending"` (when `teamId` is set but cost is not yet available) or `"unavailable"` (when `teamId` is not configured). Only present when `cost` is `null`.
> - `traceId`: The trace ID for request correlation (only present if `traceId` was provided in `usageMetadata`).

## Trace Visualization Fields

The middleware automatically captures trace visualization fields for distributed tracing and analytics:

| Field                 | Type   | Description                                                                     | Environment Variable               |
| --------------------- | ------ | ------------------------------------------------------------------------------- | ---------------------------------- |
| `environment`         | string | Deployment environment (production, staging, development)                       | `REVENIUM_ENVIRONMENT`, `NODE_ENV` |
| `operationType`       | string | Operation classification (CHAT) - automatically detected                        | N/A (auto-detected)                |
| `operationSubtype`    | string | Additional detail (function_call, etc.) - automatically detected                | N/A (auto-detected)                |
| `retryNumber`         | number | Retry attempt number (0 for first attempt, 1+ for retries)                      | `REVENIUM_RETRY_NUMBER`            |
| `parentTransactionId` | string | Parent transaction reference for distributed tracing                            | `REVENIUM_PARENT_TRANSACTION_ID`   |
| `transactionName`     | string | Human-friendly operation label                                                  | `REVENIUM_TRANSACTION_NAME`        |
| `region`              | string | Cloud region (us-east-1, etc.) - auto-detected from AWS/Azure/GCP               | `AWS_REGION`, `REVENIUM_REGION`    |
| `credentialAlias`     | string | Human-readable credential name                                                  | `REVENIUM_CREDENTIAL_ALIAS`        |
| `traceType`           | string | Categorical identifier (alphanumeric, hyphens, underscores only, max 128 chars) | `REVENIUM_TRACE_TYPE`              |
| `traceName`           | string | Human-readable label for trace instances (max 256 chars)                        | `REVENIUM_TRACE_NAME`              |

**All trace visualization fields are optional.** The middleware will automatically detect and populate these fields when possible.

### Example Configuration

```env
REVENIUM_ENVIRONMENT=production
REVENIUM_REGION=us-east-1
REVENIUM_CREDENTIAL_ALIAS=Anthropic Production Key
REVENIUM_TRACE_TYPE=customer_support
REVENIUM_TRACE_NAME=Support Ticket #12345
REVENIUM_PARENT_TRANSACTION_ID=parent-txn-123
REVENIUM_TRANSACTION_NAME=Answer Customer Question
REVENIUM_RETRY_NUMBER=0
```

## Prompt Capture

The middleware can capture prompts and responses for analysis and debugging. This feature is **disabled by default** for privacy and performance.

### Configuration

Enable via environment variable:

```bash
REVENIUM_CAPTURE_PROMPTS=true
```

Or configure programmatically:

```typescript
import { configure } from "@revenium/anthropic";

configure({
  reveniumApiKey: "hak_your_key",
  capturePrompts: true,
});
```

### Per-Request Control

Override the global setting for individual requests:

```typescript
const response = await anthropic.messages.create(
  {
    model: "claude-3-5-sonnet-20241022",
    max_tokens: 1024,
    messages: [{ role: "user", content: "Hello!" }],
  },
  {
    capturePrompts: true, // Enable for this request only
  },
);
```

### Security

All captured prompts are automatically sanitized to remove sensitive credentials including:

- API keys (sk-\*, sk-proj-\*, sk-ant-\*)
- Bearer tokens
- Passwords
- Generic tokens and api_key fields

## Advanced Usage

### Initialization Options

The middleware supports three initialization patterns:

**Automatic (Recommended)** - Simply import the middleware and it auto-initializes:

```typescript
import "@revenium/anthropic";
import Anthropic from "@anthropic-ai/sdk";

const anthropic = new Anthropic();
// Tracking works automatically if env vars are set
```

**Explicit** - Call `initialize()` for error handling control

**Manual** - Use `configure()` to set all options programmatically

For detailed examples of all initialization patterns, see [examples/](https://github.com/revenium/revenium-middleware-anthropic-node/blob/HEAD/examples/README.md).

### Streaming Responses

Streaming is fully supported with real-time token tracking and time-to-first-token metrics. The middleware automatically tracks streaming responses without any additional configuration.

See [examples/advanced-features.ts](https://github.com/revenium/revenium-middleware-anthropic-node/blob/HEAD/examples/advanced-features.ts) for working streaming examples.

### Custom Metadata Tracking

Add business context to track usage by organization, user, task type, or custom fields. Pass a `usageMetadata` object with any of these optional fields:

| Field                         | Description                                            | Use Case                                                                                                         |
| ----------------------------- | ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------- |
| `traceId`                     | Unique identifier for session or conversation tracking | Link multiple API calls together for debugging, user session analytics, or distributed tracing across services   |
| `taskType`                    | Type of AI task being performed                        | Categorize usage by workload (e.g., "chat", "code-generation", "doc-summary") for cost analysis and optimization |
| `subscriber.id`               | Unique user identifier                                 | Track individual user consumption for billing, rate limiting, or user analytics                                  |
| `subscriber.email`            | User email address                                     | Identify users for support, compliance, or usage reports                                                         |
| `subscriber.credential.name`  | Authentication credential name                         | Track which API key or service account made the request                                                          |
| `subscriber.credential.value` | Authentication credential value                        | Associate usage with specific credentials for security auditing                                                  |
| `organizationName`            | Organization or company name                           | Multi-tenant cost allocation, usage quotas per organization (used for lookup/auto-creation)                      |
| `subscriptionId`              | Subscription plan identifier                           | Track usage against subscription limits, identify plan upgrade opportunities                                     |
| `productName`                 | Your product or feature name                           | Attribute AI costs to specific features in your application (e.g., "chatbot", "email-assistant")                 |
| `agent`                       | AI agent or bot identifier                             | Distinguish between multiple AI agents or automation workflows in your system                                    |
| `responseQualityScore`        | Custom quality rating (0.0-1.0)                        | Track user satisfaction or automated quality metrics for model performance analysis                              |

**All metadata fields are optional.** Custom fields beyond the standard ones are automatically preserved and sent to Revenium.

**Resources:**

- [examples/advanced-features.ts](https://github.com/revenium/revenium-middleware-anthropic-node/blob/HEAD/examples/advanced-features.ts) - Working examples

## Tool Metering

Track execution of custom tools and external API calls with automatic timing, error handling, and metadata collection.

### Quick Example

```typescript
import { meterTool, setToolContext } from '@revenium/anthropic';

setToolContext({
  agent: 'my-agent',
  traceId: 'session-123'
});

const result = await meterTool('weather-api', async () => {
  return await fetch('https://api.example.com/weather');
}, {
  operation: 'get_forecast',
  outputFields: ['temperature', 'humidity']
});
```

### Functions

**meterTool(toolId, fn, metadata?)**

Wraps a function with automatic metering. Captures duration, success/failure, and errors. Returns function result unchanged.

**reportToolCall(toolId, report)**

Manually report a tool call that was already executed. Useful when wrapping is not possible.

**Context Management**

- `setToolContext(ctx)` - Set context for all subsequent tool calls
- `getToolContext()` - Get current context
- `clearToolContext()` - Clear context
- `runWithToolContext(ctx, fn)` - Run function with scoped context

### Metadata Options

| Field | Description |
|-------|-------------|
| `operation` | Tool operation name (e.g., "search", "scrape") |
| `outputFields` | Array of field names to auto-extract from result |
| `usageMetadata` | Custom metrics (e.g., tokens, results count) |
| `agent`, `traceId`, etc. | Context fields (inherited from setToolContext) |

## Metadata Fields

The middleware automatically sends the following fields to Revenium's `/meter/v2/ai/completions` endpoint:

| Field                     | Type    | Source             | Description                                                              |
| ------------------------- | ------- | ------------------ | ------------------------------------------------------------------------ |
| `stopReason`              | string  | Anthropic Response | Why completion stopped: "END", "MAX_TOKENS", "STOP_SEQUENCE", "TOOL_USE" |
| `costType`                | string  | Fixed              | Always "AI" for AI completions                                           |
| `isStreamed`              | boolean | Request Type       | Whether response was streamed                                            |
| `taskType`                | string  | usageMetadata      | Optional task categorization                                             |
| `agent`                   | string  | usageMetadata      | Optional agent identifier                                                |
| `operationType`           | string  | Fixed              | Always "CHAT" for message completions                                    |
| `inputTokenCount`         | number  | Anthropic Usage    | Input tokens consumed                                                    |
| `outputTokenCount`        | number  | Anthropic Usage    | Output tokens generated                                                  |
| `reasoningTokenCount`     | number  | Fixed              | Always 0 (Anthropic doesn't report reasoning tokens)                     |
| `cacheCreationTokenCount` | number  | Anthropic Usage    | Tokens used for prompt caching creation                                  |
| `cacheReadTokenCount`     | number  | Anthropic Usage    | Tokens read from prompt cache                                            |
| `totalTokenCount`         | number  | Calculated         | Sum of input + output tokens                                             |
| `organizationName`        | string  | usageMetadata      | Optional organization name (used for lookup/auto-creation)               |
| `productName`             | string  | usageMetadata      | Optional product name (used for lookup/auto-creation)                    |
| `subscriber`              | object  | usageMetadata      | Optional subscriber info (id, email, credential)                         |
| `subscriptionId`          | string  | usageMetadata      | Optional subscription plan identifier                                    |
| `model`                   | string  | Request            | Anthropic model used (e.g., "claude-3-5-haiku-20241022")                 |
| `transactionId`           | string  | Generated          | Unique request identifier (UUID)                                         |
| `responseTime`            | string  | Timestamp          | ISO 8601 timestamp of response completion                                |
| `requestDuration`         | number  | Measured           | Total request duration in milliseconds                                   |
| `provider`                | string  | Fixed              | Always "Anthropic"                                                       |
| `requestTime`             | string  | Timestamp          | ISO 8601 timestamp when request started                                  |
| `completionStartTime`     | string  | Timestamp          | ISO 8601 timestamp when completion generation started                    |
| `timeToFirstToken`        | number  | Measured           | Milliseconds from request start to first token (streaming only)          |
| `traceId`                 | string  | usageMetadata      | Optional trace identifier for request correlation                        |
| `responseQualityScore`    | number  | usageMetadata      | Optional quality rating (0.0-1.0)                                        |
| `middlewareSource`        | string  | Fixed              | Always "nodejs" to identify this middleware                              |
| Custom Fields             | any     | usageMetadata      | Any additional fields in usageMetadata are preserved                     |

**Note:** Fields marked as "usageMetadata" come from the optional `usageMetadata` object you pass to `messages.create()`.

**Resources:**

- [API Reference](https://revenium.readme.io/reference/meter_ai_completion) - Complete metadata field documentation

## Configuration Options

### Environment Variables

| Variable                     | Required | Default                   | Description                                |
| ---------------------------- | -------- | ------------------------- | ------------------------------------------ |
| `REVENIUM_METERING_API_KEY`  | Yes      | -                         | Your Revenium API key                      |
| `ANTHROPIC_API_KEY`          | Yes      | -                         | Anthropic Claude API key                   |
| `REVENIUM_METERING_BASE_URL` | No       | `https://api.revenium.ai` | Revenium metering API base URL             |
| `REVENIUM_DEBUG`             | No       | `false`                   | Enable debug logging (true/false)          |
| `REVENIUM_CAPTURE_PROMPTS`   | No       | `false`                   | Capture prompts and responses (true/false) |

### Manual Configuration

For programmatic configuration instead of environment variables, use the `configure()` function. See the initialization options above and [examples/](https://github.com/revenium/revenium-middleware-anthropic-node/blob/HEAD/examples/README.md) for details.

## Troubleshooting

### Common Issues

#### "Missing API Key" Error

```bash
# Make sure you've set the API key
export ANTHROPIC_API_KEY="sk-ant-your-actual-api-key"

# Verify it's set
echo $ANTHROPIC_API_KEY
```

#### "Requests not being tracked"

```bash
# Verify Revenium configuration
export REVENIUM_METERING_API_KEY="hak-your-actual-revenium-key"

# Enable debug logging to see what's happening
export REVENIUM_DEBUG="true"
```

#### TypeScript errors with usageMetadata

- Ensure you're importing the middleware before using Anthropic
- Check that your TypeScript version is 4.5+ for module augmentation
- Verify you're using the latest version: `npm update @revenium/anthropic`

#### Build/Import Errors

```bash
# Clean and reinstall
rm -rf node_modules package-lock.json
npm install

# For TypeScript projects
npm run build
```

### Debug Mode

Enable detailed logging to troubleshoot issues:

```bash
export REVENIUM_DEBUG="true"
node your-script.js
```

This will show:

- Request/response details
- Token counting information
- Metering data being sent
- Error details

Look for log messages like:

- `[Revenium] Anthropic request intercepted`
- `[Revenium] Usage metadata extracted`
- `[Revenium] Revenium tracking successful`

## Included Examples

The package includes these example files:

- **basic-usage.ts**: Simple chat completions with all initialization methods
- **advanced-features.ts**: Streaming, tools, and custom metadata

All examples are in the `examples/` directory of the installed package. For detailed TypeScript patterns and usage, see [examples/README.md](https://github.com/revenium/revenium-middleware-anthropic-node/blob/HEAD/examples/README.md).

## How It Works

1. **Automatic Patching**: When imported, the middleware patches Anthropic's `messages.create` method
2. **Request Interception**: All Anthropic requests are intercepted to extract metadata
3. **Usage Extraction**: Token counts, model info, and timing data are captured
4. **Async Tracking**: Usage data is sent to Revenium in the background (fire-and-forget)
5. **Transparent Response**: Original Anthropic responses are returned unchanged

The middleware never blocks your application - if Revenium tracking fails, your Anthropic requests continue normally.

## Documentation

For detailed documentation, visit [docs.revenium.io](https://docs.revenium.io).  
For contributor lifecycle, validation, and provider metadata, see
[docs/standardization/README.md](https://github.com/revenium/revenium-middleware-anthropic-node/blob/HEAD/docs/standardization/README.md).

## Contributing

See [CONTRIBUTING.md](https://github.com/revenium/revenium-middleware-anthropic-node/blob/HEAD/CONTRIBUTING.md)

## Code of Conduct

See [CODE_OF_CONDUCT.md](https://github.com/revenium/revenium-middleware-anthropic-node/blob/HEAD/CODE_OF_CONDUCT.md)

## Security

See [SECURITY.md](https://github.com/revenium/revenium-middleware-anthropic-node/blob/HEAD/SECURITY.md)

## License

This project is licensed under the MIT License - see the [LICENSE](https://github.com/revenium/revenium-middleware-anthropic-node/blob/HEAD/LICENSE) file for details.

## Support

For issues, feature requests, or contributions:

- **Website**: [www.revenium.ai](https://www.revenium.ai)
- **GitHub Repository**: [revenium/revenium-middleware-anthropic-node](https://github.com/revenium/revenium-middleware-anthropic-node)
- **Issues**: [Report bugs or request features](https://github.com/revenium/revenium-middleware-anthropic-node/issues)
- **Documentation**: [docs.revenium.io](https://docs.revenium.io)
- **Email**: support@revenium.io

## Development

For development and testing instructions, see [DEVELOPMENT.md](https://github.com/revenium/revenium-middleware-anthropic-node/blob/HEAD/DEVELOPMENT.md).

---

**Built by Revenium**