# JavaScript SDK

> Use PromptRails from JavaScript or TypeScript apps with typed clients for agents, prompts, traces, and scores.

Source: https://0.0.0.0:3000/javascript-sdk

The official JavaScript/TypeScript SDK for PromptRails provides a fully typed client for interacting with the PromptRails API from Node.js, Deno, or browser environments.

<div style={{ display: 'flex', gap: '0.75rem', marginBottom: '0.5rem' }}>
  <a href="https://github.com/promptrails/javascript-sdk" target="_blank" rel="noopener noreferrer">
    GitHub
  </a>
  <span style={{ color: 'var(--color-muted-foreground)' }}>·</span>
  <a
    href="https://www.npmjs.com/package/@promptrails/sdk"
    target="_blank"
    rel="noopener noreferrer"
  >
    npm
  </a>
</div>

Use the JavaScript SDK when a web app, Node service, serverless function, or frontend-adjacent workflow needs to call PromptRails directly. You do not need it to try an agent inside the product; Studio, chat, triggers, and Agent UI deployments can run without SDK code.

For production applications, create a scoped API key, keep it server-side when possible, and inspect the resulting execution trace before exposing the workflow to users.

## Installation

```bash
npm install @promptrails/sdk
```

Or with other package managers:

```bash
yarn add @promptrails/sdk
pnpm add @promptrails/sdk
```

Supports both ESM and CommonJS module formats.

