# Onyx Usage Examples: Chat Widgets and Assistants API Automation

> Explore Onyx usage examples including a chat widget and Assistants API automation. Learn to create sessions send messages and stream responses from the Onyx backend.

- Repository: [Onyx/onyx](https://github.com/onyx-dot-app/onyx)
- Tags: tutorial
- Published: 2026-03-28

---

**The onyx-dot-app/onyx repository provides two primary usage examples—a ready-to-embed chat widget and a Python Assistants API client—that demonstrate how to create sessions, send messages, and stream retrieval-augmented responses from the Onyx backend.**

The onyx-dot-app/onyx repository ships with concrete implementation examples that illustrate how to integrate with the platform's search-augmented AI capabilities. These Onyx usage examples cover both frontend embedding via a web component and backend automation through Python scripts. Whether you need to add a chat interface to your website or build automated analysis pipelines, the repository provides battle-tested code patterns.

## Overview of Official Onyx Usage Examples

According to the source code, the repository contains two runnable reference implementations. The **widget example** provides a Lit-based web component located in [`widget/README.md`](https://github.com/onyx-dot-app/onyx/blob/main/widget/README.md) that communicates directly with Onyx chat endpoints. The **Assistants API example** offers a Python CLI in [`examples/assistants-api/topics_analyzer.py`](https://github.com/onyx-dot-app/onyx/blob/main/examples/assistants-api/topics_analyzer.py) that automates topic analysis using OpenAI-compatible endpoints.

Both implementations follow the same architectural flow: create a session or thread, send user input via HTTP POST, and consume Server-Sent Events (SSE) for streaming responses. This pattern applies universally across custom frontends (React, Vue, plain HTML) and backend clients (Python, Node.js, Go).

## Embedding the Onyx Chat Widget

### HTML Drop-in Integration

The simplest Onyx usage example involves adding a `<script>` tag and custom element to any HTML page. The widget automatically handles session management, API authentication, and real-time streaming via `POST /api/chat/create-chat-session` and `POST /api/chat/send-message`.

```html
<!-- Load the widget from the CDN -->
<script type="module"
        src="https://cdn.onyx.app/widget/1.0/dist/onyx-widget.js"></script>

<!-- Insert the widget -->
<onyx-chat-widget
  backend-url="https://cloud.onyx.app/api"
  api-key="YOUR_LIMITED_SCOPE_KEY"
  mode="launcher">
</onyx-chat-widget>

```

*Source:* [`widget/README.md`](https://github.com/onyx-dot-app/onyx/blob/main/widget/README.md) contains the complete quick-start instructions and architecture diagram showing how the component streams answers via SSE【/cache/repos/github.com/onyx-dot-app/onyx/main/widget/README.md†L21-L38】【L44-L66】.

### React and TypeScript Implementation

For modern web applications, the repository includes a complete React implementation in [`examples/widget/src/app/widget/Widget.tsx`](https://github.com/onyx-dot-app/onyx/blob/main/examples/widget/src/app/widget/Widget.tsx). This example demonstrates manual management of streaming responses using the `handleStream` generator and reassembles chunked SSE payloads via helper functions `processRawChunkString` and `processSingleChunk`.

```tsx
// examples/widget/src/app/widget/Widget.tsx
import React, { useState } from "react";

const API_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:8080";
const API_KEY = process.env.NEXT_PUBLIC_API_KEY || "";

export const ChatWidget = () => {
  const [messages, setMessages] = useState<
    { text: string; isUser: boolean }[]
  >([]);
  const [input, setInput] = useState("");
  const [loading, setLoading] = useState(false);

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!input.trim()) return;
    setMessages([...messages, { text: input, isUser: true }]);
    setLoading(true);
    try {
      const gen = sendMessage({ message: input });
      let full = "";
      for await (const chunks of gen) {
        for (const c of chunks) {
          if ("answer_piece" in c) {
            full += c.answer_piece;
            setMessages([
              ...messages,
              { text: input, isUser: true },
              { text: full, isUser: false },
            ]);
          }
        }
      }
    } finally {
      setLoading(false);
      setInput("");
    }
  };
  /* UI omitted for brevity */
};

```

*Source:* The complete streaming logic and session handling appear in [`examples/widget/src/app/widget/Widget.tsx`](https://github.com/onyx-dot-app/onyx/blob/main/examples/widget/src/app/widget/Widget.tsx)【/cache/repos/github.com/onyx-dot-app/onyx/main/examples/widget/src/app/widget/Widget.tsx†L1-L55】【L96-L124】.

## Automating Workflows with the Assistants API

### Python Client Configuration

The [`examples/assistants-api/topics_analyzer.py`](https://github.com/onyx-dot-app/onyx/blob/main/examples/assistants-api/topics_analyzer.py) script demonstrates backend automation. It configures an OpenAI-compatible client pointing at `http://localhost:8080/openai-assistants` using the `DANSWER_API_KEY` environment variable (legacy name) for authentication via the `Authorization` header.

```python

# examples/assistants-api/topics_analyzer.py

from openai import OpenAI

API_KEY = os.getenv("OPENAI_API_KEY")
ONYX_KEY = os.getenv("DANSWER_API_KEY")

client = OpenAI(
    api_key=API_KEY,
    base_url="http://localhost:8080/openai-assistants",
    default_headers={"Authorization": f"Bearer {ONYX_KEY}"},
)

```

*Source:* Client initialization appears in [`examples/assistants-api/topics_analyzer.py`](https://github.com/onyx-dot-app/onyx/blob/main/examples/assistants-api/topics_analyzer.py)【/cache/repos/github.com/onyx-dot-app/onyx/main/examples/assistants-api/topics_analyzer.py†L8-L16】.

### Creating Search-Enabled Assistants

The example creates an assistant with `tools=[{"type": "SearchTool"}]` to enable retrieval from all connected knowledge sources. It creates threads, adds messages, and polls run status using `wait_on_run` until completion.

```python

# examples/assistants-api/topics_analyzer.py

assistant = client.beta.assistants.create(
    name="Topic Analyzer",
    instructions=SYSTEM_PROMPT,
    tools=[{"type": "SearchTool"}],
    model="gpt-4o",
)

for topic in topics:
    thread = client.beta.threads.create()
    client.beta.threads.messages.create(
        thread_id=thread.id,
        role="user",
        content=USER_PROMPT.format(topic=topic),
    )
    run = client.beta.threads.runs.create(
        thread_id=thread.id,
        assistant_id=assistant.id,
        tools=[{
            "type": "SearchTool",
            "retrieval_details": {
                "run_search": "always",
                "filters": {"time_cutoff": "..."},
            },
        }],
    )
    run = wait_on_run(client, run, thread)   # polls until completed

    msgs = client.beta.threads.messages.list(
        thread_id=thread.id, order="asc", after=message.id
    )
    show_response(msgs)

```

*Source:* The complete assistant lifecycle and search configuration appear in [`examples/assistants-api/topics_analyzer.py`](https://github.com/onyx-dot-app/onyx/blob/main/examples/assistants-api/topics_analyzer.py)【/cache/repos/github.com/onyx-dot-app/onyx/main/examples/assistants-api/topics_analyzer.py†L31-L43】【L66-L78】.

## Common Integration Patterns

Both Onyx usage examples rely on identical backend API structures, differing only in language-specific client implementations.

**Session Initialization:**
- **Widget:** Sends `POST /api/chat/create-chat-session` to obtain a `chat_session_id`.
- **Assistants API:** Calls `client.beta.assistants.create()` followed by `client.beta.threads.create()`.

**Message Transmission:**
- **Widget:** Issues `POST /api/chat/send-message` with the session ID and message content.
- **Assistants API:** Uses `client.beta.threads.messages.create()` to add user messages to a thread.

**Retrieval Configuration:**
- Both support forcing document retrieval via `run_search: "always"`. The widget passes this in the request body, while the Python client includes it within the `SearchTool` definition.

**Streaming Consumption:**
- **Widget:** Consumes SSE through the `handleStream` generator and processes chunks via `processRawChunkString` and `processSingleChunk`.
- **Python:** Polls run status via `wait_on_run` until the assistant completes processing.

## Summary

- The **widget example** ([`widget/README.md`](https://github.com/onyx-dot-app/onyx/blob/main/widget/README.md)) provides a drop-in Lit component for websites that handles `POST /api/chat/create-chat-session` and SSE streaming automatically.
- The **Assistants API example** ([`examples/assistants-api/topics_analyzer.py`](https://github.com/onyx-dot-app/onyx/blob/main/examples/assistants-api/topics_analyzer.py)) offers a Python CLI for automated topic analysis using OpenAI-compatible endpoints at `http://localhost:8080/openai-assistants`.
- Both implementations use **Server-Sent Events (SSE)** for real-time response streaming and support **retrieval-augmented generation** via `SearchTool` or `run_search` parameters.
- Authentication requires limited-scope API keys (`NEXT_PUBLIC_API_KEY` for the widget, `DANSWER_API_KEY` for Python) passed via `Authorization` headers.
- The examples demonstrate patterns reusable across any HTTP-capable client, from React frontends to automated Python backends.

## Frequently Asked Questions

### What endpoints does the Onyx chat widget use?

The widget communicates with `POST /api/chat/create-chat-session` to initialize conversations and `POST /api/chat/send-message` to transmit user messages. Both endpoints return responses via Server-Sent Events (SSE), which the widget consumes through the `handleStream` generator function defined in [`examples/widget/src/app/widget/Widget.tsx`](https://github.com/onyx-dot-app/onyx/blob/main/examples/widget/src/app/widget/Widget.tsx).

### How do I enable document retrieval in Onyx API calls?

To enable retrieval, pass `run_search: "always"` in the request body (for direct API usage) or include `tools=[{"type": "SearchTool", "retrieval_details": {"run_search": "always"}}]` when creating a run via the Assistants API. This configuration forces the LLM to query connected knowledge sources before generating responses, as demonstrated in [`examples/assistants-api/topics_analyzer.py`](https://github.com/onyx-dot-app/onyx/blob/main/examples/assistants-api/topics_analyzer.py).

### Can I use the Onyx Assistants API with standard OpenAI client libraries?

Yes. The Onyx backend exposes an OpenAI-compatible endpoint at `http://localhost:8080/openai-assistants` (or your deployment URL). Configure your OpenAI client with this `base_url` and provide your Onyx API key via the `Authorization` header. The [`topics_analyzer.py`](https://github.com/onyx-dot-app/onyx/blob/main/topics_analyzer.py) example uses exactly this pattern with the official `openai` Python package.

### What is the difference between the widget and Assistants API examples?

The **widget example** provides a frontend-focused implementation for embedding chat UIs into websites using HTML or React components. The **Assistants API example** offers a backend Python script for programmatic automation, creating persistent assistants that can run scheduled analysis tasks. Both use the same underlying Onyx retrieval and streaming architecture but serve different integration scenarios.