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

# Browser & Webview Runtimes

> Run PraisonAI Agents inside browsers, Electron, Tauri, and React Native

PraisonAI Agents run anywhere JavaScript runs — browsers, Electron, Tauri webviews, and React Native — with zero extra setup.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
  subgraph "PraisonAI Agent — everywhere JS runs"
    Node[🖥️ Node] --> Agent[🤖 Agent]
    Browser[🌐 Browser] --> Agent
    Electron[💻 Electron] --> Agent
    Tauri[🪟 Tauri Webview] --> Agent
    RN[📱 React Native] --> Agent
    Agent --> OpenAI[🧠 OpenAI SDK]
  end
  classDef in fill:#6366F1,stroke:#7C90A0,color:#fff
  classDef core fill:#8B0000,stroke:#7C90A0,color:#fff
  classDef out fill:#10B981,stroke:#7C90A0,color:#fff
  class Node,Browser,Electron,Tauri,RN in
  class Agent core
  class OpenAI out
```

## Quick Start

The runtime is detected automatically — pass credentials directly on the Agent.

**1. Browser / Electron renderer (auto-detected)**

The browser guard is enabled for you — no config needed.

```typescript theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import { Agent } from 'praisonai';

const agent = new Agent({
  instructions: "You are a helpful assistant",
  apiKey: import.meta.env.VITE_OPENAI_KEY,
});

await agent.chat("Hello from the browser!");
```

**2. Tauri / native fetch bridge**

Pass a custom `fetch` to route requests through native code — the key stays out of the JS heap.

```typescript theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import { Agent } from 'praisonai';
import { invoke } from '@tauri-apps/api/core';

const nativeFetch: typeof fetch = async (input, init) => {
  const body = await invoke<string>('openai_proxy', {
    url: String(input),
    init,
  });
  return new Response(body, { status: 200 });
};

const agent = new Agent({
  instructions: "You are the desktop assistant",
  fetch: nativeFetch,   // implies dangerouslyAllowBrowser
  // no apiKey here — the key lives in Rust
});
```

**3. Explicit override**

Force the browser guard on or off — useful in tests.

```typescript theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import { Agent } from 'praisonai';

const agent = new Agent({
  instructions: "You are helpful",
  apiKey: process.env.OPENAI_API_KEY,
  dangerouslyAllowBrowser: true,
});
```

***

## How It Works

The Agent detects the runtime and merges the right options before constructing the OpenAI SDK.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
  participant User
  participant Agent
  participant Helper as buildOpenAIClientOptions
  participant SDK as OpenAI SDK
  User->>Agent: new Agent({ apiKey, fetch? })
  Agent->>Helper: options + runtime hints
  Helper->>Helper: detect window / RN / custom fetch
  Helper-->>Agent: merged options (± dangerouslyAllowBrowser)
  Agent->>SDK: new OpenAI(mergedOptions)
  SDK-->>Agent: client ready (no throw)
```

| Runtime | Detected as | Flag added |
| - | - | - |
| Node | `process` present, no `window` | none — behaviour unchanged |
| Browser / Electron renderer | `window` + `window.document` | `dangerouslyAllowBrowser: true` |
| Embedded webview (Tauri) | `window` + `window.document` | `dangerouslyAllowBrowser: true` |
| React Native | `navigator.product === 'ReactNative'` | `dangerouslyAllowBrowser: true` |
| Custom `fetch` supplied | any runtime | `dangerouslyAllowBrowser: true` + injected `fetch` |

***

## When to use which option

Pick the option that matches where your code runs and how sensitive the key is.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
  Start{Where does the code run?} -->|Node server| Node[Do nothing — Node path unchanged]
  Start -->|Browser / Electron / webview / RN| Q1{Is the API key safe in the JS heap?}
  Q1 -->|No — production mobile/desktop| Fetch[Pass a custom fetch → routes via native code]
  Q1 -->|Yes — internal tool / demo| Auto[Auto-detected; nothing to pass]
  Q1 -->|Force behaviour for tests| Explicit[Set dangerouslyAllowBrowser explicitly]
  classDef q fill:#F59E0B,stroke:#7C90A0,color:#fff
  classDef a fill:#10B981,stroke:#7C90A0,color:#fff
  class Start,Q1 q
  class Node,Fetch,Auto,Explicit a