Current release: **v0.7.0** — the standalone [`@promptrails/sdk/tracing`](#tracing)
entry point for sending spans to PromptRails from any code, with LangChain,
OpenAI, Anthropic, Google GenAI, and OpenTelemetry integrations. See the
[changelog](https://github.com/promptrails/javascript-sdk/releases).

<TechnicalDetails title="Client setup and resource reference">

## Client Initialization

```typescript
import { PromptRails } from '@promptrails/sdk'

const client = new PromptRails({
  apiKey: 'your-api-key',
  baseUrl: 'https://api.promptrails.ai', // default
  timeout: 30000, // milliseconds, default
  maxRetries: 3, // default
})
```

## Configuration

| Parameter    | Type   | Default                      | Description                     |
| ------------ | ------ | ---------------------------- | ------------------------------- |
| `apiKey`     | string | Required                     | PromptRails API key             |
| `baseUrl`    | string | `https://api.promptrails.ai` | API base URL                    |
| `timeout`    | number | 30000                        | Request timeout in milliseconds |
| `maxRetries` | number | 3                            | Maximum retry attempts          |

## Available Resources

| Resource       | Property               | Description                                                                            |
| -------------- | ---------------------- | -------------------------------------------------------------------------------------- |
| Agents         | `client.agents`        | Agent CRUD, versioning, execution                                                      |
| Prompts        | `client.prompts`       | Prompt CRUD, versioning, execution                                                     |
| Executions     | `client.executions`    | Execution listing and details                                                          |
| Credentials    | `client.credentials`   | Credential management                                                                  |
| Data Sources   | `client.dataSources`   | Data source CRUD, versioning, execution                                                |
| Chat           | `client.chat`          | Send messages to chat sessions                                                         |
| Sessions       | `client.sessions`      | Chat session management                                                                |
| Memories       | `client.memories`      | Agent memory CRUD and search                                                           |
| Traces         | `client.traces`        | Trace listing and filtering                                                            |
| Costs          | `client.costs`         | Cost analysis and summaries                                                            |
| MCP Tools      | `client.mcpTools`      | MCP tool management                                                                    |
| MCP Templates  | `client.mcpTemplates`  | MCP template browsing                                                                  |
| Guardrails     | `client.guardrails`    | Guardrail configuration                                                                |
| Approvals      | `client.approvals`     | Approval request management                                                            |
| Scores         | `client.scores`        | Scoring and evaluation                                                                 |
| Templates      | `client.templates`     | Flow templates                                                                         |
| Dashboard      | `client.dashboard`     | Agent UI deployments                                                                   |
| Sessions       | `client.sessions`      | Session management                                                                     |
| A2A            | `client.a2a`           | Agent-to-Agent protocol                                                                |
| LLM Models     | `client.llmModels`     | Available LLM models                                                                   |
| Agent Triggers | `client.agentTriggers` | Agent trigger management (generic webhook, Slack, Telegram, Teams, WhatsApp, schedule) |

</TechnicalDetails>

## Common Operations

### Execute an Agent

```typescript
const result = await client.agents.execute('agent-id', {
  input: { message: 'Hello, world!' },
  metadata: { source: 'api' },
})

console.log(result.data.output)
console.log(`Cost: $${result.data.cost.toFixed(6)}`)
```

<TechnicalDetails title="More JavaScript SDK operations">

### List Agents

```typescript
const agents = await client.agents.list({ page: 1, limit: 20 })

for (const agent of agents.data) {
  console.log(`${agent.name} (${agent.type})`)
}
```

### Create a Prompt

```typescript
const prompt = await client.prompts.create({
  name: 'Summarizer',
  description: 'Summarizes text',
})

const version = await client.prompts.createVersion(prompt.data.id, {
  systemPrompt: 'You are a concise summarizer.',
  userPrompt: 'Summarize: {{ text }}',
  temperature: 0.5,
  message: 'Initial version',
})
```

### Chat

```typescript
const session = await client.chat.createSession({
  agentId: 'agent-id',
})

const response = await client.chat.sendMessage(session.id, {
  content: 'What is PromptRails?',
})

console.log(response.content)
```

### Stream a Chat Turn

`sendMessageStream` posts a user message and yields typed
Server-Sent Events on the same HTTP connection — useful for showing the
agent's reasoning, tool calls, and token-by-token deltas in the UI.

```typescript
const session = await client.chat.createSession({ agentId: 'agent-id' })

const controller = new AbortController()

for await (const event of client.chat.sendMessageStream(
  session.id,
  { content: 'What is PromptRails?' },
  { signal: controller.signal },
)) {
  switch (event.type) {
    case 'execution':
      console.log('execution_id:', event.executionId)
      break
    case 'thinking':
      console.log('[thinking]', event.content)
      break
    case 'tool_start':
      console.log('[tool_start]', event.name)
      break
    case 'tool_end':
      console.log('[tool_end]', event.name, event.summary)
      break
    case 'content':
      process.stdout.write(event.content)
      break
    case 'done':
      console.log('\n[done]', event.tokenUsage)
      break
    case 'error':
      console.error('[error]', event.message)
      break
  }
}
```

Cancel an in-flight stream with `controller.abort()`. All event shapes are
exported via the `StreamEvent` discriminated union:

```typescript
import type { StreamEvent } from '@promptrails/sdk'
```

### Stream an Existing Execution

When an execution was started outside a chat (e.g. `client.agents.execute`),
subscribe to its live event stream with `client.executions.stream`:

```typescript
for await (const event of client.executions.stream(executionId)) {
  if (event.type === 'content') process.stdout.write(event.content)
  if (event.type === 'done') break
}
```

### Search Memories

```typescript
const results = await client.memories.search({
  agentId: 'agent-id',
  query: 'refund policy',
  limit: 5,
})
```

### Create a Score

```typescript
await client.scores.create({
  traceId: 'trace-id',
  name: 'quality',
  dataType: 'numeric',
  value: 4.5,
  source: 'manual',
})
```

### Approve an Execution

```typescript
await client.approvals.decide('approval-id', {
  decision: 'approved',
  reason: 'Looks good',
})
```

</TechnicalDetails>

<TechnicalDetails title="JavaScript SDK advanced details">

## Typed Agent Config

`createVersion` takes a typed `AgentConfig` — a discriminated union by
agent type. The SDK injects the `type` discriminator automatically, so
renames in the backend schema (e.g. `prompt_version_id` → `prompt_id`)
surface as TypeScript errors instead of silent runtime failures.

```typescript
import {
  SimpleAgentConfig,
  ChainAgentConfig,
  MultiAgentConfig,
  WorkflowAgentConfig,
  CompositeAgentConfig,
  PromptLink,
} from '@promptrails/sdk'

// Simple agent — one prompt per execution
const simple: SimpleAgentConfig = {
  type: 'simple',
  prompt_id: 'prompt-id',
  approval_required: false,
}

// Chain agent — prompts run sequentially, output of step N feeds step N+1
const chain: ChainAgentConfig = {
  type: 'chain',
  prompt_ids: [
    { prompt_id: 'p1', role: 'step1', sort_order: 0 },
    { prompt_id: 'p2', role: 'step2', sort_order: 1 },
  ],
}

await client.agents.createVersion('agent-id', {
  version: '1.0.0',
  config: simple,
  set_current: true,
})
```

Available variants: `SimpleAgentConfig`, `ChainAgentConfig`,
`MultiAgentConfig`, `WorkflowAgentConfig`, `CompositeAgentConfig`. Chain
and multi-agent configs use `PromptLink[]`; workflow uses `WorkflowNode[]`;
composite uses `CompositeStep[]`. See
[Agent Versioning](/docs/agent-versioning) for the per-type field
reference.

## Tracing

The `@promptrails/sdk/tracing` entry point sends spans to PromptRails from any code, without managing your prompts or agents on the platform. It is independent of the API client and only needs an API key with the `traces:write` scope.

```typescript
import { Tracer } from '@promptrails/sdk/tracing'

const tracer = new Tracer({ apiKey: 'pr_...' })

await tracer.span('agent-run', { kind: 'agent' }, async (root) => {
  root.setInput({ q: 'weather?' })
  await tracer.span('llm-call', { kind: 'llm' }, async (llm) => {
    llm.setModel('gpt-4o').setUsage(120, 30)
  })
})

await tracer.flush()
```

### Framework integrations

Subpath imports auto-instrument popular frameworks:

```typescript
// LangChain
import { PromptRailsCallbackHandler } from '@promptrails/sdk/tracing/integrations/langchain'
await chain.invoke(inputs, { callbacks: [new PromptRailsCallbackHandler(tracer)] })

// OpenAI
import { traceOpenAI } from '@promptrails/sdk/tracing/integrations/openai'
const client = traceOpenAI(new OpenAI(), tracer)

// Anthropic
import { traceAnthropic } from '@promptrails/sdk/tracing/integrations/anthropic'
const anthropic = traceAnthropic(new Anthropic(), tracer)

// Google GenAI
import { traceGoogle } from '@promptrails/sdk/tracing/integrations/google'
const google = traceGoogle(new GoogleGenAI({ apiKey: '...' }), tracer)
```

See the [Tracing](/docs/tracing) guide for span kinds, batching, and the OpenTelemetry bridge.

## SDK Version

```typescript
import { VERSION } from '@promptrails/sdk'
console.log(VERSION) // "0.7.0"
```

The SDK also sends `User-Agent: promptrails-js/<version>` on every
request (except in browsers, where fetch ignores the header).

## TypeScript Types

The SDK includes full TypeScript type definitions. All request and response types are exported:

```typescript
import type {
  Agent,
  Prompt,
  Execution,
  Trace,
  Score,
  Credential,
  ChatSession,
} from '@promptrails/sdk'
```

## Error Handling

The SDK throws typed errors for different HTTP status codes:

```typescript
import {
  PromptRailsError,
  ValidationError,
  UnauthorizedError,
  ForbiddenError,
  NotFoundError,
  RateLimitError,
  ServerError,
} from '@promptrails/sdk'

try {
  const result = await client.agents.execute('invalid-id', { input: {} })
} catch (error) {
  if (error instanceof NotFoundError) {
    console.log(`Agent not found: ${error.message}`)
  } else if (error instanceof ValidationError) {
    console.log(`Invalid input: ${error.message}`)
    console.log(`Details:`, error.details)
  } else if (error instanceof RateLimitError) {
    console.log(`Rate limited: ${error.message}`)
  } else if (error instanceof UnauthorizedError) {
    console.log(`Invalid API key: ${error.message}`)
  } else if (error instanceof ForbiddenError) {
    console.log(`Insufficient permissions: ${error.message}`)
  } else if (error instanceof ServerError) {
    console.log(`Server error (${error.statusCode}): ${error.message}`)
  } else if (error instanceof PromptRailsError) {
    console.log(`Unexpected error: ${error.message}`)
  }
}
```

### Error Classes

| Exception           | HTTP Status | Description                |
| ------------------- | ----------- | -------------------------- |
| `ValidationError`   | 400         | Invalid request parameters |
| `UnauthorizedError` | 401         | Invalid or missing API key |
| `ForbiddenError`    | 403         | Insufficient permissions   |
| `NotFoundError`     | 404         | Resource not found         |
| `RateLimitError`    | 429         | Rate limit exceeded        |
| `ServerError`       | 5xx         | Server-side error          |
| `PromptRailsError`  | Any         | Base class for all errors  |

All error instances include:

- `message` -- Error description
- `statusCode` -- HTTP status code
- `code` -- Optional error code
- `details` -- Optional additional details object

## ESM and CJS Support

The SDK ships with both ESM and CommonJS builds:

```typescript
// ESM
import { PromptRails } from '@promptrails/sdk'

// CommonJS
const { PromptRails } = require('@promptrails/sdk')
```

## Pagination

```typescript
// Page-based pagination
const page1 = await client.agents.list({ page: 1, limit: 20 })
const page2 = await client.agents.list({ page: 2, limit: 20 })
```

</TechnicalDetails>

## Related Topics

- [Examples](https://github.com/promptrails/examples/tree/main/javascript) -- Ready-to-run code examples
- [Quickstart](/docs/quickstart) -- Getting started guide
- [Python SDK](/docs/python-sdk) -- Python alternative
- [Go SDK](/docs/go-sdk) -- Go alternative
- [API Keys and Scopes](/docs/api-keys-and-scopes) -- API key management
- [REST API Reference](/docs/rest-api-reference) -- Underlying REST API
