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

# Embed an agent on your website

> Configure a public embed token or use the authenticated text-chat API.

Athena has two ways to add text interaction to a site: the generated public widget uses an embed token, while a server-side integration can create text-chat sessions with an API key. Both can start model work and create runs. A token or successful HTTP response does not prove the full browser conversation works, so test the complete flow on a controlled page.

## Configure the public widget

Create and test the agent first. Open its embed settings and create a token with the narrowest allowed website domains that fit your deployment. The token settings can also include widget settings, a usage limit, and an expiration period. A workflow has one active embed token; creating or updating that token changes its public embed configuration.

The current widget integration uses `dograh-widget.js` and `data-dograh-context`; preserve those attribute and script names because they are part of the integration contract. Check the script URL before installing the generated snippet.

> [!WARNING]
>
> The hosted API can currently generate a snippet whose script host is `http://127.0.0.1:3002`. That address only reaches the visitor's own computer, so the widget will not load for your visitors. In the snippet's `js.src` value, replace that origin with `https://athena.tryopencomputer.com`, keeping `/embed/dograh-widget.js`, the token, and the other query parameters. The `apiEndpoint` value must also point to `https://athena.tryopencomputer.com`. This correction has been exercised with the text chat widget; browser voice requires its own microphone and audio check.

**1. Set allowed domains**

Enter the origins where the widget should load. Include the real scheme and host used by your deployed page, and avoid broad wildcards unless you need them.

**2. Install the generated snippet**

Copy the snippet into the page or site template that should show the widget. Do not put an organization API key in browser code.

**3. Test both origin cases**

Open the page on an allowed origin and confirm the widget can initialize. Test a disallowed origin as well to confirm it is rejected.

**4. Exercise a full session**

Send a synthetic message, verify the response, and end the session. For voice, also check microphone permission and two-way audio in the target browser.

The embed-token management API supports `allowed_domains`, `settings`, `usage_limit`, and `expires_in_days`. Updating the configuration keeps the same token string. Calling create-or-update after revocation reactivates that token; it does not rotate it, and previously installed snippets can regain access under the new settings.

End active sessions before revoking the token. Revocation rejects new access and subsequent requests from existing sessions, but it does not complete their stored chat runs.

## Choose widget type and layout

In **Settings → Add to Website**, enable embedding and choose **Widget Type**: a voice agent or text chat. Set the allowed domains before installing the snippet. For text chat, set the available inactivity timeout if your session policy needs one, then save the configuration.

Under **Embed Mode**, choose:

| Mode | Setup |
| - | - |
| Floating | Set button text/color and the corner position, then install the generated snippet. |
| Inline | Add the generated container, normally `<div id="dograh-inline-container"></div>`, where the widget should appear, give it sufficient height, and install the matching snippet. |
| Headless | Install the script, render your own controls, and bind them to the widget methods after the script has loaded. |

Use the text fields shown for the selected widget to customize its labels, chat panel, voice panel, or call-to-action text. Preview the appearance, save, then check it on the actual allowed website origin. A dashboard preview does not establish origin authorization or audio readiness.

### Headless controls

Wait until `window.DograhWidget` is available before binding controls. For voice, call `start()` directly from a user click so the browser can request microphone access, and call `end()` to stop. Subscribe to `onCallStart`, `onCallEnd`, `onStatusChange`, and `onError` to update your interface. The voice status values include `idle`, `connecting`, `connected`, and `failed`.

For text, use `startChat()`, `sendMessage(text)`, and `endChat()`, and subscribe to `onChatStateChange` and `onMessage`. Disable duplicate sends while a reply is pending and show ended, expired, and error states to the visitor. Use `setContext({...})` before starting when the page learns visitor details after load. Browser context remains untrusted input.

The generated headless examples in the dashboard show the selected mode's integration. Preserve the `DograhWidget` global name for compatibility. Check script load, session start, a complete response, and session end; for voice, verify two-way audio in the target browser.

## Pass visitor context

The widget can send initial context through `data-dograh-context`. Keep the supplied keys aligned with the workflow's prompt and templates. Treat every browser-provided value as untrusted input: do not include secrets or use visitor context as authorization. See [Context and variables](https://docs.tryopencomputer.com/guides/context.md).

## Use server-managed text sessions

For an integration you control on the server, use the authenticated text-chat API with your numeric `workflow_id`. Send the organization API key only from your backend. The [Text chat sessions and streaming guide](https://docs.tryopencomputer.com/guides/text-chat.md) covers session creation and recovery, revision checks, POST-based SSE, rewind, and end behavior.

## Public widget streams

The public embed API initializes a session using the embed token, then uses the short-lived session token for visitor messages. Its message stream is designed for the visitor-facing response; do not expect it to expose private tool output or internal workflow errors. Keep any backend-only processing behind your own authenticated service.

For a custom text client that uses the public embed token, the route sequence is:

| Action | Path |
| - | - |
| Read widget configuration | `GET /api/v1/public/embed/config/{token}` |
| Create a session | `POST /api/v1/public/embed/init` or `POST /api/v1/public/embed/init/stream` |
| Read the session | `GET /api/v1/public/embed/chat/{session_token}` |
| Send a message | `POST /api/v1/public/embed/chat/{session_token}/messages` or `POST /api/v1/public/embed/chat/{session_token}/messages/stream` |
| End the session | `POST /api/v1/public/embed/chat/{session_token}/end` |

The public token and session token are for the public embed flow and are not a substitute for a backend API key. Keep their allowed origin restrictions configured, and test the token's actual session path before launch.

Before launch, test token initialization, allowed-origin behavior, a complete chat or voice conversation, and session completion in the browsers your visitors use. After revoking a token, confirm the installed widget can no longer start a session.


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