> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tracia.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Overview

> Execute LLM prompts directly against providers with automatic tracing

The `runLocal()` method lets you execute prompts directly against OpenAI, Anthropic, Google, or Amazon Bedrock while keeping your prompts in your codebase. You get full observability through Tracia without any added latency.

```typescript theme={null}
import { Tracia } from 'tracia';

const tracia = new Tracia({ apiKey: process.env.TRACIA_API_KEY });

const result = await tracia.runLocal({
  model: 'gpt-4o',
  messages: [
    { role: 'system', content: 'You are a helpful assistant.' },
    { role: 'user', content: 'Hello!' }
  ]
});

console.log(result.text);
```

## Why runLocal()?

Some teams prefer managing prompts in their codebase rather than in an external dashboard. This keeps prompts:

* Version-controlled with your application code
* Reviewed through your standard PR process
* Deployed alongside the code that uses them
* Constructed programmatically when needed

`runLocal()` gives you full Tracia observability while respecting this workflow.

## How It Works

When you call `runLocal()`, the SDK:

1. **Calls the provider SDK directly** - Your request goes straight to OpenAI, Anthropic, Google, or Amazon Bedrock using their native SDK. Tracia is not in the request path.

2. **Sends the trace asynchronously** - After the LLM responds, trace data is sent to Tracia in the background. This is non-blocking and adds zero latency to your application.

|                             | `prompts.run()`         | `runLocal()`           |
| --------------------------- | ----------------------- | ---------------------- |
| **Prompts stored in**       | Tracia dashboard        | Your codebase          |
| **LLM call routed through** | Tracia API              | Direct to provider SDK |
| **Trace creation**          | Automatic (server-side) | Async, non-blocking    |

## When to Use runLocal() vs prompts.run()

**Use `runLocal()` when you want to:**

* Keep prompts in your codebase, version-controlled with git
* Build prompts programmatically (e.g., assembling messages based on context)
* Prototype quickly without dashboard setup
* Use Tracia purely for observability

**Use `prompts.run()` when you want to:**

* Edit prompts without code deployments
* A/B test prompt versions from the dashboard
* Let non-engineers manage prompt content
* Track prompt versions separately from code versions

| Use Case                             | Recommended Method |
| ------------------------------------ | ------------------ |
| Prompts managed in Tracia dashboard  | `prompts.run()`    |
| Prompts defined in code              | `runLocal()`       |
| Prompts reviewed in PRs              | `runLocal()`       |
| Quick prototyping                    | `runLocal()`       |
| A/B testing prompt versions          | `prompts.run()`    |
| Programmatically constructed prompts | `runLocal()`       |
| Non-technical prompt editors         | `prompts.run()`    |

## Quick Examples

<CodeGroup>
  ```typescript OpenAI theme={null}
  const result = await tracia.runLocal({
    model: 'gpt-4o',
    messages: [
      { role: 'user', content: 'Explain quantum computing in simple terms.' }
    ],
    temperature: 0.7
  });
  ```

  ```typescript Anthropic theme={null}
  const result = await tracia.runLocal({
    model: 'claude-sonnet-4-20250514',
    messages: [
      { role: 'user', content: 'Write a haiku about programming.' }
    ],
    maxOutputTokens: 100
  });
  ```

  ```typescript Google theme={null}
  const result = await tracia.runLocal({
    model: 'gemini-2.0-flash',
    messages: [
      { role: 'user', content: 'What are the benefits of TypeScript?' }
    ]
  });
  ```

  ```typescript Amazon Bedrock theme={null}
  const result = await tracia.runLocal({
    model: 'amazon.nova-lite-v1:0',
    messages: [
      { role: 'user', content: 'What are the benefits of cloud computing?' }
    ]
  });
  ```

  ```typescript Streaming theme={null}
  const stream = tracia.runLocal({
    model: 'gpt-4o',
    messages: [{ role: 'user', content: 'Write a poem' }],
    stream: true,
  });

  for await (const chunk of stream) {
    process.stdout.write(chunk);
  }

  const result = await stream.result;
  console.log('Tokens:', result.usage.totalTokens);
  ```
</CodeGroup>

## Available Methods

