# Integrations

> @faustine-ai/browser-sandbox documentation · https://browser-sandbox.faustine.ai/docs/integrations/ · source: README.md on GitHub (https://github.com/faustine-ai/browser-sandbox)

Faustine built this library for its own code mode in the browser, where
the agent's program runs on the customer's page. It is meant for custom
code mode implementations like that one, for the code mode libraries
below, and for any other system, agentic loop or not, that has to run
agent-generated code in the browser.

## AI SDK (`useChat`, `Chat`)

The AI SDK has one `onToolCall` per chat and answers through
`addToolOutput`. The sandbox's tool is one entry in a map you build here;
the rest of your client tools keep working.

```ts
import { createSandbox, defineFunctions } from '@faustine-ai/browser-sandbox';
import { runCodeTool, clientTools, fromTools } from '@faustine-ai/browser-sandbox/ai';

const sandbox = createSandbox({ frame: { url: '/sandbox' }, warm: true });

const functions = defineFunctions({
  ...fromTools(myClientTools, { namespace: 'app' }),        // AI SDK tools with `execute` → sdk.app.<name>
  'orders.list':   (input) => api.orders.list(input),
  'orders.cancel': { call: (input) => api.orders.cancel(input), approval: true },
});

const runCode = runCodeTool({
  sandbox, functions,
  approval: { mode: 'collect', onApproval: (pending) => showBatchCard(pending) },
});

const tools = clientTools({
  runCode,                                                  // the sandbox's tool (name "runCode")
  getLocation: async () => geo.current(),                   // your own client tools
  confirmPayment: 'external',                               // answered later by your UI
});

const chat = useChat({ transport, onToolCall: tools.onToolCall });
tools.attach(chat);                                         // hands the helper addToolOutput
```

- Dispatch is by `toolCall.toolName`. A plain function runs and its value
  goes to `addToolOutput`; `'external'` is left alone for your UI; an
  unknown name is logged and never answered. Dynamic tools dispatch by
  name too.
- Outputs produced before `attach` are delivered when you attach.
- With your own `onToolCall`, skip `clientTools` and call
  `runCode.handle(toolCall)` from your `switch`.
- `fromTools` maps `needsApproval: true` to `approval: true`; inside the
  sandbox the run's approval mode governs it.

On the server, `runCode` is a tool without `execute` (the client answers):

```ts
tools: {
  runCode: tool({
    description: 'Runs JavaScript in the user\'s browser against `sdk`. Return the value you need.',
    inputSchema: z.object({ code: z.string() }),
  }),
}
```

Put `describe(functions)` in the system prompt so the model writes the
names the code will find.

**Isn't code mode already in the AI SDK?** On the server. The program of
`@ai-sdk/code-mode` runs in QuickJS inside a Node worker, "is not
available in browser or edge runtimes", and reaches server tools only. In
the browser the AI SDK gives you client tools and nothing that runs a
program against them; `runCode` is that piece. The two can combine in one
chat: server tools behind `code_mode`, page functions behind `runCode`.

## Cloudflare `@cloudflare/codemode`

Cloudflare's `createCodeTool` owns the prompt and the tool wiring and
delegates the run to an `Executor`. It ships two: Dynamic Workers on the
server, and `IframeSandboxExecutor` for the browser, an iframe without a
worker, which cannot stop a synchronous loop (documented, 30 s timeout),
needs `'unsafe-inline'` in its CSP and has no approval hook.
`asExecutor(sandbox)` is a third executor for the same `createCodeTool`:
a worker it can terminate, a frame that works under a strict CSP, and the
approval modes. Their server executor stays for server tools.

```ts
import { asExecutor } from '@faustine-ai/browser-sandbox/codemode';

const executor = asExecutor(sandbox);                        // Executor { execute(code, fns) }
const codemode = createCodeTool({ tools, executor });
```

A plain record of functions is exposed as `codemode.<name>(...args)`;
providers as `codemode.<provider>.<fn>`. `asExecutor(sandbox, { root,
needsApproval, approval, caps })` for the policies.

## TanStack AI

TanStack's `createCodeMode` writes the prompt and compiles the bindings;
the program runs through a pluggable `IsolateDriver`, and the driver it
ships is QuickJS compiled to WASM, with no approval step.
`asIsolateDriver(sandbox)` is a driver for the same `createCodeMode`: the
page's own engine instead of a second one, structured clone instead of
re-encoding `File` and `Blob` by hand, about 8 KB instead of a 1 MB WASM
payload, and the approval modes. Their QuickJS driver stays the choice on
the server or when you want an engine separate from the page's.

```ts
import { asIsolateDriver } from '@faustine-ai/browser-sandbox/tanstack';

createCodeMode({ tools, driver: asIsolateDriver(sandbox) });
```

Bindings become bare `external_<name>(input)` functions, as TanStack's
generated code expects. `createContext({ timeout })` maps to `timeoutMs`.
