Browser & Mobile Runtimes

Use the PraisonAI TypeScript SDK inside Tauri, React Native, browser webviews, Deno, Bun, and edge runtimes

The PraisonAI TypeScript SDK runs in any JavaScript runtime — not just Node. Pass the API key through the Agent config, and the same code that runs on your server runs inside a Tauri app, a React Native mobile app, a browser webview, Deno, Bun, or a Cloudflare Worker.

Diagram

One codebase, many runtimes

📝 new Agent&(…&)

🌐 JS Runtime

🖥️ Node.js

💻 Tauri Desktop

📱 React Native

🌍 Browser

⚡ Deno / Bun / Workers

Quick Start

  1. Create an agent in a browser bundle

    Pass the API key explicitly — a browser bundle has no process.env.

    typescript
    import { Agent } from 'praisonai';
    
    const agent = new Agent({
      instructions: 'You are a helpful assistant',
      llm: 'gpt-4o-mini',
    });
    
    const answer = await agent.start('Say hello');
    console.log(answer);

Choosing Where to Run

Pick the runtime that matches how your agent ships.

Diagram

Yes

No

Desktop app

Mobile app

Browser

Where does your agent run?

Server-side only?

Use Node / Bun / Deno
Read env via process.env

Ships to user devices?

Tauri / Electron
Pass API key from Rust/Node side

React Native
Fetch ephemeral token from your backend

Browser
Proxy through your backend


What Changed

The Agent constructor now works on runtimes without a process global.

Previously the constructor read process.env.OPENAI_MODEL_NAME, PRAISONAI_MODEL, PRAISON_VERBOSE, and PRAISON_PRETTY directly. On any runtime without a process global (Tauri webview, React Native, plain browser), the very first new Agent(...) threw ReferenceError: process is not defined — before your code ever ran.

Now those reads go through an internal getEnv() helper that returns undefined when there is no process. Constructors succeed, defaults apply (gpt-4o-mini, verbose on, pretty off), and any explicit config value still wins.

Streaming also survives: the default token sink (writeTokenToStdout) no-ops when process.stdout is unavailable, so agent.start() and agent.stream() no longer die on the first token in a webview.


Runtime Interaction Flow

A single agent call streams tokens straight into your UI.

Diagram
🧠 LLM API🤖 Agent📱 App UI👤 User🧠 LLM API🤖 Agent📱 App UI👤 UserConstructor works — no process neededTap “Ask”new Agent&({ llm, apiKey }&)agent.start&(prompt&)HTTPS requeststreamed tokensonToken callback per tokenRender tokens live

Passing API Keys Per Runtime

Read the key where each runtime keeps it, then pass it to the Agent.

RuntimeWhere to read the keyPattern
Node.js / Bun / Denoprocess.env (or Deno.env)Unchanged — set env var as before
TauriRead in Rust, pass to JS via invokenew Agent({ apiKey: await invoke('get_key') })
React NativeFetch ephemeral token from your backendnew Agent({ apiKey: token, llm: 'openai/gpt-4o-mini' })
BrowserProxy through your backendPoint baseURL at your own edge function
Cloudflare WorkersWorker secrets bindingRead from env.OPENAI_API_KEY in the handler, pass to Agent

Minimal Tauri Example

Read the key in Rust, hand it to the renderer, and construct the agent.

typescript
import { invoke } from '@tauri-apps/api/core';
import { Agent } from 'praisonai';

const apiKey = await invoke<string>('get_openai_key');

const agent = new Agent({
  instructions: 'You are a coding assistant',
  llm: 'openai/gpt-4o-mini',
  apiKey,
});

await agent.start('Explain closures in one paragraph');

Minimal React Native Example

Fetch an ephemeral token from your backend, then run the agent on-device.

typescript
import { Agent } from 'praisonai';

async function ask(prompt: string) {
  const { token } = await fetch('https://your-backend.example/agent-token')
    .then(r => r.json());

  const agent = new Agent({
    instructions: 'You are a mobile helper',
    llm: 'openai/gpt-4o-mini',
    apiKey: token,
  });

  return await agent.start(prompt);
}

Streaming Without stdout

Use stream() and render each chunk into the UI instead of the terminal.

typescript
const agent = new Agent({
  instructions: 'You are helpful',
  llm: 'openai/gpt-4o-mini',
  apiKey,
});

const tokens: string[] = [];
for await (const chunk of agent.stream('Write a haiku')) {
  tokens.push(chunk);
  updateUI(tokens.join(''));  // your renderer
}

Best Practices

Never ship raw API keys to a client build

Proxy every request or mint an ephemeral token from your own backend. A key bundled into a browser or mobile build is public.

Set llm explicitly

The gpt-4o-mini default only applies when the env is unreachable and you passed no llm. Set llm so behaviour is identical across every runtime.

Prefer stream() in UI runtimes

The default token sink is silent when there is no stdout. Use stream() (or pass onToken to start()) to render tokens live in the UI.

Cancel long streams

Pass an AbortSignal through SimpleAgentConfig.signal or stream(prompt, { signal }), and abort it when the user leaves the screen to stop the provider request.


Troubleshooting

'process is not defined'

You’re on a pre-fix build. Update praisonai to the release that ships the getEnv() guard.

No LLM response, no error

You didn’t pass an apiKey and the runtime has no env. Check your Agent config.

Tokens don't appear

You called start() without onToken. Use stream() or supply an onToken callback.


Related