# Code Execution Source: https://docs.onyx.app/admins/actions/code_interpreter Enable Python code execution for your AI Agents in Onyx The code execution action allows your Agents to write and run Python code to complete more complex tasks such as performing calculations, analyzing data, and generating visualizations. ## Capabilities * **Calculations**: Accurately perform large or complex mathematical operations * **Data Analysis**: Run analysis on files provided by the user (e.g., CSVs, spreadsheets) * **File Generation**: Create and return files such as reports, modified datasets, or exports * **Visualizations**: Generate graphs and charts that render directly in the [Chat UI](/overview/core_features/chat) ## Configuration No configuration is required. Code execution is a built-in action available to all Onyx deployments out of the box. To enable it for a specific Agent, make sure the **Code Execution** action is toggled on in the Agent's configuration. ## Connect / Disconnect Code Execution Server The code execution server is connected by default. You can disconnect or reconnect it at any time from the **Admin Panel**. This page also displays the server's health and connection status. Code Execution ## How It Works Code execution runs in a secure, sandboxed Python environment with: * **Pre-installed libraries** such as numpy, pandas, scipy, and matplotlib * **Network access disabled** and restricted filesystem access for security * **Resource limits and timeouts** to prevent runaway execution The LLM decides when to invoke code execution based on the user's query — no explicit invocation is needed. # Coding Agent Source: https://docs.onyx.app/admins/actions/coding_agent Enable your AI Agents to investigate and answer questions about a GitHub codebase The Coding Agent is a **beta** Action. It is disabled by default and currently supports **public** GitHub repositories only. The Coding Agent action lets your Agents investigate a GitHub repository and answer questions about its codebase. It clones the repository into an isolated sandbox, explores the code with shell commands, and returns a written answer. ## Capabilities * **Codebase Q\&A**: Answer questions about how a repository is implemented and where logic lives * **Code investigation**: Trace data flow and interactions between components * **Onboarding**: Summarize a project's structure and key modules ## How It Works When invoked, the Coding Agent: The target GitHub repository is cloned into an isolated sandbox. An iterative loop powered by an LLM executes shell commands to explore the codebase. A final answer is produced based on its findings. The Coding Agent runs in the same sandboxed environment as the [Code Interpreter](/admins/actions/code_interpreter), so it requires a connected code execution (bash) server. ## Configuration The Coding Agent is a built-in Action, but because it is in beta it is **disabled by default**. Go to the **Admin Panel** and open the **Actions** tab. Locate the **Coding Agent** action and enable it. The Coding Agent relies on the same sandboxed bash environment as the Code Interpreter. Make sure the code execution server is connected and healthy from the Admin Panel. Enable the **Coding Agent** action on the [Agents](/admins/agents/overview) that should be able to use it. Once enabled, the LLM automatically decides when to invoke it. ## Using the Coding Agent Once enabled and attached to an Agent, the LLM decides when to invoke the Coding Agent based on the user's query — no explicit invocation is needed. Be explicit about which repository you want analyzed. For example: *"Using the repository at [https://github.com/onyx-dot-app/onyx](https://github.com/onyx-dot-app/onyx), explain how the connector indexing pipeline works."* ## Limitations * **Public repositories only**: Private repositories are not yet supported and will currently fail to clone. Support for private repositories is planned. * **Beta**: Behavior and configuration may change as the feature matures. # Image Generation Source: https://docs.onyx.app/admins/actions/image_generation Enable image generation capabilities for your AI Agents in Onyx The image generation action allows your Agents to create images based on text prompts. Once configured, any AI model in Onyx can invoke this action to generate images using supported image generation models. ## Supported Models | Model | Provider | | --------------- | --------------------- | | GPT Image 1.5 | OpenAI / Azure OpenAI | | GPT Image 1 | OpenAI / Azure OpenAI | | DALL-E 3 | OpenAI / Azure OpenAI | | Nano Banana | Vertex (Google) | | Nano Banana Pro | Vertex (Google) | ## Configuration Go to the **Admin Panel** and select **Image Generation** under the **Configuration** section. Image Generation Configuration Page The page displays available models grouped by provider (OpenAI, Azure OpenAI and Vertex). Click **Connect** on any model to configure it. A modal will open where you can set up credentials: * **Use existing API key**: Select from previously configured OpenAI API keys * **Enter new API key**: Add a new OpenAI API key * **Use existing API key**: Select from previously configured Azure OpenAI API keys * **Enter new API key**: Add a new Azure OpenAI API key * **Service Account**: Create a Google Cloud service account, then generate and download a JSON key file * **Upload credentials**: Upload the service account JSON key file * **Region (Optional)**: Define the region you want requests sent to. Defaults to global The last configured model will automatically become the **Current Default**. The model marked as **Current Default** is used when users request image generation in chat. * To **remove** a model as default: Click the "Current Default" badge on that model * To **edit credentials**: Click the settings icon (gear) to open a modal where you can update the API key ## Using Image Generation Once image generation is configured with a default model, any AI model in Onyx can invoke the image generation action. When a user requests an image, the Agent will automatically use the configured default image generation model. # MCP Source: https://docs.onyx.app/admins/actions/mcp Configure Model Context Protocol (MCP) actions in Onyx Model Context Protocol (MCP) enables AI Agents to invoke tools and services in a controlled manner. You can configure Onyx to be an MCP client and allow your Agents to retrieve data or perform operations. Onyx can also act as an MCP server! See the [Onyx MCP Server](/overview/onyx_anywhere/mcp_server) guide to connect Claude, Cursor, and other AI tools to your Onyx knowledge base. ## MCP in Onyx Click your user profile icon and select **Admin Panel** and select the **MCP Actions** tab in the sidebar. MCP Actions dashboard in Onyx Admin Panel Click the **Add MCP Server** button and fill out the following fields: Add MCP Server dialog in Onyx Admin Panel * **Server Name** — A human-readable name for this MCP server. Typically the name of the service you're connecting to (e.g. "Slack", "Jira"). * **Description** — Any additional information that helps identify the server. Useful for distinguishing multiple configured MCP server connections that talk to the same service. * **MCP Server URL** — The URL of the MCP server, which must be reachable from your Onyx instance. Most URLs end in `/mcp`, or `/sse` for older servers. * **Managed MCP server:** The URL is typically found in the provider's documentation describing how to connect. * **Self-hosted MCP server:** You'll need to run your server in HTTP transport mode — Onyx doesn't currently support connecting via stdio. If the server is running on the same machine as Onyx, use `http://127.0.0.1:`. Otherwise, use the URL and port the server is exposed at. When you click **Add Server**, Onyx will create the server in a **disconnected** state. The next steps will set up authentication (if any) and validate that Onyx can connect to it. MCP server authentication configuration in Onyx Onyx supports four authentication types when connecting to an MCP server: ### No Auth Use this when your MCP server is unprotected. Typically only used for testing when connecting to a local MCP server on a local Onyx instance, but may be useful if the server is deployed inside a VPC and you want all users to have the same unrestricted access to it. ### API Key The server is protected by API key authentication, typically using the `Authorization: Bearer ` format. There are two sub-modes: * **Shared Key** — The admin configures a single API key used for all user requests. Similar to No Auth in that users won't need any additional configuration and will all get the same level of access (whatever is provided by the API key you choose). * **Individual Key** — Users authenticate in the chat flow by providing their own API key(s) to connect to the server. Useful when you want users to have differing access to an external service by identity. This mode is also the most configurable — Onyx allows the admin to specify arbitrary header patterns to send to the MCP server. ### OAuth Many modern MCP servers support OAuth authentication to give users access to tools and data using the same login flow they use when manually accessing the service. Many OAuth-enabled MCP servers support [Client ID Metadata Documents (CIMD)](https://datatracker.ietf.org/doc/draft-ietf-oauth-client-id-metadata-document/) or [Dynamic Client Registration (DCR)](https://datatracker.ietf.org/doc/html/rfc7591). These standards let Onyx connect without a manually configured **Client ID** or **Client Secret**. In most cases, you can simply click **Connect** and complete the OAuth flow. If the MCP server's documentation requires you to register an OAuth app: 1. Create an OAuth app in the IdP (Identity Provider) used by the MCP server. 2. Add the following Onyx callback URL to the app: `https:///mcp/oauth/callback` 3. Enter the generated **Client ID** and **Client Secret** in Onyx, then click **Connect**. On HTTPS deployments, Onyx automatically publishes and uses a deployment-level, Onyx-branded CIMD at `https:///api/mcp/oauth/client-metadata` when the authorization server supports it. HTTP local development uses DCR instead. ### Pass-Through OAuth Only available when your Onyx instance is configured to authenticate via OAuth. In this mode, Onyx passes the user's OAuth access token through as an `Authorization: Bearer` header to the MCP server. This is most often useful if your organization hosts its own MCP servers and would rather not require users to authenticate again after already going through the OAuth flow to log in to Onyx. Many MCP servers require scopes that Onyx does not request by default during login. Check the MCP server's documentation for the exact scopes it requires, then add them to the comma-separated scope override for your authentication type: * **Google OAuth:** `GOOGLE_OAUTH_SCOPE_OVERRIDE` * **OIDC:** `OIDC_SCOPE_OVERRIDE` These settings replace the default scopes, so retain `openid`, `email`, and `profile` alongside the additional scopes. See [Google OAuth scope configuration](/deployment/authentication/oauth#customizing-requested-scopes) or [OIDC scope configuration](/deployment/authentication/oidc#customizing-requested-scopes) for examples. Requesting a scope in Onyx does not guarantee that the identity provider will grant it. The scope must also be exposed and permitted for the Onyx OAuth/OIDC client in the identity provider, and some providers require an administrator to grant consent. The exact configuration varies by provider. The issued access token must include both the required scopes and an audience accepted by the MCP server. *** Clicking **Connect** will validate that Onyx can reach the MCP server using the provided authentication method. The MCP Actions dashboard then lets the admin list the tools available from the MCP server and select which subset of tools should be made available for use in Agents across the organization. # OpenAPI Source: https://docs.onyx.app/admins/actions/openapi Configure custom actions in Onyx with OpenAPI You can create custom actions in Onyx using an OpenAPI 3.0 or 3.1 specification of an API. This enables your AI agents to interact with REST APIs and trigger workflows in external systems. Include only the endpoints you want your agent to call in the OpenAPI spec. Remove any endpoints you don't want the agent to access. ## Setting Up Custom Actions Click your user profile icon and select **Admin Panel**, then click the **OpenAPI Actions** tab in the sidebar.
OpenAPI Actions tab in Onyx Admin Panel sidebar OpenAPI Actions dashboard in Onyx Admin Panel
Click the **Add OpenAPI Action** button. Paste your OpenAPI spec and configure any required authentication or headers. Add OpenAPI Action modal in Onyx Admin Panel
## Example The below OpenAPI spec can be used to create a Custom Action for fetching and creating Agents in Onyx. ```json OpenAPI expandable theme={null} { "openapi": "3.1.0", "info": { "title": "Agents API", "version": "1.0.0", "description": "Minimal OpenAPI schema for creating and fetching agents in Onyx" }, "servers": [ { "url": "https://cloud.onyx.app/api" } ], "paths": { "/persona": { "post": { "summary": "Create Agent (Persona)", "operationId": "create_persona", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "properties": { "name": { "type": "string" }, "description": { "type": "string" }, "document_set_ids": { "type": "array", "items": { "type": "integer" } }, "num_chunks": { "type": "number" }, "is_public": { "type": "boolean" }, "recency_bias": { "type": "string", "enum": ["favor_recent", "base_decay", "no_decay", "auto"] }, "llm_filter_extraction": { "type": "boolean" }, "llm_relevance_filter": { "type": "boolean" }, "tool_ids": { "type": "array", "items": { "type": "integer" } }, "system_prompt": { "type": "string" }, "task_prompt": { "type": "string" }, "datetime_aware": { "type": "boolean" } }, "required": [ "name", "description", "document_set_ids", "num_chunks", "is_public", "recency_bias", "llm_filter_extraction", "llm_relevance_filter", "tool_ids", "system_prompt", "task_prompt", "datetime_aware" ] } } } }, "responses": { "200": { "description": "Created" } } } }, "/persona/{persona_id}": { "get": { "summary": "Get Agent (Persona) By ID", "operationId": "get_persona", "parameters": [ { "name": "persona_id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "OK" } } } } } } ``` # Voice Mode Source: https://docs.onyx.app/admins/actions/voice_mode Set up voice providers to enable Voice Mode for your Onyx instance The Voice Mode action allows your users to have spoken conversations with Onyx using speech-to-text and text-to-speech providers. ## Setting up Voice Mode Click your user profile icon and select Admin Panel, then select the Voice Mode tab in the sidebar. Voice Mode dashboard in Onyx Admin Panel Configure a provider to transcribe user speech into text. Speech-to-Text Providers
Navigate to the [OpenAI dashboard](https://platform.openai.com/api-keys) and create a new API key, or reuse an existing OpenAI API key already configured for your LLM provider. Click **Connect** and enter the API key.
Navigate to the [Azure Portal](https://portal.azure.com) and create a Speech resource. Copy the API key and region. Click **Connect** and enter the API key, region, and target URI.
Navigate to the [ElevenLabs dashboard](https://elevenlabs.io/app/settings/api-keys) and create a new API key. Click **Connect** and enter the API key.
Configure a provider to convert AI responses into spoken audio. Text-to-Speech Providers
Navigate to the [OpenAI dashboard](https://platform.openai.com/api-keys) and create a new API key (or reuse the one from Whisper). Click **Connect** and enter the API key.
Navigate to the [OpenAI dashboard](https://platform.openai.com/api-keys) and create a new API key (or reuse the one from Whisper). Click **Connect** and enter the API key. TTS-1 HD provides higher quality audio than TTS-1 but may have slightly higher latency and cost.
Navigate to the [Azure Portal](https://portal.azure.com) and create a Speech resource. Copy the API key and region. Click **Connect** and enter the API key, region, and target URI.
Navigate to the [ElevenLabs dashboard](https://elevenlabs.io/app/settings/api-keys) and create a new API key. Click **Connect** and enter the API key.
Once your TTS provider is configured, select a voice from the dropdown or input a voice ID directly. Voice Selection
If you have multiple providers configured, make sure to **Set as Default** for both your preferred STT and TTS provider. Set Default Provider
Make sure your users have microphone access enabled in their browser to use Voice Mode. # Web Search Source: https://docs.onyx.app/admins/actions/web_search Enable web search capabilities for your AI Agents in Onyx The web search action allows your Agents to query the internet and retrieve real-time information from web sources. ## Web Search in Onyx ### On Onyx Cloud Web search is already active and ready to use on Onyx Cloud - no additional configuration required! ### Self-Hosted Click your user profile icon and select Admin Panel and select the Web Search tab in the sidebar. Web Search dashboard in Onyx Admin Panel We currently support the following web search providers: Exa AI, Serper, and Google PSE. To set any ofthem up, follow the steps below. Search Engine Providers Create an Exa API key in the [Exa AI dashboard](https://exa.ai/dashboard). In Onyx, click **Connect** and paste the API key in the **API Key** field. Create a Serper API key in the [Serper dashboard](https://serper.dev/dashboard). In Onyx, click **Connect** and paste the API key in the **API Key** field. Create a Google PSE API key in the [Google PSE dashboard](https://programmablesearchengine.google.com/controlpanel/all). In Onyx, click **Connect** and paste the API key in the **API Key** field and the Search Engine ID in the **Search Engine ID** field. We currently support the following web crawlers: Onyx web crawler and Firecrawl. To set them up, follow the steps below. Crawler Providers **(Recommended)** It is already set up and ready to use, no additional setup required. Create a Firecrawl API key in the [Firecrawl dashboard](https://firecrawl.com/dashboard). In Onyx, click **Connect** and paste the API key in the **API Key** field. Make sure to **Set as Default** the provider if you have multiple providers set up for the search engine and web crawler. You can change it at any time. Set Default Provider Make sure your Agent has the Web Search Action enabled! # Hook Extensions Source: https://docs.onyx.app/admins/advanced_configs/hook_extensions Inject custom logic into Onyx's pipeline at defined stages without modifying source code Hook Extensions are an [Enterprise Edition](/deployment/miscellaneous/enterprise_edition) feature and are only available on **single-tenant** deployments. ## Overview Hook Extensions let you inject custom logic into Onyx's pipeline at defined stages — without modifying Onyx source code. You provide an HTTP endpoint; Onyx calls it at the right moment, sends a JSON payload, and uses your response to influence what happens next. ## Concepts ### Hook Points A hook point is a defined stage in Onyx's pipeline where custom logic can be injected. Each hook point specifies: * **When** it fires in the pipeline * **What** payload it sends to your endpoint * **What** response it expects back * A default timeout and fail strategy Hook points are intentional — once a hook point is added, Onyx commits to maintaining its payload structure, response format, and behavior — meaning it won't change in a breaking way without a proper deprecation process. Because of this long-term commitment, each proposal is evaluated carefully before being added. ### Hooks A hook connects a hook point to your HTTPS endpoint. When the hook point is triggered, Onyx POSTs a request to your endpoint and uses your response to continue, modify, or abort the pipeline. Only one hook per hook point is allowed at a time. ## How It Works The pipeline triggers at a defined stage. If an active hook is configured for that point, Onyx sends a JSON payload to your endpoint URL. Your endpoint processes the payload and returns a JSON response. Onyx uses your response to continue, modify, or abort the pipeline. If your endpoint is unreachable, times out, or returns an invalid response, Onyx follows the **fail strategy** you configured. ## Adding a Hook Go to the **Admin Panel** and select **Hook Extensions**. Find the hook point you want to use and click **Connect**. Complete the form: Add Hook Form | Field | Required | Description | | ------------- | -------- | ------------------------------------------------------------------------------------------------------------- | | Display Name | Yes | A human-readable label for this hook | | Fail Strategy | No | **Hard** — abort the pipeline. **Soft** — log and continue. Defaults to the hook point's recommended strategy | | Timeout | No | Seconds to wait for your endpoint to respond (1–600). Defaults to the hook point's recommended timeout | | Endpoint URL | Yes | The HTTPS URL Onyx will POST to when the hook point is triggered. Must use HTTPS. | | API Key | No | If provided, Onyx sends this as `Authorization: Bearer ` on every request | Click **Connect**. Onyx validates your endpoint with a test request before saving. On success, the hook appears in the connected list. ## Managing a Hook Once connected, you can: * **Activate / Deactivate** — toggle whether the hook runs * **Edit** — update the name, endpoint URL, API key, timeout, or fail strategy * **Delete** — remove the hook entirely * **View Logs** — inspect recent execution failures for debugging ## Hook Health Onyx monitors your endpoint after the hook is registered and connected, displays its current health status. | Status | Meaning | | ---------------------- | ------------------------------------------------- | | Connected | Reachable, no failures in the last hour | | Degraded | Reachable, but failures occurred in the last hour | | Connection Lost | Onyx cannot reach your endpoint | Connected Hook Card Hook Errors in the Last Hour Hook Connection Lost The 10 most recent failures from the past 30 days are also shown to help with debugging. Hook Errors in the Last 30 Days *** ## Document Ingestion The Document Ingestion hook point lets you intercept every document before it enters the Onyx indexing pipeline. Your endpoint receives the fully-formed document and can filter it out, rewrite its content, or pass it through unchanged. It runs immediately after Onyx's internal validation and before the indexing pipeline begins — no partial writes have occurred yet. | Setting | Value | | --------------------- | -------------------------------- | | Default Timeout | 30 seconds (configurable) | | Default Fail Strategy | Hard (configurable) | | On Hard Fail | The document will not be indexed | ### Input Schema Onyx sends a `POST` request to your endpoint once per document with the following JSON body: ```json theme={null} { "document_id": "string", "title": "string | null", "semantic_identifier": "string", "source": "string", "sections": [ { "text": "string | null", "link": "string | null", "image_file_id": "string | null" } ], "metadata": { "key": ["string"] }, "doc_updated_at": "string | null", "primary_owners": [ { "display_name": "string | null", "email": "string | null" } ], "secondary_owners": [ { "display_name": "string | null", "email": "string | null" } ] } ``` All input fields are provided for context only. Your endpoint can only influence the pipeline through the output schema — specifically the `sections` field. | Field | Type | Required | Description | | --------------------------------- | ----------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `document_id` | string | Yes | Unique identifier for the document. | | `title` | string \| null | Yes | Title of the document. | | `semantic_identifier` | string | Yes | Human-readable identifier used for display (e.g. file name, page title). | | `source` | string | Yes | Connector source type. For the full list of possible values, see [`DocumentSource`](https://github.com/onyx-dot-app/onyx/blob/main/backend/onyx/configs/constants.py) in the Onyx source code. | | `sections` | object\[] | Yes | All sections of the document — both text sections and image sections. | | `sections[].text` | string \| null | Yes | Text content. Set for text sections, `null` for image sections. | | `sections[].link` | string \| null | No | Optional URL associated with this section. | | `sections[].image_file_id` | string \| null | No | Opaque image identifier. Set for image sections, `null` for text sections. Image content is not included — hooks can reorder or drop image sections but cannot read or modify the image. | | `metadata` | object | Yes | Key-value metadata. Values are always `string[]`. Connector-specific — see below. | | `doc_updated_at` | string \| null | Yes | Timestamp of the last update at the source in the format `YYYY-MM-DDTHH:MM:SS.ffffff+00:00`, or `null` if unknown. | | `primary_owners` | object\[] \| null | Yes | Primary owners of the document, or `null` if not available. | | `primary_owners[].display_name` | string \| null | No | Human-readable name of the owner. | | `primary_owners[].email` | string \| null | No | Email address of the owner. | | `secondary_owners` | object\[] \| null | Yes | Secondary owners of the document, or `null` if not available. | | `secondary_owners[].display_name` | string \| null | No | Human-readable name of the owner. | | `secondary_owners[].email` | string \| null | No | Email address of the owner. | #### Metadata Keys by Connector The keys present in `metadata` depend on the connector source. Below are a few examples: | Connector | Keys | | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Confluence | `space`, `labels` | | Jira | `key`, `project`, `project_name`, `issuetype`, `status`, `priority`, `assignee`, `assignee_email`, `reporter`, `reporter_email`, `labels`, `created`, `updated`, `duedate`, `resolution`, `resolution_date`, `parent` | | File | Arbitrary user-defined tags. You can embed custom key-value pairs directly in the file using an `ONYX_METADATA` block — see the [File connector docs](/admins/connectors/official/file) for details. | **Example** ```json theme={null} { "document_id": "FILE_CONNECTOR__0376357d-6431-4082-b71a-9f83688f1f16", "title": "Q4 2024 Refund Policy", "semantic_identifier": "Q4 2024 Refund Policy", "source": "confluence", "sections": [ { "text": "Our refund policy allows returns within 30 days...", "link": "https://wiki.example.com/pages/123456", "image_file_id": null }, { "text": null, "link": null, "image_file_id": "846d6333-1a2b-4c5d-8e9f-0a1b2c3d4e5f" } ], "metadata": { "space": ["HR"], "labels": ["policy", "finance"] }, "doc_updated_at": "2024-10-01T12:00:00.000000+00:00", "primary_owners": [ { "display_name": "Alice Smith", "email": "alice@example.com" } ], "secondary_owners": null } ``` ### Output Schema A successful response from your endpoint must return HTTP `200` and a JSON body: | Field | Type | Required | Description | | ------------------ | ----------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | | `sections` | object\[] \| null | Yes | The sections to index, using the same schema as the input `sections`. The hook controls final ordering. `null` or empty list drops the document. | | `rejection_reason` | string \| null | No | Logged when `sections` is `null` or empty. Falls back to a generic message if omitted. | ```json theme={null} { "sections": [ { "text": "Our refund policy allows returns within 30 days...", "link": "https://wiki.example.com/pages/123456", "image_file_id": null }, { "text": null, "link": null, "image_file_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" } ], "rejection_reason": null } ``` ```json theme={null} { "sections": [ { "text": "Our refund policy allows returns within 30 days. Contact [REDACTED] for details." } ], "rejection_reason": null } ``` ```json theme={null} { "sections": null, "rejection_reason": "Document contains restricted classification label." } ``` ### Authentication If you configured an API key when registering the hook, Onyx includes it in every request: ``` Authorization: Bearer ``` ### Lambda Example You can use an [AWS Lambda function](https://docs.aws.amazon.com/lambda/latest/dg/getting-started.html) as your hook endpoint by exposing it over HTTPS via a [Lambda Function URL](https://docs.aws.amazon.com/lambda/latest/dg/lambda-urls.html). This is the simplest way to deploy a hook without managing a server. When Onyx calls your endpoint, the request arrives as an API Gateway-style event. Your handler reads the JSON body from `event["body"]`, processes the document, and returns a response with a `statusCode` and a JSON-encoded `body`. If you configured an API key on the hook, validate it against the `Authorization` header in the event before processing. ```python theme={null} import json import logging import os logger = logging.getLogger() logger.setLevel(logging.INFO) # Set the HOOK_API_KEY environment variable in your Lambda configuration. # If not set, API key validation is skipped. API_KEY = os.environ.get("HOOK_API_KEY") def lambda_handler(event, context): # Validate API key if configured if API_KEY: auth = (event.get("headers") or {}).get("authorization", "") if auth != f"Bearer {API_KEY}": logger.warning("Unauthorized request — invalid or missing API key") return {"statusCode": 401, "body": json.dumps({"error": "Unauthorized"})} body = json.loads(event.get("body", "{}")) source = body.get("source", "") document_id = body.get("document_id", "") sections = body.get("sections", []) logger.info("Received document: id=%s source=%s sections=%d", document_id, source, len(sections)) # Reject documents from the file connector if source == "file": logger.info("Rejecting document %s — file connector documents are not allowed", document_id) return { "statusCode": 200, "body": json.dumps({ "sections": None, "rejection_reason": "File connector documents are not allowed.", }), } logger.info("Passing through document %s", document_id) return { "statusCode": 200, "body": json.dumps({"sections": sections}), } ``` ### Testing Use `curl` to test your Lambda Function URL before connecting it to Onyx. **Pass-through (non-file source):** ```bash theme={null} curl -X POST https:// \ -H "Content-Type: application/json" \ -H "Authorization: Bearer " \ -d '{ "document_id": "confluence::page::123456", "title": "Q4 Refund Policy", "semantic_identifier": "Q4 Refund Policy", "source": "confluence", "sections": [{"text": "Our refund policy allows returns within 30 days.", "link": null, "image_file_id": null}], "metadata": {}, "doc_updated_at": null, "primary_owners": null, "secondary_owners": null }' ``` **Rejected (file source):** ```bash theme={null} curl -X POST https:// \ -H "Content-Type: application/json" \ -H "Authorization: Bearer " \ -d '{ "document_id": "FILE_CONNECTOR__abc123", "title": "Internal Doc", "semantic_identifier": "Internal Doc", "source": "file", "sections": [{"text": "Some content.", "link": null, "image_file_id": null}], "metadata": {}, "doc_updated_at": null, "primary_owners": null, "secondary_owners": null }' ``` Once the hook is connected, you can validate end-to-end by adding a File connector and uploading a document. After the connector syncs, search for content from that document in the chat window — if the hook is working correctly, the material should not appear in results since file connector documents are being rejected. File Connector Add File Document Ingestion Test — File Content Not Found *** ## Document Push The Document Push hook point fires after each document is successfully indexed. Use it to push indexed content to an external destination such as a wiki, data warehouse, or audit log. Unlike Document Ingestion (which runs before indexing and can modify or drop documents), this hook fires **after** the document has been written to the index. The response body is not used — any `2xx` response is treated as success. Document Push only fires for **public connectors** in **single-tenant** deployments, and only during **incremental syncs** — it does not fire during an initial index or a full re-index from the beginning. | Setting | Value | | --------------------- | --------------------------------------- | | Default Timeout | 30 seconds (configurable) | | Default Fail Strategy | Soft (configurable) | | On Soft Fail | The push is skipped; indexing continues | | On Hard Fail | The indexing batch will fail | ### Input Schema Onyx sends a `POST` request to your endpoint once per successfully indexed document with the following JSON body: ```json theme={null} { "document_id": "string", "title": "string | null", "content": "string", "source": "string", "url": "string | null", "doc_updated_at": "string | null", "metadata": { "key": ["string"] } } ``` | Field | Type | Description | | ---------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `document_id` | string | Unique identifier for the document. | | `title` | string \| null | Title of the document. | | `content` | string | Full text content (all text sections joined with a space). | | `source` | string | Connector source type (e.g. `confluence`, `slack`, `google_drive`). For the full list see [`DocumentSource`](https://github.com/onyx-dot-app/onyx/blob/main/backend/onyx/configs/constants.py) in the Onyx source code. | | `url` | string \| null | Canonical URL of the document at its source, if available. | | `doc_updated_at` | string \| null | ISO 8601 UTC timestamp of the last update at the source, or `null` if unknown. | | `metadata` | object | Key-value metadata. Values are always `string[]`. | **Example** ```json theme={null} { "document_id": "confluence::page::789012", "title": "Engineering Onboarding Guide", "content": "Welcome to the engineering team. This guide covers...", "source": "confluence", "url": "https://wiki.example.com/pages/789012", "doc_updated_at": "2025-03-15T09:30:00.000000+00:00", "metadata": { "space": ["Engineering"], "labels": ["onboarding", "guide"] } } ``` ### Output Schema The response body is **not used** — any `2xx` status code is treated as success. Your endpoint can return an empty body or any JSON object. ### Authentication If you configured an API key when registering the hook, Onyx includes it in every request: ``` Authorization: Bearer ``` ### Lambda Example You can use an [AWS Lambda function](https://docs.aws.amazon.com/lambda/latest/dg/getting-started.html) as your hook endpoint by exposing it over HTTPS via a [Lambda Function URL](https://docs.aws.amazon.com/lambda/latest/dg/lambda-urls.html). ```python theme={null} import json import logging import os logger = logging.getLogger() logger.setLevel(logging.INFO) API_KEY = os.environ.get("HOOK_API_KEY") def lambda_handler(event, context): if API_KEY: auth = (event.get("headers") or {}).get("authorization", "") if auth != f"Bearer {API_KEY}": return {"statusCode": 401, "body": json.dumps({"error": "Unauthorized"})} body = json.loads(event.get("body", "{}")) logger.info("Received document: id=%s title=%s", body.get("document_id"), body.get("title")) return {"statusCode": 200, "body": "{}"} ``` ### Testing Use `curl` to test your endpoint before connecting it to Onyx: ```bash theme={null} curl -X POST https:// \ -H "Content-Type: application/json" \ -H "Authorization: Bearer " \ -d '{ "document_id": "confluence::page::789012", "title": "Engineering Onboarding Guide", "content": "Welcome to the engineering team. This guide covers...", "source": "confluence", "url": "https://wiki.example.com/pages/789012", "doc_updated_at": "2025-03-15T09:30:00.000000+00:00", "metadata": { "space": ["Engineering"], "labels": ["onboarding"] } }' ``` *** ## Query Processing The Query Processing hook point lets you intercept every user query before it enters the Onyx pipeline. Your endpoint receives the raw query and the user's identity, and can rewrite the query, reject it entirely, or pass it through unchanged. It runs immediately after the user submits a message, before anything is saved to the database or sent to the LLM. This is the earliest possible point in the pipeline — no side effects have occurred yet. | Setting | Value | | --------------------- | ---------------------------------------------------------------- | | Default Timeout | 5 seconds (configurable) | | Default Fail Strategy | Hard (configurable) | | On Hard Fail | The query will be blocked and the user will see an error message | ### Input Schema Onyx sends a `POST` request to your endpoint with the following JSON body: ```json theme={null} { "query": "What is our refund policy?", "user_email": "alice@example.com", "chat_session_id": "550e8400-e29b-41d4-a716-446655440000" } ``` | Field | Type | Required | Description | | ----------------- | -------------- | -------- | --------------------------------------------------------------------- | | `query` | string | Yes | The raw query exactly as the user typed it. | | `user_email` | string \| null | Yes | Email of the user submitting the query, or `null` if unauthenticated. | | `chat_session_id` | string | Yes | UUID of the chat session. | ### Output Schema A successful response from your endpoint must return HTTP `200` and a JSON body: | Field | Type | Required | Description | | ------------------- | -------------- | -------- | --------------------------------------------------------------------------------------------- | | `query` | string \| null | Yes | The query to use downstream. Set to `null` or empty string to reject the query. | | `rejection_message` | string \| null | No | Message shown to the user when `query` is `null`. Falls back to a generic message if omitted. | ```json theme={null} { "query": "What is our refund policy?", "rejection_message": null } ``` ```json theme={null} { "query": "What is the refund policy for enterprise customers?", "rejection_message": null } ``` ```json theme={null} { "query": null, "rejection_message": "This topic is restricted. Please contact your administrator." } ``` ### Authentication If you configured an API key when registering the hook, Onyx includes it in every request: ``` Authorization: Bearer ``` ### Lambda Example You can use an [AWS Lambda function](https://docs.aws.amazon.com/lambda/latest/dg/getting-started.html) as your hook endpoint by exposing it over HTTPS via a [Lambda Function URL](https://docs.aws.amazon.com/lambda/latest/dg/lambda-urls.html). This is the simplest way to deploy a hook without managing a server. When Onyx calls your endpoint, the request arrives as an API Gateway-style event. Your handler reads the JSON body from `event["body"]`, processes the query, and returns a response with a `statusCode` and a JSON-encoded `body`. If you configured an API key on the hook, validate it against the `Authorization` header in the event before processing. ```python theme={null} import json import os BLOCKED_KEYWORDS = ["ssn", "phone number"] # Set the HOOK_API_KEY environment variable in your Lambda configuration. # If not set, API key validation is skipped. API_KEY = os.environ.get("HOOK_API_KEY") def lambda_handler(event, context): # Validate API key if configured if API_KEY: auth = (event.get("headers") or {}).get("authorization", "") if auth != f"Bearer {API_KEY}": return {"statusCode": 401, "body": json.dumps({"error": "Unauthorized"})} body = json.loads(event.get("body", "{}")) query = body.get("query", "") # Reject queries containing blocked keywords for keyword in BLOCKED_KEYWORDS: if keyword.lower() in query.lower(): return { "statusCode": 200, "body": json.dumps({ "query": None, "rejection_message": "Your query contains restricted terms. Please contact your administrator.", }), } return { "statusCode": 200, "body": json.dumps({"query": query}), } ``` ### Testing Use `curl` to test your Lambda Function URL before connecting it to Onyx. **Pass-through (no blocked keywords):** ```bash theme={null} curl -X POST https:// \ -H "Content-Type: application/json" \ -H "Authorization: Bearer " \ -d '{ "query": "What is our refund policy?", "user_email": "alice@example.com", "chat_session_id": "550e8400-e29b-41d4-a716-446655440000" }' ``` **Rejected (contains blocked keyword):** ```bash theme={null} curl -X POST https:// \ -H "Content-Type: application/json" \ -H "Authorization: Bearer " \ -d '{ "query": "What is the SSN format?", "user_email": "alice@example.com", "chat_session_id": "550e8400-e29b-41d4-a716-446655440000" }' ``` Once the hook is connected, you can also validate the logic directly in the Onyx chat window. Try sending a query that contains a blocked keyword (e.g. "ssn" or "phone number") — you should see the rejection message instead of a response. Queries without blocked keywords should pass through normally. Query Processing Hook Test *** ## Suggesting a New Hook Point If your use case requires a pipeline injection point that doesn't exist yet, open a GitHub issue describing: * **Where** in the pipeline you need to inject logic (e.g. after retrieval, before document indexing) * **What your endpoint would receive** — what context does it need to do its job? * **What your endpoint would return** — how should Onyx change its behavior based on your response? * **Use cases** — what problem does this solve? Are other customers likely to need the same point? The Onyx team reviews proposals and implements hook points that have broad applicability. Once a hook point is added, Onyx commits to maintaining its payload structure, response format, and behavior — meaning it won't change in a breaking way without a proper deprecation process. Because of this long-term commitment, each proposal is evaluated carefully before being added. # Language Model Access Controls Source: https://docs.onyx.app/admins/advanced_configs/llm_access_controls Configure access controls for language model providers ## Overview Onyx provides fine-grained access control for language model providers, allowing administrators to control **who** can use specific models and **which agents** can use them. This enables better cost control, governance, and enforcement of model usage policies. Language model access controls ### Access Control Types **Public Providers** * Accessible to all users and agents * No restrictions applied * Useful for default, unrestricted models **Private Providers** * Subject to user group and/or agent restrictions * Enables fine-grained access control * Recommended for expensive or specialized models Control **who** can use specific language model providers by restricting access to specific user groups. **How it works:** * Assign one or more user groups to a provider * Only users in those groups can use the provider * Admins bypass group restrictions (but not agent restrictions) * Leave empty for no group restrictions **Use cases:** * Restrict expensive models to specific teams * Provide specialized models to certain departments * Implement cost controls by team Control **which agents** can use specific language model providers. **How it works:** * Assign one or more agents to a provider via the "Agent Whitelist" * The provider will only appear as an option when using those agents * Applies to **all users**, including admins * Leave empty for no agent restrictions **Use cases:** * Reserve GPT-4 for "Code Review Agent" only * Use Claude Opus exclusively with "Legal Document Analyzer" * Prevent users from selecting inappropriate models for specific use cases * Enforce model policies per agent type You can combine both user group and agent restrictions for maximum control. **Access Rules (AND logic):** * User must be in an allowed group **AND** using an allowed agent * Both conditions must be satisfied for access * Admins bypass group restrictions but still require allowed agents **Example:** * Provider: GPT-4 * User Groups: "Engineering Team" * Agent Whitelist: "Code Review Agent", "Architecture Advisor" * **Result:** Only Engineering Team members can use GPT-4, and only with those two agents ### Configuring Access Controls To configure access controls for a language model provider: Navigate to **Admin Panel → Configuration → Language Models** Click on an existing provider or create a new one In the **Access Controls** section nested under Advanced options: * Toggle **Make Public** off to enable restrictions * Select user groups in **User Group Access** (optional) * Select agents in **Agent Whitelist** (optional) Save your changes When a provider is set to public, the access control selectors are automatically disabled. ### Access Decision Logic The system determines access based on the following logic: | is\_public | Groups Set | Agents Set | Access Rule | | ---------- | ---------- | ---------- | -------------------------------------------- | | `true` | Any | Any | Everyone has access | | `false` | Yes | Yes | Must be in group **AND** using allowed agent | | `false` | Yes | No | Must be in group (admins bypass) | | `false` | No | Yes | Must use allowed agent (applies to admins) | | `false` | No | No | Admin-only access | ### Provider Visibility Users will only see the language model providers they have access to: * In the agent creation/editing interface * In the chat UI model selector * When using the API to list available providers Restricted providers are completely hidden from users who don't have access, preventing confusion and unauthorized usage attempts. # OpenSearch Document Index Migration Source: https://docs.onyx.app/admins/advanced_configs/opensearch_document_index_migration Migrating indexed documents from Vespa to OpenSearch ## Overview Onyx has gradually been working towards switching our backing document index database from Vespa to OpenSearch. The motivating factors behind this decision are to reduce the baseline resources required to run Onyx, and to switch to a widely used and supported documented index provider. This is a living page and more details will be added over the coming weeks. ## Migration As of `v3`, Onyx uses both Vespa and OpenSearch. Any documents which Onyx indexes while using this version are indexed into both Vespa and OpenSearch, and there is no migration required. Also as of `v3`, Onyx automatically runs a task to migrate your existing documents from Vespa to OpenSearch. This task makes checkpointed progress so Onyx does not necessarily need to be running continuously until the migration completes in order for it to complete successfully. No explicit input is needed from admins other than upgrading to `v3` in order for this task to run. The migration's progress can be monitored in the Admin Panel, in the Document Index Migration sidebar tab. The migration is best-effort. Although the vast majority of documents are not expected to have migration issues, some documents (in particular documents which were indexed a long time ago in versions of Onyx which enforced weaker/different contracts for indexed content) may have irreconcilable migration issues. In this event the only solution is a re-index of connectors for those documents, where they will be processed in such a way that they can then be indexed into OpenSearch. ## Deprecation of Vespa `v4` of Onyx will represent the first major version to use OpenSearch entirely without Vespa. In order to preserve existing indexed content in Vespa without requiring re-indexing, it will be necessary to upgrade to `v3` of Onyx to allow migrations to run before upgrading to `v4`, when released. Although it may be technically feasible without breaking the product for a determined admin to upgrade Onyx directly from some version \< `v3` directly to some version > `v3` skipping `v3` entirely, this will result in complete loss of indexed data and will require re-indexing all connectors in order to be able to search over documents. ## Retrieval During `v3`, document retrieval can be done via either Vespa (the default) or OpenSearch, and which one is used can be toggled in the Document Index Migration sidebar tab on the Admin Panel. Naturally, if the migration is not yet complete, retrieval via OpenSearch may not yield every expected document. ## cloud.onyx.app The migration for cloud users began in March 2026, and by April 2026 virtually all tenants' migrations indicated completion. As of `v3.2.0-cloud.7` in April, all tenants in the cloud have been swapped over to OpenSearch for retrieval, and Vespa is no longer in the loop with Onyx, so all new documents indexed are indexed only using OpenSearch. Due to a unique failure mode involving automatic updates in Vespa Cloud, there may be some migrations which report successful completion despite there being some existing documents which did not exist from the perspective of Vespa at the time of migration for that particular document, and which therefore might not have been migrated into OpenSearch. Similarly to the best-effort warning above, the recommended solution to this is a re-index for connectors suspected of having missing documents. Unfortunately due to the nature of this issue, there is little visibility into which specific documents may have experienced this. # Index Settings Source: https://docs.onyx.app/admins/advanced_configs/search_configs Configure search settings and parameters ## Overview From the **Search Settings** page, you can configure the embedding model, reranking, and a variety of advanced search and indexing options. Search settings overview page ### Embedding Model The embedding model is used to convert your documents into vectors that are stored in Vespa. These vectors are used to search for relevant documents when a user queries Onyx. A powerful embedding model can significantly improve the accuracy of your search results, but comes at the cost of additional memory and disk usage. Embedding model configuration page The best embedding models are generally available through a cloud provider such as Cohere or Google. To use a cloud provider, select the model you want to use, submit your credentials for the provider, and click **Continue**. Self-hosted models run on your own infrastructure and guarantee that your data does not leave your bounds. Embedding data at the scale that Onyx operates requires significant compute resources. If you want to use a self-hosted model, we strongly recommend you make a GPU available to Onyx's indexing model server container. In the **Self-hosted** tab, you can select a suggested model or follow the instructions to connect your own model. #### Embedding Swaps If you select a new embedding model, Onyx will need to re-index all of your data. During this process, the old embedding model will still be available for searches. While the swap is in progress, you will see the Search Settings page show details indexing progress. This process can take a while. Additionally, private user data is also being re-indexed, but are not displayed to the Admin Search Settings page. Embedding swap in progress ### Reranking Reranking is an optional step that can be used to improve the accuracy of your search results. A reranking model will assess and re-organize your search results based on the relevance of the documents to the query. This process adds a small amount of latency to your search results. Generally, re-ranking is only useful if you have a very large number of documents. Reranking configuration page ### Advanced Configs On the final page, you can configure a variety of advanced search settings. Multilingual expansion rephrases your queries into the specified other languages. This can be helpful for cross-language results. Multipass indexing creates chunks of varying sizes and stores them in the index. This can help the hybrid search algorithm better identify relevant sources. Contextual RAG adds additional document-level information to every chunk in the index. This can help the hybrid search algorithm better identify relevant sources. Contextual RAG can be very expensive as it adds a signficnat amount of data to every embedding call. Embedding precision may be set to either `bfloat16` or `float`. Setting the precision to `bfloat16` can reduce the memory usage of the index, but may slightly reduce the accuracy of the results. Setting this value will reduce the number of dimensions in the embedding vectors. This can reduce the memory usage of the index, but may reduce the accuracy of the results. Reduced dimension is only supported for OpenAI embedding models at this time. Advanced search configurations page # Spending Limits Source: https://docs.onyx.app/admins/advanced_configs/spending_limits Configure spending limits in Onyx ## Overview Spending limits allow you to configure LLM rate limits and throttling settings. These settings are found in the **Admin Panel** under **Appearance & Theming**. Rate limits can be applied globally, by User, or by User Group. Spending Limits # Tracing Source: https://docs.onyx.app/admins/advanced_configs/tracing Send LLM call traces to observability platforms to monitor and evaluate your Onyx deployment Tracing forwards every LLM call Onyx makes to an external observability platform so you can monitor latency, token usage, and cost, and evaluate response quality. Onyx supports [Braintrust](https://www.braintrust.dev) and [Langfuse](https://langfuse.com). Tracing is available on **self-hosted** deployments. It is not configurable on Onyx Cloud. ## Connect a provider Click your user profile icon, select **Admin Panel**, and open the **Tracing** tab under the **Usage** section of the sidebar. You can connect either or both providers — traces are sent to every connected provider. Create an API key in the [Braintrust dashboard](https://www.braintrust.dev/app) under **Settings → API Keys**. In Onyx, click **Connect** on the Braintrust card and fill in: * **API Key** — your Braintrust API key. * **Project Name** *(optional)* — the Braintrust project traces are logged to. Defaults to `Onyx`. * **API URL** *(optional)* — only needed for self-hosted Braintrust or non-default regions. Defaults to `https://api.braintrust.dev`. Create a key pair in your [Langfuse](https://cloud.langfuse.com) project settings under **Setup → API Keys**. In Onyx, click **Connect** on the Langfuse card and fill in: * **Secret Key** — your Langfuse secret key (`sk-...`). * **Public Key** — your Langfuse public key (`pk-...`). * **API Base URL** *(optional)* — defaults to the EU region (`https://cloud.langfuse.com`). Set this for the US region, another region, or a self-hosted Langfuse instance. Onyx validates the credentials before saving. Once connected, the card shows **Connected** and traces begin flowing within about 30 seconds — no restart required. ## Disconnect a provider Open the provider card, click the disconnect button, and confirm. Onyx stops sending new traces to that provider immediately. Traces already delivered are unaffected. ## Configuring with environment variables Configuring tracing from the Admin Panel is the recommended approach, but Onyx also honors environment variables for backwards compatibility. A provider configured through the UI takes precedence over its environment variables. | Provider | Variable | Description | | ---------- | --------------------- | -------------------------------------------------------------- | | Braintrust | `BRAINTRUST_API_KEY` | API key. Enables Braintrust tracing when set. | | Braintrust | `BRAINTRUST_PROJECT` | Project name traces are logged to. Defaults to `Onyx`. | | Braintrust | `BRAINTRUST_API_URL` | Custom API URL for self-hosted / non-default regions. | | Langfuse | `LANGFUSE_SECRET_KEY` | Secret key. Required (with the public key) to enable Langfuse. | | Langfuse | `LANGFUSE_PUBLIC_KEY` | Public key. Required (with the secret key) to enable Langfuse. | | Langfuse | `LANGFUSE_HOST` | Base URL for a non-default region or self-hosted Langfuse. | Providers configured through environment variables appear in the Tracing dashboard as configured via environment. You can adopt them into UI-managed configuration by connecting the provider from the Admin Panel. # White Labeling Source: https://docs.onyx.app/admins/advanced_configs/white_labeling Customize Onyx's branding and appearance White labeling allows you to customize Onyx's appearance to match your organization's identity. These settings are found in the **Admin Panel** under **Appearance & Theming**. White labeling is an [Enterprise Edition](/deployment/miscellaneous/enterprise_edition) feature. ## White Labeling Options ### Logo and Name You can customize the logo, the application name, or both independently: * **Custom Logo** — upload an image to replace the default Onyx logo shown in the top left corner and on the login page * **Application Name** — set a custom name displayed alongside or in place of the logo Custom Logo and Name ### Messaging Customize the text shown throughout the chat interface: * **Greeting Message** — shown to users when they start a new chat session * **Chat Header Text** — displayed in the header of the chat interface * **Chat Footer Text** — displayed in the footer of the chat interface Greeting Message, Chat Header, and Footer ### First Visit Notice Configure a notice shown to users the first time they access Onyx. The notice has the following options: | Option | Description | | ------------------- | --------------------------------------------------------------------------- | | **Show Notice** | Toggle to enable or disable the first visit notice | | **Notice Header** | Title text displayed at the top of the notice | | **Notice Content** | Body text of the notice | | **Require Consent** | When enabled, users must acknowledge the notice before they can access Onyx | First Visit Notice # Custom Agents Source: https://docs.onyx.app/admins/agents/overview Managing AI agents Onyx Agents are customized AI assistants with unique instructions, knowledge sources, and Actions. ## Managing Agents On the Agents page in the Admin Panel, you can see all of the Agents in your organization. From this page, you can create new Agents, edit existing configurations, designate featured Agents, hide or show certain Agents, and delete them. Onyx Agents Overview page showing available agents ## Creating Agents Navigate to the **Admin Panel** and click **Agents** in the sidebar. Click **New Agent** to create a new agent. Give your Assistant a name, description, instructions, and maybe even an icon. To help users understand how to use your Agent, you can add **Conversation Starters**. Onyx Agent Configuration page Onyx provides several methods for attaching information to Agents. Onyx Agent Knowledge configuration If **Use Knowledge** is toggled on but nothing is selected (as in the screenshot above), the agent will have access to anything accessible to the person using the agent. This includes: * Any files that the user has uploaded ("Your Files" in the admin view, visible from the Upload Files icon in the chat window for basic users chatting with the agent) * All documents from all public connectors * Documents that the user has access to in the external source for permission-synced connectors See the [Connectors](/admins/connectors/overview) page for more detail on permissions. Explicitly selecting anything in Add Knowledge will narrow the Agent's scope to *only* that selected knowledge. This can be useful because search quality tends to slowly degrade at scale, so in larger organizations narrowing the scope of what is searched over may improve answer quality. For Onyx versions prior to 3.0 and 3.x deployments that have not yet completed a migration to OpenSearch, the primary way of scoping access to connectors and granting an agent access to private connectors is to put the desired connectors into a [Document Set](/admins/managing_features/document_sets), then select that document set in the Document Sets section of the Add Knowledge pane. The OpenSearch migration note above is relevant for existing deployments upgrading to 3.x, not new deployments. This functionality is still available in Onyx 3.x+, but with OpenSearch enabled Onyx also provides a more granular way to attach knowledge to agents. By clicking on specific source types (added by creating a connector of that source type and indexing successfully), you can view the hierarchy of knowledge in your source and select files and folders you want your agent to have access to when searching for knowledge. Selecting a folder gives the agent access to all information in that folder and in all its sub-folders. Onyx Agent hierarchical knowledge selection showing folder and file browsing Add Actions to your Agent to enable it to perform specific tasks. See [Actions Overview](/admins/actions/overview) for more information. Onyx Agent Configuration page You can publish your Agent to your entire organization or share it with specific users or groups. If you set your Agent as **Featured**, your users will see it at the top of the Agents explorer. You can configure the default language model for your Agent. You can also configure certain knowledge options for your Agent, such as a knowledge cutoff date and overwriting the system prompt. Onyx Agent advanced configuration options Once you've published your Agent, you can find it in the **Explore Agents** page from the Chat sidebar. Onyx Explore Agents page # Anthropic Source: https://docs.onyx.app/admins/ai_models/anthropic Configure Anthropic Claude language models for Onyx ## Guide Access the Admin Panel from your user profile icon, then navigate to **Configuration → Language Models**. Select **Anthropic** from the available providers. Give this configuration a **Display Name**. Create an [API key](https://console.anthropic.com/dashboard) from the Anthropic API dashboard and paste it in the **API Key** field. Anthropic Provider Configuration In the **Advanced Options**, you will see a list of all models available from this provider. You may choose which models are visible to your users in Onyx. Setting visible models is useful when a provider publishes multiple models and versions of the same model. Lastly, decide whether the provider should be public to all users in Onyx. If set to private, the provider's models will be available to Admins and User Groups you explicitly assign the provider to. # Azure OpenAI Source: https://docs.onyx.app/admins/ai_models/azure_openai Configure Azure OpenAI for enterprise-grade GPT models ## Guide Go to the [Azure Portal](https://portal.azure.com/) and navigate to the Azure OpenAI Service. Azure OpenAI Service Click **Create** and fill out the required fields in each section. Default values are usually sufficient. The deployment may take a few minutes to complete. Azure OpenAI Deployment Go to the [Azure OpenAI Service](https://oai.azure.com/) and select your new AI resource. Navigate to the **Model Catalog** tab and select the model you want to use with Onyx. Click **Use this model** → **Deploy to selected resource**. Azure OpenAI Service Landing Page Azure OpenAI Model Deployment In your deployed model page, save the **Target URI** and **API Key**. Your **Target URI** has the **API Base**, **API Version**, and **Deployment Name** necessary to configure the provider in Onyx. Azure OpenAI Deployed Model Details If you see `I'm sorry, but I cannot assist with that request` in Onyx chat responses, update the model deployment **Content filter** to **Default** instead of **DefaultV2**. Azure OpenAI configuration page Access the Admin Panel from your user profile icon, then navigate to **Configuration → Language Models**. Select **Azure OpenAI** from the available providers. Give this configuration a **Display Name**. Paste your **API Key** into the **API Key** field. From your **Target URI**, extract the **API Base**, **API Version**, and **Deployment Name** Example: `https://onyxazureai.openai.azure.com/openai/deployments/gpt-4.1/chat/completions?api-version=2025-01-01-preview` Azure OpenAI Provider Configuration In the **Advanced Options**, you may select whether or not the provider is public to all users in Onyx. If set to private, the provider's models will be available to Admins and User Groups you explicitly assign the provider to. # Amazon Bedrock Source: https://docs.onyx.app/admins/ai_models/bedrock Configure Amazon Bedrock models for use with Onyx ## Authentication Methods Onyx supports 3 authentication methods for Amazon Bedrock: * Automatically authorizes Onyx through an IAM Role attached to the environment * Use when running on AWS infrastructure (EC2, EKS) To connect Onyx to Bedrock using IAM, create an IAM Role with the `AmazonBedrockLimitedAccess` policy. Optionally, you can attach the `AmazonBedrockFullAccess` and `AmazonBedrockMarketplaceAccess` policies. Once created, attach the IAM Role to the environment that Onyx is running in. For example, attach the IAM Role to your Onyx EC2 instance or EKS service account. * Manual credential management using an Access Key ID and Secret Access Key * Recommended for accessing Bedrock from non-AWS environments To connect Onyx to Bedrock using Access Keys, create an IAM User with the `AmazonBedrockLimitedAccess` policy. Optionally, you can attach the `AmazonBedrockFullAccess` and `AmazonBedrockMarketplaceAccess` policies. Once created, go to your IAM User's **Security Credentials** tab. Create a new **Access Key** and copy the **Access Key ID** and **Secret Access Key**. Provide these credentials to Onyx using one of the following methods: * Add them to your Onyx `.env` file as `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` * Add them to your AWS CLI config in `~/.aws/credentials` * Enter them directly in the Onyx Bedrock configuration UI * New method to access Bedrock generated from the AWS Bedrock Console * Recommended for accessing Bedrock from non-AWS environments To connect Onyx to Bedrock using an API Key, navigate to the Bedrock console, select **API keys** and create a **Long-term API key**. AWS will automatically create a new IAM User with the `AmazonBedrockLimitedAccess` policy. Submit your API key to Onyx through the Onyx Bedrock configuration UI. When using an IAM role, the role credentials must be attached to the Onyx environment. When using Access Keys or a Bedrock API Key, you must provide the credentials in the Onyx LLM configuration UI. ## Guide Determine if IAM, Access Keys, or a Bedrock API Key is the best authentication method for your environment. Click the above accordions to learn more about each method and how to set them up. Navigate to the **Model Catalog** and decide the models you want to use with Onyx. If you don't already have access to your desired models, you can request access through the Bedrock Console. If your models are not enabled, you will not be able to see them in Onyx! Ensure your models are available before continuing. Access the Admin Panel from your user profile icon, then navigate to **Configuration → Language Models**. Select **AWS Bedrock** from the available providers. Give your provider a **Display Name**. Determine your AWS region and enter it in **AWS Region Name**. Certain models are only available in specific regions or through cross-region inference profiles. Onyx will automatically determine what is available in your region. Depending on your authentication method, fill out `AWS Access Key ID` and `AWS Secret Access Key` or `AWS Bedrock API Key`. Once your region and credentials are set, click the **Fetch Available Model for Region** button. If you do not click the **Fetch Available Model for Region** button, you will see all Bedrock models listed even if you cannot use them. Bedrock Provider Configuration In the **Advanced Options**, you will see a list of all models available from this provider. You may choose which models are visible to your users in Onyx. Setting visible models is useful when a provider publishes multiple models and versions of the same model. Lastly, decide whether the provider should be public to all users in Onyx. If set to private, the provider's models will be available to Admins and User Groups you explicitly assign the provider to. # Bifrost Source: https://docs.onyx.app/admins/ai_models/bifrost Configure Bifrost as a language model gateway for Onyx ## Guide Configure Onyx to use models served through [Bifrost](https://docs.getbifrost.ai/overview). Onyx connects to your Bifrost gateway by fetching the models exposed at its `/v1/models` endpoint. Bifrost can expose models from multiple vendors behind a single endpoint. Make sure your Bifrost deployment is reachable from the Onyx server. You will need your Bifrost **API Base URL**. If your Bifrost deployment requires authentication, also generate a Bifrost **API Key**. Access the Admin Panel from your user profile icon, then navigate to **Configuration → Language Models**. Select **Bifrost** from the available providers. Give your provider a **Display Name**. Enter the **API Base URL** for your Bifrost gateway. If your gateway requires authentication, enter your **API Key**. Click **Fetch Available Models** to load the language models currently exposed by Bifrost. Onyx will import the model IDs returned by Bifrost and use the display names returned by the gateway when available. This is useful when your Bifrost gateway exposes models from multiple vendors such as Anthropic, OpenAI, or others. In the **Advanced Options**, you will see a list of all models available from this provider. You may choose which models are visible to your users in Onyx. Setting visible models is useful when a provider publishes multiple models and versions of the same model. Lastly, decide whether the provider should be public to all users in Onyx. If set to private, the provider's models will be available to Admins and User Groups you explicitly assign the provider to. # Custom Inference Provider Source: https://docs.onyx.app/admins/ai_models/custom_inference_provider Configure an OpenAI-compatible language model provider ## Guide If you want to use a language model provider that is not supported directly by Onyx, you can configure a custom inference provider. Your custom provider must provide OpenAI-compatible API endpoints. Determine your provider's API base URL. It should look something like `https://yourprovider.com/v1` or `http://localhost:12345/v1`. Access the Admin Panel from your user profile icon, then navigate to **Configuration → Language Models**. Select **Add Custom LLM Provider** from the available providers. Give your provider a **Display Name**. Enter your model's **Provider Name**. The **Provider Name** must match Litellm's [list of supported providers](https://docs.litellm.ai/docs/providers). In this example, the provider name is `vertex_ai`. Custom inference provider name Enter the provider's **Base URL**. Fill out the other optional fields if applicable. In the **Model Configurations** section, enter each model you want to make available through this provider. Lastly, you may select whether or not the provider is public to all users in Onyx. If set to private, the provider's models will be available to Admins and User Groups you explicitly assign the provider to. # Google Vertex AI Source: https://docs.onyx.app/admins/ai_models/google_ai Configure Google Vertex AI language models for use with Onyx ## Guide This guide walks through setting up Google Vertex AI language models for use with Onyx. Google Vertex AI and Google AI Studio serve the same models. However, Vertex AI has enterprise-grade features that may be useful for your organization. Go to the [Google Cloud Console Service Accounts Page](https://console.cloud.google.com/iam-admin/serviceaccounts) Select your project and click **Create Service Account**. Give your Service Account a name and a description. On the **Permissions** tab, grant the service account the **Agent Platform User** role. Google Cloud Console Service Accounts Page Google Cloud Console Service Account Configuration Click your newly created Service Account → **Keys** → **Add Key** → **Create new key**. Select **JSON** as the key type and click **Create**. The key will be automatically downloaded to your computer. Access the Admin Panel from your user profile icon, then navigate to **Configuration → Language Models**. Select **Google Cloud Vertex AI** from the available providers. Give this configuration a **Display Name**. Upload your JSON key to the **Credentials File** field. If relevant, specify a **Location**. In the **Advanced Options**, you will see a list of all models available from this provider. You may choose which models are visible to your users in Onyx. Setting visible models is useful when a provider publishes multiple models and versions of the same model. Lastly, decide whether the provider should be public to all users in Onyx. If set to private, the provider's models will be available to Admins and User Groups you explicitly assign the provider to. # LiteLLM Proxy Source: https://docs.onyx.app/admins/ai_models/litellm_proxy Configure LiteLLM Proxy as a language model gateway for Onyx ## Guide Configure Onyx to use models exposed by your LiteLLM Proxy server. Onyx reads the available models from the LiteLLM Proxy `/v1/models` endpoint. This is a good option when you want one gateway in front of multiple providers or self-hosted backends. Deploy LiteLLM Proxy and make sure it is reachable from the Onyx server. You will need the LiteLLM Proxy **API Base URL** and **API Key**. The local default is commonly `http://localhost:4000`. Access the Admin Panel from your user profile icon, then navigate to **Configuration → Language Models**. Select **LiteLLM Proxy** from the available providers. Give your provider a **Display Name**. Enter the proxy **API Base URL** and **API Key**. Click **Fetch Available Models** to load the models currently exposed by your LiteLLM Proxy instance. Onyx stores the model IDs returned by LiteLLM Proxy and makes those models available to your users. This is useful when LiteLLM is routing requests to multiple providers through a single gateway. In the **Advanced Options**, you will see a list of all models available from this provider. You may choose which models are visible to your users in Onyx. Setting visible models is useful when a provider publishes multiple models and versions of the same model. Lastly, decide whether the provider should be public to all users in Onyx. If set to private, the provider's models will be available to Admins and User Groups you explicitly assign the provider to. # LM Studio Source: https://docs.onyx.app/admins/ai_models/lm_studio Using LM Studio with Onyx ## Guide Configure Onyx to use models served by [LM Studio](https://lmstudio.ai/). Onyx has a built-in integration with LM Studio that auto-discovers your loaded models, including their capabilities (vision, reasoning) and context length. Download LM Studio from [lmstudio.ai](https://lmstudio.ai/) and load the models you want to use. Start the LM Studio local server: ```bash theme={null} lms server start --port 1234 ``` LM Studio runs on port `1234` by default. For best results, use a model with strong instruction-following and tool-use capabilities (e.g., Qwen 3.5). If LM Studio is running on a different machine than Onyx, make sure the server is accessible from the Onyx host (e.g., `http://:1234`). **Running Onyx in Docker on the same machine as LM Studio?** By default, LM Studio binds only to `127.0.0.1`, which is unreachable from inside an Onyx container. To fix: * In LM Studio's **Developer** tab, enable **"Serve on Local Network"** (or set the host to `0.0.0.0`) and restart the server. * Use `http://host.docker.internal:1234` as the **API Base URL** instead of `http://localhost:1234`. See [LM Studio's docs](https://lmstudio.ai/docs/developer/core/server/serve-on-network) for more details. Access the Admin Panel from your user profile icon, then navigate to **Configuration → Language Models**. Select **LM Studio** from the available providers. Give your provider a **Display Name**. Set the **API Base URL** to your LM Studio server address (e.g., `http://localhost:1234`). If Onyx is running in Docker on the same machine as LM Studio, use `http://host.docker.internal:1234` instead — `localhost` inside the container points to the container itself, not your host. Make sure LM Studio is set to **"Serve on Local Network"** (see the Info callout in the previous step). Onyx will automatically connect and discover your loaded models. LM Studio Provider Configuration In the **Advanced Options**, you will see a list of all models available from this provider. You may choose which models are visible to your users in Onyx. Setting visible models is useful when a provider publishes multiple models and versions of the same model. Lastly, decide whether the provider should be public to all users in Onyx. If set to private, the provider's models will be available to Admins and User Groups you explicitly assign the provider to. # Ollama Source: https://docs.onyx.app/admins/ai_models/ollama Using Ollama with Onyx ## Guide Configure Onyx to use models served by [Ollama](https://ollama.com/). The [Ollama GitHub repository](https://github.com/ollama/ollama?tab=readme-ov-file#ollama) details how to download and deploy models on Ollama. If self-hosting, Ollama is configured to run on port `11434` by default. You can also configure Onyx to use [Ollama's managed cloud service](https://ollama.com/cloud). Access the Admin Panel from your user profile icon, then navigate to **Configuration → Language Models**. Select **Ollama** from the available providers. Give your provider a **Display Name**. If using Ollama Cloud, enter your Ollama Cloud **API Key**. Click the **Fetch Available Models** button to see the models available in your Ollama instance. Ollama Provider Configuration In the **Advanced Options**, you will see a list of all models available from this provider. You may choose which models are visible to your users in Onyx. Setting visible models is useful when a provider publishes multiple models and versions of the same model. Lastly, decide whether the provider should be public to all users in Onyx. If set to private, the provider's models will be available to Admins and User Groups you explicitly assign the provider to. # OpenAI Source: https://docs.onyx.app/admins/ai_models/openai Configure OpenAI language models for Onyx ## Guide Access the Admin Panel from your user profile icon, then navigate to **Configuration → Language Models**. Select **OpenAI** from the available providers. Give this configuration a **Display Name**. Create an [API key](https://platform.openai.com/api-keys) from the OpenAI API dashboard and paste it in the **API Key** field. OpenAI Provider Configuration In the **Advanced Options**, you will see a list of all models available from this provider. You may choose which models are visible to your users in Onyx. Setting visible models is useful when a provider publishes multiple models and versions of the same model. Lastly, decide whether the provider should be public to all users in Onyx. If set to private, the provider's models will be available to Admins and User Groups you explicitly assign the provider to. # OpenRouter Source: https://docs.onyx.app/admins/ai_models/openrouter Using OpenRouter with Onyx ## Guide Configure Onyx to use models served by [OpenRouter](https://openrouter.ai/). Log in to your OpenRouter account and create a new API key. Access the Admin Panel from your user profile icon, then navigate to **Configuration → Language Models**. Select **OpenRouter** from the available providers. Give your provider a **Display Name**. Enter your OpenRouter **API Key**. Click the **Fetch Available Models** button to see the models currently available on OpenRouter. OpenRouter Provider Configuration In the **Advanced Options**, you will see a list of all models available from this provider. You may choose which models are visible to your users in Onyx. Setting visible models is useful when a provider publishes multiple models and versions of the same model. Lastly, decide whether the provider should be public to all users in Onyx. If set to private, the provider's models will be available to Admins and User Groups you explicitly assign the provider to. # Overview Source: https://docs.onyx.app/admins/ai_models/overview Configure language model providers and models in Onyx Use this page to configure the language models available for chat, agents, and other text-based workflows in Onyx. Image generation and voice are configured separately in [Image Generation](/admins/actions/image_generation) and [Voice Mode](/admins/actions/voice_mode). ## Language Models Navigate to **Admin Panel → Language Models** to choose which providers your workspace can use, which models are visible, and which models should be the default or fast option in Onyx. Language Models page overview ### Provider Types These providers give you direct access to a model vendor's hosted API. Common choices include **OpenAI** and **Anthropic**. This is usually the simplest setup when you want fast access to the provider's latest flagship models. These providers expose language models through a broader cloud or routing layer. Common choices include **Azure OpenAI**, **Amazon Bedrock**, **Google Vertex AI**, **OpenRouter**, **LiteLLM Proxy**, and **Bifrost**. They are useful when you need enterprise controls, cloud alignment, regional hosting options, or access to multiple model families from one integration point. These options let you run open-weight models on your own infrastructure or local hardware. Onyx includes built-in integrations for [Ollama](/admins/ai_models/ollama) and [LM Studio](/admins/ai_models/lm_studio). This is a good fit when your team needs local development workflows, tighter data residency, or lower per-token costs. If your provider is not listed directly, you can still connect it through an OpenAI-compatible API. This covers custom gateways, hosted inference endpoints, and internal model platforms that expose an OpenAI-style `/chat/completions` or `/models` interface. ### Choosing a Good Starting Setup If cloud-hosted models are approved for your organization, they are usually the best default choice because they are easier to operate and generally provide the best capability-to-cost tradeoff. * Start with one primary provider for most users. * Use a recent **GPT**, **Claude**, or **Gemini** family model as your default if you want the strongest out-of-the-box experience. * Use **Bedrock**, **Vertex AI**, **Azure OpenAI**, **OpenRouter**, **LiteLLM Proxy**, or **Bifrost** when procurement, routing, or cloud alignment matters more than a direct vendor integration. * Use open-weight families such as **Llama**, **Qwen**, **DeepSeek**, or **gpt-oss** if you are self-hosting. * Keep the visible model list short so users are choosing between a few intentional options instead of every possible version. Self-hosting is best for advanced teams that already know which models they want to run and how they will operate them. ## Configure Your Providers ## Best Practices * Review the terms, privacy posture, and data processing terms of every provider you enable. * Limit the visible model list to the models you actually want users to choose from. * Use private providers and access controls for costly, experimental, or team-specific models. * Decide on a default model at the organization level before rolling the page out broadly. * Make sure internal guidance is clear about what data users can send to each provider. # Custom Analytics Source: https://docs.onyx.app/admins/analytics/custom_analytics Configure a custom analytics provider in Onyx **Enterprise Edition Feature** This feature requires an Enterprise plan. [View plans](/admins/billing/overview) or [contact sales](https://onyx.app/contact-sales) to learn more. Onyx Enterprise Edition allows you to configure a custom analytics provider. Set the `CUSTOM_ANALYTICS_SECRET_KEY` environment variable to some random string. Make sure you have the value saved temporarily somewhere. Re-deploy Onyx. Go to the Custom Analytics tab in the Admin Panel. This snippet would normally be placed within the `` tags at the base of your project. For the Secret Key, use the value you saved in Step 1. The ` ``` ### Self-Hosted Deployment For self-hosted Onyx instances, you'll need to build and host the widget yourself. Clone the [Onyx repository](https://github.com/onyx-dot-app/onyx) from GitHub. ```bash theme={null} cd widget/ ``` ```bash theme={null} npm install ``` Navigate to your Onyx admin panel and create a new API key specifically for the widget. Creating a widget API key in the Onyx admin panel Create a **limited-scope API key** with only chat permissions. Never use admin or full-access keys since the API key will be visible in client-side code. For builds with baked-in configuration, create a `.env` file: ```bash theme={null} cp .env.example .env ``` Edit `.env` and set your backend URL and API key: ``` VITE_WIDGET_BACKEND_URL=https://your-backend.com VITE_WIDGET_API_KEY=your_api_key ``` For **cloud-style deployment** (config via HTML attributes): ```bash theme={null} npm run build:cloud ``` For **self-hosted deployment** (config baked into bundle): ```bash theme={null} npm run build:self-hosted ``` Upload `dist/onyx-widget.js` to your CDN or web server. ### Customer Embed Code After deployment, provide customers with the embed code: **Cloud-style (attributes required):** ```html theme={null} ``` **Self-hosted (config baked in):** ```html theme={null} ``` ## Configuration Reference ### Required Attributes | Attribute | Type | Description | | ------------- | ------ | -------------------------- | | `backend-url` | string | Your Onyx backend API URL | | `api-key` | string | API key for authentication | #### `backend-url` The URL of your Onyx backend API. This is where the widget sends chat requests. * **Onyx Cloud**: Use `https://cloud.onyx.app` or your tenant-specific URL * **Self-hosted**: Use your Onyx instance URL (e.g., `https://onyx.yourcompany.com`) ```html theme={null} ``` #### `api-key` A valid Onyx API key for authenticating widget requests. **This key is visible in client-side code**, so always use a limited-scope key. ```html theme={null} ``` For self-hosted builds with baked-in config, `backend-url` and `api-key` can be set via environment variables during build instead of HTML attributes. ### Optional Attributes | Attribute | Type | Default | Description | | ------------------- | ------- | ------------- | ------------------------------------------------ | | `agent-id` | number | `undefined` | Specific agent/persona to use | | `agent-name` | string | `"Assistant"` | Display name in header | | `logo` | string | Onyx logo | URL to custom logo image | | `primary-color` | string | `#1c1c1c` | Primary brand color (buttons, accents) | | `background-color` | string | `#e9e9e9` | Widget background color | | `text-color` | string | `#000000bf` | Text color (75% opacity black) | | `mode` | string | `"launcher"` | Display mode: `"launcher"` or `"inline"` | | `include-citations` | boolean | `false` | Show citation badges linking to source documents | #### `include-citations` When enabled, assistant messages display clickable citation badges below the response text. Each badge shows a sequential number and the source document title, linking directly to the original document. ```html theme={null} ``` **Be mindful of document access when enabling citations.** The widget will cite any documents accessible to the configured agent or API key. If the agent has access to private or internal documents, citation links may point to resources that end users do not have permission to view. To avoid exposing private document links, either scope the agent's document access to only public-facing sources, or disable citations for public-facing widget deployments. ## API Key Security The widget's API key is exposed in client-side code. Always create a dedicated API key with: * **Limited permissions** - Only chat access, no admin features * **Rate limiting** - Prevent abuse from malicious actors * **Monitoring** - Track usage and detect anomalies In your Onyx admin panel, create a new API key with minimal permissions. Configure rate limits appropriate for your expected usage. Regularly review API key usage for unusual patterns. ## Browser Support * Chrome/Edge 90+ (Chromium) * Firefox 90+ * Safari 15+ * Mobile Safari (iOS 15+) * Mobile Chrome (Android) **Need help with setup?** Contact your Onyx administrator for API key configuration or deployment assistance. # Quickstart Source: https://docs.onyx.app/deployment/getting_started/quickstart Recommended way to deploy Onyx in minutes ## Onyx CLI The recommended way to install Onyx is the guided installer built into the [Onyx CLI](/overview/onyx_anywhere/cli): ```bash theme={null} uv tool install onyx-cli && onyx-cli deploy install ``` The installer will: * Check your system resources and requirements (installing Docker on Linux if needed) * Let you choose between **Lite** and **Standard** deployment modes * Prompt for the version of Onyx to deploy * Set up the deployment configuration in `~/.config/onyx` * Pull the Onyx containers, start them, and wait until every service is healthy After installation, the same command group manages the deployment: `onyx-cli deploy upgrade`, `status`, `logs`, `stop`, and `uninstall`. Full documentation for `onyx-cli deploy` and its lifecycle commands. ## Installation Scripts The installation scripts are thin wrappers around the CLI: they install `onyx-cli` if needed and run `onyx-cli deploy install`, producing the same deployment as the command above. Use them when you want a single copy-paste one-liner: ```bash theme={null} curl -fsSL https://onyx.app/install_onyx.sh | bash ``` ```powershell theme={null} irm https://onyx.app/install_onyx.ps1 | iex ``` Or download the script and run it manually: Download **install.sh** and run it with `bash install.sh`. Download **install.ps1** and run it with `.\install.ps1` in PowerShell. Older versions of the scripts were standalone and installed into a directory called **onyx\_data**. The Onyx CLI detects those deployments and manages them in place — see [migrating an existing deployment](/deployment/local/onyx_cli#migrating-an-existing-deployment). ## Next Steps Install the Onyx desktop application for a native experience on Windows, macOS, and Linux. Follow our guide to deploy Onyx on an AWS EC2 instance. # Resourcing Source: https://docs.onyx.app/deployment/getting_started/resourcing Resource requirements for deploying Onyx ## Resourcing Overview ### Onyx Lite | Resource | Minimum | Preferred | | -------- | ------- | --------- | | CPU | 2 vCPU | 4 vCPU | | RAM | 2 GB | 4 GB | | Disk | 10 GB | 50 GB | Onyx Lite uses under 1GB of memory at baseline. Disk and memory usage scale with the number of files users upload to the system, since PostgreSQL handles file storage in Lite mode. ### Onyx Standard | Resource | Minimum | Preferred | | -------- | --------------------------- | ------------------------------------- | | CPU | 4 vCPU | 8+ vCPU | | RAM | 10 GB | 16+ GB | | Disk | 32 GB + \~2.5x indexed data | 500 GB for organizations \<5000 users | OpenSearch enforces a read-only block on indices when disk usage hits the flood stage watermark (default 95%), which effectively blocks all writes. Monitor disk usage and plan capacity accordingly. ## Local Deployment (Docker) You can control the resources available to Docker in the **Resources** section of the Docker Desktop settings menu. Often old, unused Docker images take up sizeable disk space. To clean up dangling images, run `docker image prune`. ## Cloud Providers (AWS, GCP, etc.) For small to mid scale deployments, we recommend deploying Onyx to a single instance in your cloud provider of choice. When evaluating your instance, follow the Preferred resources in the table above. ### Onyx Lite | Provider | Recommended Instance Type | | -------- | ------------------------- | | AWS | `t3.medium` | | GCP | `e2-medium` | | Azure | `B2s` | ### Onyx Standard | Provider | Recommended Instance Type | | ------------ | ----------------------------------------------- | | AWS | `m7g.xlarge` | | GCP | `e2-standard-4` or `e2-standard-8` | | Azure | `D4s_v3` | | DigitalOcean | Meet the preferred resources in the table above | ## Container-Specific Resourcing (Standard) For more efficient scaling, you can dedicate resources to each Onyx container using Kubernetes or AWS EKS. See the [Onyx Helm chart](https://github.com/onyx-dot-app/onyx/blob/main/deployment/helm/charts/onyx/values.yaml) `values.yaml` for our default requests and limits. | Component | CPU | Memory | | ------------------------ | ---------- | ------ | | `api_server` | 1 | 2 Gi | | `background` | 2 | 8 Gi | | `indexing_model_server` | 2 | 4 Gi | | `inference_model_server` | 2 | 4 Gi | | `postgres` | 2 | 2 Gi | | `opensearch` | 2 | 4 Gi | | `nginx` | 250m (1/4) | 128 Mi | If you are using cloud-based embedding models (e.g. OpenAI, Cohere, etc.) instead of locally hosted ones, the `indexing_model_server` and `inference_model_server` will use significantly less memory. All together, this comes out to a total available node size of at least \~12 CPU and \~24GB of Memory. ## Container-Specific Resourcing (Lite) Onyx Lite runs only four services. All storage is consolidated onto PostgreSQL. | Component | CPU | Memory | | ------------ | ---------- | ------ | | `api_server` | 1 | 1 Gi | | `web_server` | 250m (1/4) | 512 Mi | | `postgres` | 1 | 1 Gi | | `nginx` | 250m (1/4) | 128 Mi | Memory usage in Lite mode scales with the number of user-uploaded files, since PostgreSQL handles file storage, caching, and session management. ## How Resource Requirements Scale The main driver of resource requirements for Standard mode is the number of indexed documents. This primarily affects the search index (OpenSearch), which is responsible for storing documents and handling search requests. ### OpenSearch Memory OpenSearch memory is split roughly 50/50 between the JVM heap and the OS file system cache. Both halves are critical — the heap handles indexing and search operations while the file system cache keeps frequently accessed index segments in memory for fast reads. Key rules for JVM heap sizing: * Set `Xms` and `Xmx` to **50% of available RAM** (the other 50% goes to OS/file cache) * **Never exceed 32 GB heap** — beyond this, Java disables compressed ordinary object pointers, causing significant performance degradation ### Storage Overhead OpenSearch adds overhead on top of the raw source data. The formula for on-disk storage is: ``` Storage = Source data × (1 + replicas) × 1.45 ``` The 1.45 multiplier accounts for indexing overhead (\~10%), Linux reserved space (\~5%), and OpenSearch internal overhead (\~20%), plus a safety margin. Onyx defaults to 0 replicas for single-node deployments, so storage is approximately **1.45× the source data size**. ### Scaling Guidelines OpenSearch resource requirements scale linearly with the volume of indexed data. The exact ratio depends on deployment size — large distributed clusters are more efficient per GB than single-node deployments due to fixed per-node overhead (cluster management, garbage collection, segment merging). Industry guidelines for large clusters suggest a memory-to-data ratio of around 1:16 for search-heavy workloads. However, for the **single-node deployments typical of self-hosted Onyx**, the fixed overhead per node is a much larger fraction of total resources. Based on our experience, we recommend the following for single-node or small-cluster deployments: | Scale | Memory per 1 GB of source docs | CPU per 1 GB of source docs | | ---------------- | ------------------------------ | --------------------------- | | Small (\< 5 GB) | \~2 GB | \~0.25 CPU | | Medium (5–50 GB) | \~1.5 GB | \~0.25 CPU | | Large (50+ GB) | \~1 GB | \~0.2 CPU | The per-GB cost decreases at larger scale because the fixed baseline overhead is amortized. At very large scale, consider a dedicated OpenSearch cluster or a managed service. Other factors that may affect resource requirements include: * The embedding model and vector dimensions * Whether you have quantization and dimensional reduction enabled * Query throughput and concurrency ### Resourcing Example For a deployment with 10GB of text content, your `opensearch` component will need: * Memory: 4 (base) + 10 × 1.5 = 19 GB * CPU: 2 (base) + 10 × 0.25 = 4.5 cores If deploying in a single instance, this would be *in addition to* the base requirements. Overall, that would take us to > \= 9 CPU and >= 35GB of memory. Given these requirements, a `m7g.2xlarge` or `c5.4xlarge` EC2 instance would be appropriate. If deploying with Kubernetes or AWS EKS, this would give a per-component resource allocation of: | Component | CPU | Memory | | ------------------------ | --- | ------ | | `api_server` | 1 | 2 Gi | | `background` | 2 | 8 Gi | | `indexing_model_server` | 2 | 4 Gi | | `inference_model_server` | 2 | 4 Gi | | `postgres` | 2 | 4 Gi | | `opensearch` | 5 | 19 Gi | Total available node size: \~14 CPU and \~41GB of Memory. ## Next Steps Deploy Onyx locally with Docker. Deploy Onyx on an EC2 instance. # Deploying Craft Source: https://docs.onyx.app/deployment/local/craft Choose and prepare a sandbox runtime for self-hosted Craft Craft runs generated code in isolated sandboxes and sends sandbox network traffic through an egress proxy. Self-hosted deployments can run these sandboxes in Kubernetes or Docker. Deploy sandbox pods, the proxy, RBAC, and workers with the Onyx Helm chart. Run sandbox containers and the proxy on a trusted single Docker host. Use Kubernetes if more than a few people will use Craft, especially when they may work concurrently. Each active user needs a sandbox, so Docker Compose is best suited to small, single-host deployments. | | Kubernetes | Docker Compose | | --------------- | ------------------------------------- | ----------------------------------------- | | Sandbox runtime | One pod per active user | One container per active user | | Recommended for | Production and multi-node deployments | Single-host self-hosted deployments | | Provisioning | Onyx Helm chart | `onyx-cli deploy install --include-craft` | | Host access | Kubernetes API through scoped RBAC | Docker socket access on the host | ## Requirements Both deployment paths require: * A full Onyx deployment with the vector database and background workers. Craft does not run on Onyx Lite. * A supported Onyx release and matching application and sandbox image versions. * An Onyx URL that the sandbox runtime can reach, configured as `SANDBOX_API_SERVER_URL`. * Capacity for a sandbox per active Craft user. * An Anthropic, OpenAI, or OpenRouter provider configured after deployment. Sandboxes execute model-generated code. Review [Craft Architecture](/security/architecture/craft) before enabling Craft, especially the sandbox, network, credential, and sharing boundaries. ## After the runtime is ready In **Admin Panel → Language Models**, add an Anthropic, OpenAI, or OpenRouter provider and make at least one model available to your Craft users. Open **Admin Panel → Craft → Access**. Keep the workspace default off for a limited rollout, or enable Craft for everyone. As an enabled user, start a Craft session, send a prompt that creates a file, and open or download the result. Configure external services under **Admin Panel → Craft → Apps** and reusable workflows under **Craft → Skills**. Configure access, models, Apps, and workspace instructions. Understand sandbox isolation, egress, credentials, and approvals. # Docker Compose Source: https://docs.onyx.app/deployment/local/craft_docker_compose Deploy Craft sandboxes on a trusted Docker host Docker Compose runs one sandbox container per active Craft user. Use this path for a small, single-host Onyx deployment that you trust and control. If more than a few people will use Craft, especially concurrently, deploy Craft on [Kubernetes](/deployment/local/craft_kubernetes) instead. Craft gives the API server and background container read-write access to the Docker socket. This read-write access is effectively root access to the host. The sandbox proxy receives read-only socket access. ## Requirements * A full Docker Compose deployment of Onyx 4.0.6 or later * Docker Engine with Compose * A host with capacity for the Onyx stack and active sandbox containers * An Onyx URL reachable through the sandbox proxy Craft does not run with the Onyx Lite Compose overlay. ## New deployment Run the [Onyx CLI](/deployment/local/onyx_cli) installer with the Craft overlay: ```bash theme={null} onyx-cli deploy install --include-craft ``` The installer downloads `docker-compose.craft.yml`, enables Craft, selects the Docker sandbox backend, creates the sandbox bridge network and proxy CA volume, and starts the deployment. The examples below use the CLI's default deployment directory. For a deployment created by an older version of the `install.sh` script, replace `~/.config/onyx` with your `onyx_data` directory (e.g. `onyx_data/deployment/.env`). Open `~/.config/onyx/deployment/.env` and set the Onyx URL: ```dotenv theme={null} ONYX_SERVER_URL=https://onyx.example.com ``` Then recreate the affected services with both Compose files: ```bash theme={null} cd ~/.config/onyx/deployment docker compose \ -f docker-compose.yml \ -f docker-compose.craft.yml \ up -d --force-recreate ``` ## Existing deployment Set `ONYX_SERVER_URL` in the existing deployment's `.env`, then rerun the installer: ```bash theme={null} onyx-cli deploy install --include-craft ``` The installer adds the Craft overlay and updates the existing `.env` with: ```dotenv theme={null} ENABLE_CRAFT=true SANDBOX_BACKEND=docker ``` Setting `ENABLE_CRAFT=true` without the overlay is not sufficient. The overlay mounts the Docker socket, starts the sandbox proxy, and attaches the API server and background worker to the sandbox network. ## Set the Onyx URL For production, use the public HTTPS URL users use to reach Onyx: ```dotenv theme={null} ONYX_SERVER_URL=https://onyx.example.com ``` For local Docker Desktop on macOS or Windows, use the host port selected by the installer: ```dotenv theme={null} ONYX_SERVER_URL=http://host.docker.internal:3000 ``` On Linux, use a hostname or host address reachable from Docker containers. Compose service names such as `api_server` and `nginx` do not resolve from the isolated sandbox bridge. ## Plan host capacity Docker sandboxes default to one CPU and 2 GB of memory each: ```dotenv theme={null} SANDBOX_DOCKER_CPU_LIMIT=1.0 SANDBOX_DOCKER_MEMORY_LIMIT=2g ``` Budget for the base Onyx services plus the number of users who may run Craft concurrently. An idle sandbox is snapshotted and stopped after 3,600 seconds by default; change this with `SANDBOX_IDLE_TIMEOUT_SECONDS` when faster cleanup or longer-lived sandboxes are required. The sandbox image follows `IMAGE_TAG`. Keep the Onyx backend and sandbox on the same release. Normal deployments should not set `SANDBOX_CONTAINER_IMAGE` separately. ## Build Craft from source `docker compose up --build` builds the Onyx services declared in the Compose files. It does not build the Craft sandbox image because sandboxes are created dynamically by the API server rather than running as a Compose service. From the root of an Onyx source checkout, build the sandbox image separately with a local, non-mutable tag: ```bash theme={null} docker build \ -t onyxdotapp/sandbox:local-source \ -f backend/onyx/server/features/build/sandbox/image/Dockerfile \ backend/onyx/server/features/build/sandbox/image ``` Set the image in the `.env` used by your source checkout: ```dotenv theme={null} SANDBOX_CONTAINER_IMAGE=onyxdotapp/sandbox:local-source ``` Then build and recreate the Onyx services with the Craft overlay: ```bash theme={null} cd deployment/docker_compose docker compose \ -f docker-compose.yml \ -f docker-compose.craft.yml \ up -d --build --force-recreate ``` Do not use `latest`, `edge`, or `beta` for a locally built sandbox image. The API server treats these tags as mutable and attempts to refresh them from the registry before provisioning. Use a tag such as `local-source`. Setting `IMAGE_TAG` does not build the corresponding `onyxdotapp/sandbox:${IMAGE_TAG}` image. Either build that sandbox tag separately or set `SANDBOX_CONTAINER_IMAGE` explicitly. Recreate `api_server` and `background` after changing the setting. Existing `sandbox-*` containers continue using the image with which they were created and must be terminated and provisioned again to use the new image. If you instead launch from a staged directory such as `onyx_data/deployment`, copy the setting into that directory's `.env`. Staged deployment directories do not contain the source checkout expected by the Compose build contexts, so use already-built or published images with `--no-build`. ## Verify the deployment Confirm the core services and proxy are running: ```bash theme={null} cd ~/.config/onyx/deployment docker compose \ -f docker-compose.yml \ -f docker-compose.craft.yml \ ps api_server background sandbox-proxy ``` After configuring a model and user access, send a prompt in Craft. A sandbox container should appear: ```bash theme={null} docker ps --filter label=onyx.app/component=craft-sandbox ``` The `background` service includes the worker used for Scheduled Task runs; no separate Compose service is required. ## Network and host security Sandbox containers join only the external `onyx_craft_sandbox` bridge. They cannot resolve PostgreSQL, Redis, object storage, or the API server by Compose service name. Their outbound HTTP and HTTPS traffic passes through `sandbox-proxy`, which enforces App policies and injects credentials after a request is approved. On cloud VMs, block sandbox access to the instance metadata service at the host or platform level. On EC2, require IMDSv2 with `HttpTokens=required` and apply a host firewall rule that blocks Docker bridge traffic to `169.254.169.254`. See [Craft Architecture](/security/architecture/craft) for the complete trust and network model. ## Troubleshooting Confirm `ENABLE_CRAFT=true` and `SANDBOX_BACKEND=docker`, then recreate the API server and web application. Include both `docker-compose.yml` and `docker-compose.craft.yml` in the Compose command. Set the value in the deployment directory's `.env` and recreate the API server, background worker, and sandbox proxy with the Craft overlay. Replace `api_server`, `nginx`, or another Compose-only hostname with the public Onyx URL or a host address reachable from Docker containers. Run `docker compose -f docker-compose.yml -f docker-compose.craft.yml logs sandbox-proxy`. Check `ONYX_SERVER_URL`, PostgreSQL and Redis availability, the `sandbox_proxy_ca` volume, and access to the Docker socket. Rerun `onyx-cli deploy install --include-craft`. If automatic creation fails, create the resources and restart the deployment: ```bash theme={null} docker network create onyx_craft_sandbox docker volume create sandbox_proxy_ca ``` Inspect the sandbox container logs and host memory pressure. Increase `SANDBOX_DOCKER_MEMORY_LIMIT` or `SANDBOX_DOCKER_CPU_LIMIT` only when the host has enough capacity for every concurrent sandbox. Compare the Docker Compose and Kubernetes paths. Configure models and user access after deployment. # Kubernetes Source: https://docs.onyx.app/deployment/local/craft_kubernetes Deploy Craft sandboxes with the Onyx Helm chart Use the Onyx Helm chart to deploy Craft with Kubernetes sandboxes. The chart creates the sandbox namespace, PodTemplate, RBAC, egress proxy, NetworkPolicies, and Scheduled Task worker used by Craft. ## Requirements * Kubernetes 1.33 or later * A full Onyx Helm deployment with the vector database enabled * Nodes with enough CPU, memory, and ephemeral storage for active sandboxes * A URL that sandbox pods can use to reach the Onyx API The chart fails the install or upgrade when Craft is enabled on an older Kubernetes version, when the sandbox backend is not `kubernetes`, when `SANDBOX_API_SERVER_URL` is empty, or when sandbox push authentication is not configured. ## Prepare sandbox nodes By default, sandbox pods select nodes with this label: ```text theme={null} onyx.app/workload=sandbox ``` Label each node that can run sandboxes: ```bash theme={null} kubectl label node onyx.app/workload=sandbox ``` The default sandbox toleration also supports nodes dedicated with this taint: ```bash theme={null} kubectl taint node workload=sandbox:NoSchedule ``` The taint is optional. The node label is required unless you replace `sandboxPod.nodeSelector` with a selector that matches your cluster. ## Create the sandbox push Secret Craft uses an Ed25519 key to authenticate file and history pushes into sandbox pods. Generate a key and store it in the Onyx namespace: ```bash theme={null} SANDBOX_PUSH_PRIVATE_KEY="$(python3 -c 'import base64; from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey; from cryptography.hazmat.primitives.serialization import Encoding, NoEncryption, PrivateFormat; key = Ed25519PrivateKey.generate(); print(base64.b64encode(key.private_bytes(Encoding.Raw, PrivateFormat.Raw, NoEncryption())).decode())')" kubectl create namespace onyx --dry-run=client -o yaml | kubectl apply -f - kubectl -n onyx create secret generic onyx-sandbox-push-secret \ --from-literal=private_key="$SANDBOX_PUSH_PRIVATE_KEY" unset SANDBOX_PUSH_PRIVATE_KEY ``` Keep this Secret stable across upgrades. Replacing the key while sandboxes are running interrupts authenticated pushes until the affected components and sandboxes are recreated. ## Configure Helm Add the following settings to the values file used by your existing Onyx deployment. If `configMap` or `auth` is already present, merge these entries under the existing keys rather than adding a second block. ```yaml values.yaml theme={null} configMap: ENABLE_CRAFT: "true" SANDBOX_BACKEND: "kubernetes" SANDBOX_API_SERVER_URL: "https://onyx.example.com" auth: sandboxPushSecret: enabled: true existingSecret: "onyx-sandbox-push-secret" ``` `SANDBOX_API_SERVER_URL` can be the public Onyx URL or a cluster-internal URL. Use a scheme and hostname that resolve from the sandbox proxy and route to the Onyx API. Install or upgrade Onyx with your complete deployment values: ```bash theme={null} helm upgrade --install onyx onyx/onyx \ --namespace onyx \ --create-namespace \ --values onyx-values.yaml ``` Replace `onyx-values.yaml` with the path to the values file used by your deployment. Alternatively, save only the Craft settings in a separate `craft-values.yaml` overlay. Pass your existing deployment values first and the Craft overlay second so Helm combines them: ```bash theme={null} helm upgrade --install onyx onyx/onyx \ --namespace onyx \ --create-namespace \ --values onyx-values.yaml \ --values craft-values.yaml ``` ## Plan sandbox capacity Each active user receives a sandbox pod. The main sandbox container has these defaults: | Resource | Request | Limit | | ----------------- | ------- | ------- | | CPU | `1000m` | `2000m` | | Memory | `2Gi` | `10Gi` | | Ephemeral storage | `5Gi` | `20Gi` | The pod also includes initialization and sidecar containers for network setup, file transfer, snapshots, and restore. To change the main container resources, merge these `configMap` entries into your deployment values or Craft overlay: ```yaml theme={null} configMap: SANDBOX_POD_CPU_REQUEST: "1000m" SANDBOX_POD_CPU_LIMIT: "2000m" SANDBOX_POD_MEMORY_REQUEST: "2Gi" SANDBOX_POD_MEMORY_LIMIT: "10Gi" SANDBOX_POD_EPHEMERAL_STORAGE_REQUEST: "5Gi" SANDBOX_POD_EPHEMERAL_STORAGE_LIMIT: "20Gi" ``` Use `sandboxPod.nodeSelector`, `sandboxPod.tolerations`, and `sandboxPod.affinity` to control placement. The proxy and Scheduled Task worker have separate resource settings under `sandboxProxy.resources` and `celery_worker_scheduled_tasks.resources`. ## Verify the deployment Confirm the proxy, sandbox template, and Scheduled Task worker exist: ```bash theme={null} kubectl -n onyx get deployment -l app.kubernetes.io/component=sandbox-proxy kubectl -n onyx-sandboxes get podtemplate sandbox-pod kubectl -n onyx get deployment -l app=celery-worker-scheduled-tasks ``` After configuring a model and user access, send a prompt in Craft. A sandbox pod should appear: ```bash theme={null} kubectl -n onyx-sandboxes get pods -l app.kubernetes.io/component=sandbox ``` ## Network configuration Sandbox pods can send traffic only to DNS and the sandbox proxy. The proxy handles external requests, App policies, and credential injection. Most clusters work with the chart defaults. Two cluster layouts require additional values: | Cluster layout | Configuration | | --------------------------------------------- | ---------------------------------------------- | | NodeLocal DNS or another non-pod DNS listener | Add its CIDR to `craft.dnsExtraCIDRs`. | | An external or unlabeled sandbox proxy | Add the proxy CIDR to `craft.proxyExtraCIDRs`. | | Dual-stack networking | Set `sandboxProxy.egressAllowIPv6: true`. | Keep the sandbox egress NetworkPolicies enabled. They restrict sandbox pods to the proxy and DNS, and block link-local cloud metadata access from the proxy path. ## Troubleshooting Read the render error first. Confirm Kubernetes 1.33 or later, `SANDBOX_BACKEND: "kubernetes"`, a non-empty `SANDBOX_API_SERVER_URL`, and `auth.sandboxPushSecret.enabled: true` with a populated Secret. Run `kubectl -n onyx-sandboxes describe pod `. Confirm at least one node matches `sandboxPod.nodeSelector`, accepts the configured taints and tolerations, and has enough CPU, memory, and ephemeral storage. Inspect the `sandbox-init` container logs and the proxy pods. DNS must resolve the proxy before the sandbox firewall is installed. Clusters using NodeLocal DNS usually need its listener CIDR under `craft.dnsExtraCIDRs`. Verify `SANDBOX_API_SERVER_URL`, DNS, TLS trust, and routing from the proxy. Do not point it at a Service name from another cluster or an address the proxy cannot resolve. Run `kubectl -n onyx logs -l app.kubernetes.io/component=sandbox-proxy --tail=200` and check its access to PostgreSQL, Redis, the Onyx API, and external destinations. On dual-stack clusters, enable `sandboxProxy.egressAllowIPv6`. Compare the Kubernetes and Docker Compose paths. Configure models and user access after deployment. # Desktop App Source: https://docs.onyx.app/deployment/local/desktop_app Install and configure the Onyx desktop application The Onyx Desktop App provides users with a native application experience for accessing Onyx on Windows, macOS, and Linux. Features include: * Quick-launch from system tray or dock * Desktop notifications Onyx Desktop App The desktop app is used for connecting to an Onyx server backend. Users will need access to the Onyx instance URL. It cannot connect directly to a local inference backend. ## Download Download the latest Onyx Desktop App for your platform: Download for Windows (.exe) Download for macOS (.dmg) Download for Linux (.deb) Additional architectures and formats (.msi, .rpm, .app.tar.gz) are available on the [GitHub Releases page](https://github.com/onyx-dot-app/onyx/releases/latest). ## First Launch **Self-hosted users**: On first launch, the app opens a **Settings** screen to configure the connection to your Onyx instance: * **Server URL**: Your Onyx instance URL (e.g., `https://onyx.yourcompany.com`) * **Authentication**: Sign in with your configured authentication method The Server URL can be changed at any time from the **Settings** screen (`⌘ ,` on macOS, `Ctrl ,` on Windows and Linux). ## Enterprise Deployment For organizations rolling out the desktop app at scale, you can pre-configure the Server URL (and other options) so users skip the first-launch **Settings** prompt entirely. Place a `config.json` file on each machine before the user first opens the app. On launch, Onyx reads the file and connects to your instance directly; users only need to sign in. ### Configuration File Location The app reads its settings from a `config.json` file at the following location: ``` %APPDATA%\onyx\onyx-desktop\config\config.json ``` ``` ~/Library/Application Support/app.onyx.onyx-desktop/config.json ``` ``` ~/.config/onyx-desktop/config.json # or, if $XDG_CONFIG_HOME is set: $XDG_CONFIG_HOME/onyx-desktop/config.json ``` Example `config.json`: ```json theme={null} { "server_url": "https://onyx.yourcompany.com", "window_title": "Onyx" } ``` ## Configuration Options | Option | Values | Platforms | Description | | ------------------------- | ------------------------------------------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `server_url` | string
(default: `"https://cloud.onyx.app"`) | Windows, macOS, Linux | The Onyx instance the app connects to. Required for the app to skip the first-launch **Settings** prompt. A trailing slash is ignored. | | `window_title` | string
(default: `"Onyx"`) | Windows, macOS, Linux | Custom title shown in the application window. | | `show_menu_bar` | boolean
(default: `true`) | Windows, Linux | Whether the application menu bar is shown. Normally toggled from **Window → Show Menu Bar** rather than pre-configured. Ignored on macOS, where the menu bar is managed by the operating system. | | `hide_window_decorations` | boolean
(default: `false`) | Linux | Hides the window's title bar and borders. Normally toggled from **Window → Hide Window Decorations**. | `config.json` must be valid JSON with values of the correct type. A single invalid entry causes the app to discard the **entire** file and fall back to the default settings. # Docker Source: https://docs.onyx.app/deployment/local/docker Deploy Onyx with Docker Compose Check out the [Resourcing Guide](/deployment/getting_started/resourcing) before getting started with Docker. This guide covers managing the compose files manually. For a guided install with managed upgrades, use the [Onyx CLI](/deployment/local/onyx_cli) instead — it can also [adopt an existing manual setup](/deployment/local/onyx_cli#from-a-manual-docker-compose-setup) later. ## Guide **Note:** On Windows, the commands will be slightly different but all the steps are the same. * [Git](https://git-scm.com/downloads) * [Docker (with compose)](https://docs.docker.com/get-docker/) ```bash theme={null} git clone --depth 1 https://github.com/onyx-dot-app/onyx.git ``` ```bash theme={null} cd onyx/deployment/docker_compose ``` To pull images from Docker Hub and start Onyx: ```bash theme={null} docker compose up -d ``` Alternatively, to build images from source: ```bash theme={null} docker compose up -d --build --force-recreate ``` If you've previously launched Onyx with the old `onyx-stack` service name, you'll need to add `-p onyx-stack` to your launch command. For example: `docker compose up -p onyx-stack -d`. After the containers come up, the system needs to go through an initialization process after which you can access Onyx at [localhost:3000](localhost:3000). ## Enabling Onyx Craft Craft adds isolated sandbox containers and an egress proxy to the Docker Compose deployment. Use the dedicated guide for both new and existing installations. Install the Craft overlay, configure the sandbox API URL, plan host capacity, and verify the runtime. ## Next Steps Set up authentication for your Onyx deployment with OAuth, OIDC, or SAML. Learn about all available configuration options for your Onyx deployment. # Kubernetes Source: https://docs.onyx.app/deployment/local/kubernetes Deploy Onyx with Helm Check out our [Resourcing Guide](/deployment/getting_started/resourcing) before getting started. ## Guide The Onyx Helm chart packages all the required services (API, web, PostgreSQL, Vespa, etc.) into a single deployment. By default, persistent volumes will be created for stateful services (e.g. PostgreSQL, Vespa). ```bash theme={null} helm repo add onyx https://onyx-dot-app.github.io/onyx/ helm repo update helm search repo onyx ``` Install into its own namespace (recommended): ```bash theme={null} kubectl create namespace onyx helm install onyx onyx/onyx -n onyx ``` This will pull the latest Onyx chart and deploy all dependencies. ```bash theme={null} helm list -n onyx kubectl get pods -n onyx ``` Wait until all pods are in a `Running` state before accessing Onyx. By default, the chart exposes Onyx via a Kubernetes Service. For local testing, you can port-forward: ```bash theme={null} kubectl -n onyx port-forward service/onyx-nginx 8080:80 ``` Then open [http://localhost:8080](http://localhost:8080). Configure your deployment by modifying the `values.yaml` file in the `onyx/deployment/helm/charts/onyx` directory. You'll need to restart Onyx after changing any `values.yaml` variables. ```bash theme={null} helm upgrade onyx onyx/onyx -n onyx -f deployment/helm/charts/onyx/values.yaml ``` See the [Helm chart README](https://github.com/onyx-dot-app/onyx/tree/main/deployment/helm) for advanced options such as running as non-root and testing with Kind. ## Enabling Onyx Craft Craft adds per-user sandbox pods, scoped RBAC, NetworkPolicies, an egress proxy, and a Scheduled Task worker to the Helm deployment. Prepare sandbox nodes and authentication, configure Helm, plan capacity, and verify the runtime. ## Next Steps Set up authentication for your Onyx deployment with OAuth, OIDC, or SAML. Learn about all available configuration options for your Onyx deployment. # Onyx CLI Source: https://docs.onyx.app/deployment/local/onyx_cli Install and manage a Docker Compose deployment with onyx-cli deploy The [Onyx CLI](/overview/onyx_anywhere/cli) includes a `deploy` command group that installs and manages a self-hosted Docker Compose deployment: a guided installer plus lifecycle commands for upgrading, inspecting, stopping, and removing the deployment. It is the recommended way to set up and manage a self-hosted deployment on Linux, macOS, and Windows. The `install.sh` / `install.ps1` [installation scripts](/deployment/getting_started/quickstart) are thin wrappers that install the CLI and run `onyx-cli deploy install`, so both paths produce the same deployment. Deployments created by older versions of the scripts are detected and [managed in place](#migrating-an-existing-deployment). Compared to managing the [Docker Compose files](/deployment/local/docker) by hand, the CLI: * **Keeps the compose files in sync automatically**: `deploy upgrade` refreshes the compose files, overlays, and nginx config to match the target version, so you never diff them against the repo yourself. * **Protects your customizations**: hand-edited files are detected via a checksum manifest and backed up before they are ever overwritten, and your `.env` settings survive every upgrade. * **Steers debugging**: `deploy status` flags version drift and explains *why* a service is down (restarts, exit code, OOM, last failing health probe), and `deploy logs` finds the right compose files and overlays for you. * **Handles the environment**: it checks RAM, disk, and ports, installs Docker on Linux, and generates secrets, instead of leaving prerequisites to a README. * **Has a convenient, discoverable interface**: guided prompts with sensible defaults, `--help` on every command, and clear error messages, with `--no-prompt` and `--json` for automation. | Command | Description | | --------------------------- | ------------------------------------------------------------- | | `onyx-cli deploy install` | Install a new deployment, or restart / update an existing one | | `onyx-cli deploy upgrade` | Upgrade an existing deployment to a newer version | | `onyx-cli deploy status` | Show versions, containers, and health | | `onyx-cli deploy stop` | Stop the containers without removing any data | | `onyx-cli deploy logs` | Show service logs | | `onyx-cli deploy uninstall` | Permanently delete the deployment and all its data | ## Prerequisites Install the CLI from PyPI: ```shell theme={null} uv tool install onyx-cli ``` Or with pip: ```shell theme={null} pip install onyx-cli ``` See the [CLI overview](/overview/onyx_anywhere/cli) for other installation methods. No `onyx-cli configure` step is needed — the `deploy` commands work directly against your local Docker, not an Onyx server. Check out the [Resourcing Guide](/deployment/getting_started/resourcing) before getting started. ## Install ```shell theme={null} onyx-cli deploy install ``` The interactive installer asks two questions — the deployment mode (**Lite** or **Standard**) and the version to deploy, prefilled with the latest release — while environment checks run in the background. It then: * Checks system resources (RAM, disk) and scans for a free host port * Installs Docker Engine and the compose plugin on Linux after confirmation; starts Docker Desktop and waits for it on macOS; detects Docker and provides instructions on Windows * Creates a `.env` file from the template with randomly generated secrets * Pulls the Onyx images and starts the containers, waiting until every service reports healthy Re-running `deploy install` on an existing deployment asks a single question: **Restart** it as-is or **Upgrade** it to a newer version. ### Flags | Flag | Description | | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | | `--lite` | Deploy Onyx Lite (no OpenSearch, Redis, or model servers) | | `--include-craft` | Enable [Onyx Craft](/deployment/local/craft_docker_compose) — Craft is opt-in via this flag only and is not offered by the interactive prompt | | `--tag ` | Image tag to deploy (default: the latest Onyx release) | | `--dir ` | Deployment directory (default: `~/.config/onyx`, or an existing `./onyx_data`) | | `--no-prompt` | Run non-interactively with defaults applied to every prompt (for CI/automation) | | `--local` | Use existing config files on disk instead of downloading | | `--offline` | Deploy from images already on the host without any network access (implies `--local`) | | `--no-wait` | Return as soon as containers are started instead of waiting for health | | `--dry-run` | Show what would be done without making changes | | `--force` | Overwrite hand-edited managed files (a backup is kept) and recreate running services | | `--verbose` | Show detailed output for debugging | For example, a fully non-interactive install pinned to a specific version: ```shell theme={null} onyx-cli deploy install --tag v4.4.6 --no-prompt ``` ### Deployment directory New installs live in `~/.config/onyx` (XDG-aware). Deployments created by older versions of the `install.sh` script in `./onyx_data` are detected automatically and managed **in place** — no migration needed. Pass `--dir` or set the `ONYX_DEPLOYMENT_DIR` environment variable to target a specific location. The directory holds the compose files, `.env`, and an `install-state.json` manifest recording the deployment mode, version, and a checksum of each managed file. No application data lives there — chats, users, and documents are stored in named Docker volumes. ### Offline install `--offline` deploys entirely from what is already on the host — no release lookup, no config download, and no image pull. The images must be loaded in advance, and Docker must already be installed (the installer cannot install it without a network). It implies `--local`: config files already on disk are used as-is, and any that are missing are written from copies bundled with the CLI. Staging the deployment directory from a connected install (below) is still recommended — the bundled copies match the CLI's own version, not necessarily the Onyx version being deployed. On a machine with internet access, install the latest release with the same mode flags (or pin a specific version with `--tag`), then export the images the deployment resolved to: ```bash theme={null} onyx-cli deploy install cd ~/.config/onyx/deployment docker save -o onyx-images.tar $(docker compose config --images) ``` Copy `onyx-images.tar` and the `~/.config/onyx` directory to the offline host, then: ```bash theme={null} docker load -i onyx-images.tar onyx-cli deploy install --offline ``` Without `--tag`, an offline install offers the newest released version whose images are already on the host — the one just loaded. Before starting anything, the installer verifies every image the deployment needs and names each one that is missing — load those with `docker load` and re-run. `deploy upgrade --offline` works the same way for moving an air-gapped deployment to a newer staged version. ## Upgrade ```shell theme={null} onyx-cli deploy upgrade ``` Upgrades an existing deployment to the latest release, or to a specific version with `--tag`: ```shell theme={null} onyx-cli deploy upgrade --tag v4.4.6 ``` The upgrade is designed to preserve your customizations: * Only the `IMAGE_TAG` line in `.env` is rewritten (plus `SANDBOX_BACKEND` when Craft is enabled) — every other setting, including your edits, is kept. * Managed files (compose files, overlays, nginx config) are refreshed to match the target version. Files you hand-edited are detected via the manifest, backed up, and only overwritten after you confirm (or with `--force`). * Downgrades to an older version warn and require confirmation or `--force`. The running services keep serving while the new images download and are then recreated on the new version. `upgrade` accepts the same `--dir`, `--no-prompt`, `--local`, `--offline`, `--no-wait`, `--dry-run`, and `--verbose` flags as `install`. ## Status ```shell theme={null} onyx-cli deploy status ``` Shows the installed version as recorded by the CLI, by `.env`, and by the running containers (drift between them is flagged), plus per-container status and health, the published port, and — for a service that is down — why (restarts, exit code, OOM, last failing health probe). `status` is read-only and works as a health probe: use `--json` for machine-readable output, and check the exit code. | Exit code | Meaning | | --------- | ---------------------------- | | `0` | Everything is up and healthy | | `1` | Stopped or degraded | | `9` | No installation found | ## Logs ```shell theme={null} onyx-cli deploy logs api_server ``` Shows service logs without needing to locate the deployment directory or remember which compose overlays it uses. Name one or more services to narrow the output, or pass none for all services. | Flag | Description | | ---------------- | ---------------------------------------------------------------------------- | | `-f`, `--follow` | Keep printing new log lines | | `--tail ` | Lines to show from the end of each log (default `200`, `all` for everything) | | `--since