# Build with ARBI

Use an existing ARBI deployment and account. You do not need to run the backend or clone
this monorepo to use the SDK. Your account needs access to the workspace you choose.
For a first Node integration, use an account with password sign-in; an SSO-only deployment
needs its existing SSO/session integration rather than a password workaround.

Choose one starting point:

| You want | Start here |
| --- | --- |
| Call ARBI from a script or service | [Node](#node) |
| Add a chat widget to a React app | [React](#react) |
| Add chat to a website without a build pipeline | [Website iframe](#website-iframe) |
| Control state and render your own UI | `@arbidocs/react` hooks and React Query; see the [React package](https://www.npmjs.com/package/@arbidocs/react) |

Start with the default/current workspace. Selecting a different workspace is an explicit
application choice. A configuration (`cfg-`) chooses behavior; an agent (`agt-`) is an
identity. Neither a model selection nor signing in grants workspace access.

## Node

Use Node 22.22+ with its bundled npm. Install in an empty directory:

```sh
npm init -y
npm install @arbidocs/sdk
```

Create a private `.env` file (keep it out of source control):

```dotenv
ARBI_URL=https://YOUR-ARBI-DEPLOYMENT
ARBI_EMAIL=you@example.com
ARBI_PASSWORD=your-account-password
ARBI_WORKSPACE_ID=wrk-YOUR-WORKSPACE
```

Use the deployment's public URL, without `/v1`. The workspace ID is the `wrk-` ID of a
workspace you can open in ARBI; after login, `await arbi.workspaces.list()` also lists your
available workspaces. If your API hostname differs from the account/key-derivation domain,
supply that deployment's public `deploymentDomain` setting when constructing `Arbi`.

Save this as `index.mjs`:

```js
import { Arbi } from '@arbidocs/sdk'

const arbi = new Arbi({ url: process.env.ARBI_URL })
await arbi.login(process.env.ARBI_EMAIL, process.env.ARBI_PASSWORD)
try {
  await arbi.selectWorkspace(process.env.ARBI_WORKSPACE_ID)
  const response = await arbi.responses.create({ input: 'Say hello in one sentence.' })
  if (response.status !== 'completed') throw new Error(`Response ${response.id}: ${response.status}`)
  console.log(response.output_text)
} finally {
  await arbi.logout()
}
```

Run it:

```sh
node --env-file=.env index.mjs
```

Expected result: one line of assistant text. No browser storage polyfill or framework is needed.
Keep the `.mjs` extension so Node treats the file as a module.

To stream, replace the response call with:

```js
const stream = await arbi.responses.create({ input: 'Say hello.', stream: true })
for await (const event of stream) {
  if (event.type === 'response.output_text.delta') process.stdout.write(event.delta)
  if (event.type === 'response.failed') throw new Error(`Response ${event.response.id} failed`)
}
```

A disconnected reader throws. Breaking the loop detaches your reader; it does not cancel server
execution. Use `responses.cancel(id)` to request cancellation. For follow-ups, send
`previous_response_id: response.id`. One response is `msg-`; a conversation can contain many responses.

The installed package includes runnable [streaming](../examples/stream-response.mjs),
[structured extraction](../examples/structured-extraction.mjs), and
[background inspection](../examples/background-response.mjs) examples. They use the same `.env`
variables; run, for example, `node --env-file=.env node_modules/@arbidocs/sdk/examples/stream-response.mjs`.

## React

The npm SDK package includes a standalone React starter. In an empty directory:

```sh
npm install @arbidocs/sdk
cp -R node_modules/@arbidocs/sdk/examples/react-chat ./my-arbi-chat
cd my-arbi-chat
mv gitignore .gitignore
npm install
cp .env.example .env
# Set VITE_ARBI_URL to your ARBI deployment's public URL.
npm run dev
```

`my-arbi-chat` is an independent app: move it into your own repository and keep `.env` private.
These steps require the SDK release that includes this guide; `0.5.62` predates the packaged
React starter. The existing minimal app has also been verified against published `0.5.62` packages.

It renders the shared widget:

```tsx
import { ArbiChat } from '@arbidocs/blocks/embed'

export function App() {
  return <div style={{ height: 640 }}><ArbiChat apiUrl="https://YOUR-ARBI-DEPLOYMENT" /></div>
}
```

The example supplies the dependencies and Tailwind/Blocks stylesheet order. Keep all `@arbidocs`
packages on matching versions. Sign in inside the widget and choose a workspace explicitly;
never put passwords or session tokens in `VITE_` variables. The deployment must allow your app's
origin for API calls. SSO needs the deployment's existing supported callback/popup configuration.

To deploy: set `VITE_ARBI_URL`, run `npm run build`, and serve `dist/` on a static host. The URL is
public build configuration; no custom server is required by this example.

An app already using `ArbiHost` should use `ConnectedEmbeddedChat` inside that host, sharing its
session, current workspace and React Query cache. Do not create a second standalone widget to
bypass the host's workspace choice.

## Website iframe

Use your ARBI **frontend** origin:

```html
<iframe
  src="https://YOUR-ARBI-FRONTEND/embed/chat"
  title="ARBI chat"
  style="width:380px;height:640px;border:0"
  allow="clipboard-write"
></iframe>
```

The panel owns sign-in, workspace choice and chat. This is authenticated workspace chat. The
parent page needs no ARBI packages, credentials or workspace keys. Your deployment must allow
this site to frame the embed route; the parent site's CSP must allow the frontend in `frame-src`.
Embedded storage restrictions can require a separate sign-in. Configure framing only for the embed route; keep restrictions on the API and other routes.
For host integration, use the connected widget described above.

## If something fails

| Symptom | Check |
| --- | --- |
| Login fails | Correct deployment URL and account domain? Password sign-in supported? Do not auto-register or disable SSO to recover. |
| No workspace selected / access denied | Sign in, list available workspaces, then explicitly select one you can open. Configuration or agent selection does not grant access. |
| Browser API requests blocked | Deployment CORS allowlist includes the app's exact origin. Never put a privileged server credential in the browser to bypass this. |
| Iframe blocked | Deployment `frame-ancestors` and parent `frame-src` permit the embed. Keep restrictions on other routes. |
| Structured output rejected | Check [supported modes](compatibility.md); native-agent and slash/delegation paths currently reject JSON Schema requests explicitly. |
| Request failed / stream disconnected | Keep error `code`, `status`, `requestId` and `responseId` when available. Inspect or attach to the existing response before creating another task. Do not log credentials or chat content. |

See the [compatibility table](compatibility.md) before moving an existing OpenAI, Vercel or Claude
integration. Familiar methods do not imply that every provider's fields or tool protocol are supported.


## Troubleshooting and human review

Use `await arbi.diagnose()` or `arbi doctor --json` before changing configuration. See
[setup-diagnostics.md](./setup-diagnostics.md) for browser network limitations and workspace checks.
The package also includes `examples/human-review`: an explicit approve/send-back example that
keeps the existing `con-` conversation and resumes it across separate invocations.

The React starter uses one `@arbidocs/blocks/styles.css` import and ordinary Vite; no Tailwind
plugin or application stylesheet is required. Customize the Blocks theme tokens and component
props when desired, starting from the supplied defaults.