```

***

## Configuration

Four knobs control credentials and transport across every runtime.

| Option | Type | Default | Description |
| - | - | - | - |
| `apiKey` | `string` | `undefined` (falls back to `OPENAI_API_KEY`) | Per-agent OpenAI key. |
| `baseURL` | `string` | `undefined` | Per-agent base URL for OpenAI-compatible endpoints. |
| `fetch` | `typeof fetch` | `undefined` | Custom transport. Implies `dangerouslyAllowBrowser`. |
| `dangerouslyAllowBrowser` | `boolean` | auto-detected | Force-enable the SDK's browser guard. Auto-`true` in browser-like runtimes. |

Precedence: an explicit `dangerouslyAllowBrowser` always wins — `false` even strips a pre-set flag. A custom `fetch` implies `dangerouslyAllowBrowser: true`, so a native bridge works even outside a webview.

> [card] [buildOpenAIClientOptions Reference](https://praison.ai/docs/docs/sdk/reference/typescript/functions/buildOpenAIClientOptions)
>
> TypeScript helper that merges runtime-aware options

***

## Common Patterns

### Tauri desktop app

Route every OpenAI request through a Rust command that owns the key.

```typescript theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import { Agent } from 'praisonai';
import { invoke } from '@tauri-apps/api/core';

const nativeFetch: typeof fetch = async (input, init) => {
  const body = await invoke<string>('openai_proxy', {
    url: String(input),
    init,
  });
  return new Response(body, { status: 200 });
};

const agent = new Agent({
  instructions: "You are the desktop assistant",
  fetch: nativeFetch,
});

await agent.chat("Summarize today's notes");
```

### Electron renderer

Talk directly to OpenAI from the renderer — the guard is auto-added.

```typescript theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import { Agent } from 'praisonai';

const agent = new Agent({
  instructions: "You are the in-app assistant",
  apiKey: import.meta.env.VITE_OPENAI_KEY,
});

await agent.chat("Draft a release note");
```

### React Native mobile app

`navigator.product === 'ReactNative'` is auto-detected.

```typescript theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import { Agent } from 'praisonai';

const agent = new Agent({
  instructions: "You are the mobile assistant",
  apiKey: MY_APP_CONFIG.openaiKey,
});

await agent.chat("What's on my agenda?");
```

***

## Best Practices

> [accordion] Prefer injectable fetch over dangerouslyAllowBrowser in production
>
> A custom `fetch` routes requests through native code, keeping the API key out of the JS heap. Reserve `dangerouslyAllowBrowser` for internal tools and demos.

> [accordion] Never bundle the API key into a shipped webview build
>
> Anything in the JS bundle is readable. In production Tauri / Electron / mobile apps, keep the key in native code and expose only a proxy command.

> [accordion] Use a per-agent apiKey for multi-tenant apps
>
> When multiple agents talk to different tenants or endpoints, set `apiKey` and `baseURL` per agent instead of relying on a single shared environment variable.

> [accordion] Guard process.env access in shared code
>
> Reading `process.env` throws in webviews and React Native where `process` is absent. The SDK guards its own access; do the same in code you share across runtimes.

***

## Related

> [card] [Agent](https://praison.ai/docs/js/agent.md)
>
> Per-agent apiKey, baseURL, and fetch

> [card] [Providers](https://praison.ai/docs/js/providers.md)
>
> fetch and dangerouslyAllowBrowser on ProviderConfig

> [card] [Desktop Engine Origin Gate](https://praison.ai/docs/features/desktop/api.md#browser-origin-gate)
>
> Why an embedded Tauri / Electron webview's origin must be on the engine's allowed list


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.