<CardGroup cols={2}>
  <Card title="Basic Usage" icon="play" href="/sdk-node/run-local/basic-usage">
    Getting started with each provider
  </Card>

  <Card title="Streaming" icon="bolt" href="/sdk-node/run-local/streaming">
    Real-time streaming responses
  </Card>

  <Card title="Sessions" icon="link" href="/sdk-node/run-local/sessions">
    Automatic trace chaining for multi-turn
  </Card>

  <Card title="Parameters" icon="sliders" href="/sdk-node/run-local/parameters">
    Complete RunLocalInput reference
  </Card>

  <Card title="Response" icon="arrow-right-from-bracket" href="/sdk-node/run-local/response">
    RunLocalResult fields and usage
  </Card>

  <Card title="Providers" icon="plug" href="/sdk-node/run-local/providers">
    OpenAI, Anthropic, Google, Bedrock setup
  </Card>

  <Card title="Models" icon="microchip" href="/sdk-node/run-local/models">
    94+ supported models by provider
  </Card>

  <Card title="Variables" icon="code" href="/sdk-node/run-local/variables">
    Template interpolation syntax
  </Card>

  <Card title="Tracing" icon="chart-line" href="/sdk-node/run-local/tracing">
    Background traces, flush(), error handling
  </Card>

  <Card title="Responses API" icon="brain" href="/sdk-node/run-local/responses-api">
    OpenAI reasoning models (o1, o3-mini)
  </Card>

  <Card title="Advanced" icon="gear" href="/sdk-node/run-local/advanced">
    Error handling, concurrent requests
  </Card>
</CardGroup>

## Types

### LLMProvider

```typescript theme={null}
enum LLMProvider {
  OPENAI = 'openai',
  ANTHROPIC = 'anthropic',
  GOOGLE = 'google',
  AMAZON_BEDROCK = 'amazon_bedrock',
}
```

### RunLocalInput

```typescript theme={null}
interface RunLocalInput {
  // Required
  messages: LocalPromptMessage[];
  model: string;

  // Streaming
  stream?: boolean;     // When true, returns LocalStream instead of Promise
  signal?: AbortSignal; // Cancel the request (streaming only)

  // Provider override (for custom/new models)
  provider?: 'openai' | 'anthropic' | 'google' | 'amazon_bedrock';

  // LLM configuration
  temperature?: number;
  maxOutputTokens?: number;
  topP?: number;
  stopSequences?: string[];
  timeoutMs?: number;
  customOptions?: Partial<Record<LLMProvider, Record<string, unknown>>>;  // Provider-specific options

  // Tool calling
  tools?: ToolDefinition[];
  toolChoice?: ToolChoice;

  // Variable interpolation
  variables?: Record<string, string>;

  // Provider API key override
  providerApiKey?: string;

  // Span options
  tags?: string[];
  userId?: string;
  sessionId?: string;
  sendTrace?: boolean;  // default: true (sends span to Tracia)
  spanId?: string;      // custom span ID (sp_ + 16 hex chars)
  traceId?: string;     // group related spans together (session)
  parentSpanId?: string;  // link to parent span
}
```

### RunLocalResult

```typescript theme={null}
interface RunLocalResult {
  text: string;
  spanId: string;         // Unique ID for this span
  traceId: string | null; // Session ID if part of multi-turn conversation
  latencyMs: number;
  usage: {
    inputTokens: number;
    outputTokens: number;
    totalTokens: number;
  };
  cost: number | null;
  provider: 'openai' | 'anthropic' | 'google' | 'amazon_bedrock';
  model: string;
  toolCalls: ToolCall[];
  finishReason: 'stop' | 'max_tokens' | 'tool_calls';
  message: LocalPromptMessage;  // For easy round-tripping in multi-turn
}
```

### LocalStream

When `stream: true` is set, `runLocal()` returns a `LocalStream`:

```typescript theme={null}
interface LocalStream {
  // Span ID available immediately
  readonly spanId: string;

  // Trace ID (session) if provided
  readonly traceId: string | null;

  // Iterate to receive text chunks
  [Symbol.asyncIterator](): AsyncIterator<string>;

  // Final result after stream completes
  readonly result: Promise<StreamResult>;

  // Cancel the stream
  abort(): void;
}
```

### LocalPromptMessage

```typescript theme={null}
interface LocalPromptMessage {
  role: 'system' | 'user' | 'assistant' | 'tool';
  content: string | ContentPart[];
  toolCallId?: string;  // Required for 'tool' role
  toolName?: string;    // Required for 'tool' role
}

// Content parts for assistant messages with tool calls
type ContentPart = TextPart | ToolCallPart;

interface TextPart {
  type: 'text';
  text: string;
}

interface ToolCallPart {
  type: 'tool_call';
  id: string;
  name: string;
  arguments: Record<string, unknown>;
}
```
