> For the complete documentation index, see [llms.txt](https://docs.uptiq.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.uptiq.ai/console/agent-builder/deploy/agent-integration.md).

# Integrate Agent

Embed, call, or drive your agent from your own applications.

If you want people to use this agent outside the platform — in your own app, product, or website — set it up here. Pick **Agent API** to call it from your backend, or **Embedded Chat** to drop a ready-made chat widget into your site. Find it under **Manage Agent → Integrate Agent**, under *Credentials & access*; it opens as a side panel with two tabs, **Embedded Chat** and **Agent API**.

{% hint style="info" %}
**Versions are per agent.** Read the SDK version and Executor version from your own agent's **Agent Config Panel**, and use those in your app and API calls. The values shown in the samples on this page are placeholders.
{% endhint %}

{% hint style="warning" %}
**`<BASE_URL>` in every sample on this page** is a placeholder for the Qore API host your organization uses. Confirm your production host with your Uptiq contact or your platform administrator before you ship — it differs by deployment, and a sample host will not work against your environment. (The panel's own "Download as MD" export shows a real host for your environment — copy the sample from there once you've confirmed it's the right one for where you're shipping.)
{% endhint %}

## Choosing an integration

Start by matching the tab to where your agent runs and how much of the interface you want to own.

| If you want to…                                          | Use                                      | Runtime                       |
| -------------------------------------------------------- | ---------------------------------------- | ----------------------------- |
| Drop a chat onto a web page with no UI to build          | **Embedded Chat**                        | Browser (prebuilt UI)         |
| Call the agent from a backend, service, or scheduled job | **Agent API** — Client: `raw (HTTP)`     | Server-to-server (no browser) |
| Build your own custom chat UI in the browser             | **Agent API** — Client: `TypeScript SDK` | Browser (your UI)             |

**Shared prerequisites.** Both tabs connect using credentials and domain rules configured on the agent:

| Requirement            | Where                                | Applies to                                                                              |
| ---------------------- | ------------------------------------ | --------------------------------------------------------------------------------------- |
| **Widget Key**         | Manage Agent → **Access & Security** | Embedded Chat, TypeScript SDK client (and optionally the API)                           |
| **API Key + Secret**   | Manage Agent → **Access & Security** | Agent API, raw HTTP client (server-to-server)                                           |
| **Whitelisted domain** | Manage Agent → **Access & Security** | Embedded Chat, TypeScript SDK client — add the full URL or hostname, no trailing spaces |

To obtain a **Widget Key**: open your agent's **Access & Security** page, then generate and copy the key — the same **Widget key** step the Embedded Chat wizard walks you through below. To **whitelist a domain**: on the same page, add and save your domain under **Allowed Domains**.

Set up **Access & Security** first — the screen now combines what were separate [Authentication](/console/agent-builder/deploy/authentication.md) and [Whitelisted Domains](/console/agent-builder/deploy/whitelisted-domains.md) pages; both still document the Access Keys and Allowed Domains sections respectively.

{% hint style="warning" %}
Wherever you supply a `user` object, it must represent a **trusted, authenticated identity** from your own auth system — the user currently logged into your application and verified by your auth system. Never populate it from query parameters or untrusted input, which can be manipulated.
{% endhint %}

## Embedded Chat

Embedded Chat is the quickest path — a prebuilt chat UI you drop onto a page, with no interface to build yourself. The panel walks you through it as three steps.

### Step 1 — Widget key

Choose **Use existing key** to reuse a key already issued for this agent, or **Generate new key**. A public key lets the widget talk to this agent from the browser — safe to ship in client code. Select **Generate key**, then **Continue**.

### Step 2 — Whitelist domains

Only these origins may load the widget; requests from anywhere else are rejected. Add each domain your widget will run on (for example `app.yourdomain.com`), then **Continue**.

### Step 3 — Install widget

Install the React SDK and mount the widget in your app:

```bash
npm install @uptiqai/widgets-sdk@1.295.0
```

```tsx
import { ChatWidget } from '@uptiqai/widgets-sdk';
import '@uptiqai/widgets-sdk/dist/style.css';

export default function App() {
  return (
    <ChatWidget
      config={{
        serverUrl: '<BASE_URL>',
        agentId: '<agent-id>',
        widgetKey: '<your-widget-key>',
        agentExecutorVersion: '1.4',
      }}
      user={{ uid: 'user_123', firstName: 'John', email: 'john@example.com' }}
    />
  );
}
```

{% hint style="info" %}
**The widget SDK version above is the one released alongside this agent's executor version** — pinning it keeps the widget and the executor in step. Upgrade the agent's executor version first if you need a newer widget.
{% endhint %}

That's enough to get a working chat widget live. The rest of this section is reference material for going further: the framework-agnostic HTML web component, the Full Screen layout, theming, and the headless JS SDK for a fully custom UI.

### Reference: widget variants

The **Embed Agent** widget is a drop-in chat interface backed by `@uptiqai/widgets-sdk`. Beyond the React `ChatWidget` shown above, it also comes as a framework-agnostic **HTML web component**, and each offers a compact **Chat Widget** (floating popover) or an immersive **Full Screen** layout with sidebar navigation. The widget handles conversation state, history, and messaging for you.

**Install**

```bash
npm install @uptiqai/widgets-sdk@1.295.0
# or
pnpm add @uptiqai/widgets-sdk@1.295.0
```

Import the stylesheet once in your application entry point:

```js
import '@uptiqai/widgets-sdk/dist/style.css';
```

**Chat Widget vs. Full Screen** — both share the same `config`, `user`, `theme`, `instanceId`, and ref API. Full Screen adds a `hideTrigger` / `hide-trigger` option to hide the default launcher and open via your own button. Expand the variant you need:

<details>

<summary>React — Chat Widget (popover)</summary>

```tsx
import { ChatWidget } from '@uptiqai/widgets-sdk';
import type { ChatWidgetRef } from '@uptiqai/widgets-sdk';
import '@uptiqai/widgets-sdk/dist/style.css';
import { useRef } from 'react';

function App() {
  const currentUser = useAuth(); // your auth hook
  return (
    <ChatWidget
      config={{
        serverUrl: '<BASE_URL>',
        agentId: '<agent-id>',
        widgetKey: '<your-widget-key>',
        agentExecutorVersion: '1.4',
      }}
      user={{
        uid: currentUser.id,
        firstName: currentUser.firstName,
        lastName: currentUser.lastName,
        email: currentUser.email,
      }}
    />
  );
}
```

</details>

<details>

<summary>React — Full Screen</summary>

Use `FullScreenChatWidget` / `FullScreenChatWidgetRef`. Add `hideTrigger` when driving visibility from your own button:

```tsx
import { FullScreenChatWidget } from '@uptiqai/widgets-sdk';
import type { FullScreenChatWidgetRef } from '@uptiqai/widgets-sdk';
import '@uptiqai/widgets-sdk/dist/style.css';
import { useRef } from 'react';

function App() {
  const widgetRef = useRef<FullScreenChatWidgetRef>(null);
  const currentUser = useAuth();
  return (
    <FullScreenChatWidget
      config={{
        serverUrl: '<BASE_URL>',
        agentId: '<agent-id>',
        widgetKey: '<your-widget-key>',
        agentExecutorVersion: '1.4',
      }}
      user={{
        uid: currentUser.id,
        firstName: currentUser.firstName,
        lastName: currentUser.lastName,
        email: currentUser.email,
      }}
      hideTrigger={true}
      widgetRef={widgetRef}
    />
  );
}
```

</details>

<details>

<summary>HTML — Chat Widget (popover)</summary>

Add the widget script to your page `<head>`, then use the custom element:

```html
<uptiq-chat-widget
  id="chat-widget"
  config='{
    "serverUrl": "<BASE_URL>",
    "agentId": "<agent-id>",
    "widgetKey": "<your-widget-key>",
    "agentExecutorVersion": "1.4"
  }'
  user='{
    "uid": "auth0|<user-id>",
    "firstName": "Jane",
    "lastName": "Smith",
    "email": "jane.smith@company.com"
  }'
></uptiq-chat-widget>
```

</details>

<details>

<summary>HTML — Full Screen</summary>

Use `<uptiq-full-screen-chat-widget>` and add `hide-trigger="true"` to hide the default launcher:

```html
<uptiq-full-screen-chat-widget
  id="chat-widget"
  hide-trigger="true"
  config='{
    "serverUrl": "<BASE_URL>",
    "agentId": "<agent-id>",
    "widgetKey": "<your-widget-key>",
    "agentExecutorVersion": "1.4"
  }'
  user='{
    "uid": "auth0|<user-id>",
    "firstName": "Jane",
    "lastName": "Smith",
    "email": "jane.smith@company.com"
  }'
></uptiq-full-screen-chat-widget>
```

</details>

### Props / attributes reference

React uses **props** (objects); the HTML web component uses **attributes** (JSON-stringified objects, kebab-case names). Otherwise they map 1:1.

| React prop           | HTML attribute         | Required | Type                     | Description                                                                                 |
| -------------------- | ---------------------- | -------- | ------------------------ | ------------------------------------------------------------------------------------------- |
| `config`             | `config`               | Yes      | `WidgetConfig`           | Backend/agent config — see below.                                                           |
| `user`               | `user`                 | Yes      | `WidgetUser`             | Authenticated user — see below.                                                             |
| `instanceId`         | `instance-id`          | No       | string                   | Unique ID when rendering multiple widgets on one page. Default: auto-generated.             |
| `theme`              | `theme`                | No       | `WidgetTheme`            | Palette overrides — see **Theme customization**.                                            |
| `defaultExecutionId` | `default-execution-id` | No       | string                   | Start with a specific conversation/execution loaded (continue a previous chat).             |
| `onExecutionChange`  | —                      | No       | `(executionId?) => void` | Fires when the current conversation changes.                                                |
| `defaultOpen`        | `default-open`         | No       | boolean                  | Open on mount. Default `false`.                                                             |
| `hideTrigger`        | `hide-trigger`         | No       | boolean                  | *(Full Screen)* Hide the default launcher; open via your own button + ref. Default `false`. |
| `onClose`            | —                      | No       | `() => void`             | Fires when the user closes the widget.                                                      |
| `widgetRef`          | —                      | No       | `React.Ref<…Ref>`        | Programmatic `open()` / `close()` control.                                                  |

**`config` (required)** — `WidgetConfig`:

```ts
{
  serverUrl: '<BASE_URL>',    // your Qore API host - see the note at the top of this page
  agentId: '<agent-id>',      // the agent's ID, from its Agent Config Panel
  widgetKey: string,          // from Access & Security
  agentExecutorVersion?: string, // Executor version from agent config (optional)
}
```

**`user` (required)** — `WidgetUser`:

```ts
{
  uid: string;        // Unique identifier for the user in your system
  firstName: string;  // User's first name
  lastName?: string;  // User's last name (optional)
  email: string;      // User's email address
}
```

{% hint style="warning" %}
**Security:** populate `user` from your authenticated session — e.g. `const currentUser = useAuth();` — never from query params, form input, or other untrusted sources.
{% endhint %}

<details>

<summary>widgetRef — programmatic open/close control</summary>

```ts
// React.Ref<ChatWidgetRef> | React.Ref<FullScreenChatWidgetRef>
{
  open: () => void;   // Opens the widget
  close: () => void;  // Closes the widget
}
```

```tsx
const widgetRef = useRef<FullScreenChatWidgetRef>(null);

const handleOpenChat = () => widgetRef.current?.open();
const handleCloseChat = () => widgetRef.current?.close();
```

</details>

### Theme customization

Pass a `theme` (React object / HTML JSON string) to match your design system:

```tsx
theme={{
  palette: {
    primary: '#3b82f6',
    primaryForeground: '#ffffff',
    background: '#ffffff',
    foreground: '#0f172a',
    border: '#e2e8f0',
    success: '#10b981',
    destructive: '#ef4444',
  },
}}
```

<details>

<summary>Full palette reference (WidgetTheme)</summary>

```ts
{
  palette?: {
    // Primary shades
    primary00?; primary100?; primary200?; primary300?; primary400?; primary500?;
    // Secondary shades
    secondary300?; secondary500?; secondary700?;
    // Background shades (00 lightest → 900 darkest)
    background00?; background100?; background200?; background300?; background800?; background900?;
    // Foreground / text
    foreground00?; foreground200?; foreground600?; foreground800?; foreground900?;
    // Borders
    border100?; border200?; border300?; border400?;
    // Semantic
    primary?; primaryForeground?;
    secondary?; secondaryForeground?;
    background?; foreground?;
    border?; input?;
    success?; successForeground?;
    warning?; warningForeground?;
    destructive?; destructiveForeground?;
    sidebar?; sidebarForeground?;
    ring?;
    // all values are string (optional)
  }
}
```

</details>

### Examples

<details>

<summary>Example 1 — Basic implementation</summary>

```tsx
import { FullScreenChatWidget } from '@uptiqai/widgets-sdk';
import '@uptiqai/widgets-sdk/dist/style.css';

function App() {
  const currentUser = useAuth();
  return (
    <div>
      <h1>My Application</h1>
      <FullScreenChatWidget
        config={{ serverUrl: '<BASE_URL>', agentId: '<agent-id>', widgetKey: '<your-widget-key>', agentExecutorVersion: '1.4' }}
        user={{ uid: currentUser.id, firstName: currentUser.firstName, lastName: currentUser.lastName, email: currentUser.email }}
      />
    </div>
  );
}
```

</details>

<details>

<summary>Example 2 — Custom trigger with ref control</summary>

```tsx
import { FullScreenChatWidget } from '@uptiqai/widgets-sdk';
import type { FullScreenChatWidgetRef } from '@uptiqai/widgets-sdk';
import '@uptiqai/widgets-sdk/dist/style.css';
import { useRef } from 'react';

function App() {
  const widgetRef = useRef<FullScreenChatWidgetRef>(null);
  const currentUser = useAuth();
  return (
    <div>
      <button onClick={() => widgetRef.current?.open()}>💬 Chat with AI Assistant</button>
      <FullScreenChatWidget
        config={{ serverUrl: '<BASE_URL>', agentId: '<agent-id>', widgetKey: '<your-widget-key>', agentExecutorVersion: '1.4' }}
        user={{ uid: currentUser.id, firstName: currentUser.firstName, lastName: currentUser.lastName, email: currentUser.email }}
        hideTrigger={true}
        widgetRef={widgetRef}
      />
    </div>
  );
}
```

For the **popover** `ChatWidget`, the same pattern applies with both open and close buttons (`widgetRef.current?.open()` / `.close()`).

</details>

<details>

<summary>Example 3 — Theme customization</summary>

```tsx
const customTheme = {
  palette: {
    primary: '#6366f1', primaryForeground: '#ffffff',
    background: '#f8fafc', foreground: '#1e293b', border: '#cbd5e1',
    sidebar: '#ffffff', sidebarForeground: '#475569',
    success: '#22c55e', warning: '#f59e0b', destructive: '#ef4444',
  },
};

<FullScreenChatWidget config={/* … */} user={/* … */} theme={customTheme} />
```

</details>

<details>

<summary>Example 4 — Tracking conversations</summary>

```tsx
import { useState } from 'react';

function App() {
  const currentUser = useAuth();
  const [currentExecutionId, setCurrentExecutionId] = useState<string>();

  const handleExecutionChange = (executionId?: string) => {
    setCurrentExecutionId(executionId);
    if (executionId) localStorage.setItem('lastExecutionId', executionId);
    analytics.track('conversation_changed', { executionId });
  };

  const lastExecutionId = localStorage.getItem('lastExecutionId') || undefined;

  return (
    <FullScreenChatWidget
      config={{ serverUrl: '<BASE_URL>', agentId: '<agent-id>', widgetKey: '<your-widget-key>', agentExecutorVersion: '1.4' }}
      user={{ uid: currentUser.id, firstName: currentUser.firstName, lastName: currentUser.lastName, email: currentUser.email }}
      defaultExecutionId={lastExecutionId}
      onExecutionChange={handleExecutionChange}
      onClose={() => console.log('Widget closed with execution:', currentExecutionId)}
    />
  );
}
```

</details>

<details>

<summary>Example 5 — Multiple widgets on the same page</summary>

Give each widget a distinct `instanceId` (React) / `instance-id` (HTML):

```tsx
<FullScreenChatWidget instanceId="sales-agent" config={{ /* sales agentId + widgetKey */ }} user={/* … */} />
<FullScreenChatWidget instanceId="support-agent" config={{ /* support agentId + widgetKey */ }} user={/* … */} />
```

</details>

### Features

* Chat interface (floating popover or full-screen) with responsive design
* Conversation sidebar for managing multiple chats
* New chat creation for starting fresh conversations
* Message history persistence across sessions
* Real-time messaging with the AI agent
* Agent avatar display in the trigger button
* Customizable theming to match your brand
* TypeScript support with full type definitions

### Browser support

All modern browsers: Chrome/Edge (latest), Firefox (latest), Safari (latest), and mobile browsers (iOS Safari, Chrome Mobile).

### Troubleshooting

* **Widget not appearing** — ensure you imported the CSS (`import '@uptiqai/widgets-sdk/dist/style.css';`), that both required props (`config` and `user`) are provided, and that your Widget Key is correct and active.
* **"Unauthorized" errors** — confirm your application's domain is whitelisted exactly (full URL with protocol or hostname only, no trailing spaces).

## Agent API

When you'd rather drive the agent from your own code than a prebuilt UI, use the **Agent API** tab. It generates one code sample from three selectors:

| Selector    | Options                                      | Notes                                                                                                                                                                                                                                   |
| ----------- | -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Client**  | `raw (HTTP)`, `TypeScript SDK`, `Python SDK` | Python SDK is **Coming soon**.                                                                                                                                                                                                          |
| **Mode**    | `Sync`, `Async`, `Realtime`                  | This page documents Sync and Async in full. **Realtime** appears as a selector on screen; its request/response shape isn't documented yet — check back or ask your Uptiq contact before building against it.                            |
| **Dialect** | `Native`, `OpenAI`                           | **Native** is Qore's own request/response shape, documented below. **OpenAI** exposes an OpenAI-compatible surface (chat completions-style requests); it isn't documented on this page yet — the selector is live, the reference isn't. |

The credentials panel above the generated sample reads: *"Every request needs both the API key below (sent as the `x-api-key` header, always visible here) and its matching API secret (sent as `x-api-key-secret`, shown only once when generated). Keep both server-side — never expose them in the browser."* Generate the key pair from the panel, or from **Access & Security**.

The rest of this section documents the **Native** dialect for the **raw (HTTP)** client — Sync and Async modes — plus the **TypeScript SDK** client. Both run server-to-server or in the browser respectively; pick based on where your integration runs:

### Native dialect, raw HTTP client

The **Headless Agent Trigger API** invokes an agent over HTTP — no UI or browser. Use it for backend services, scheduled jobs, or any workflow that starts the agent from your own systems.

* **Base URL:** `<BASE_URL>` · **Format:** JSON

#### Authentication

Every request must include exactly one of the following header sets.

<details>

<summary>Option 1 — API Key + Secret (server-to-server)</summary>

Best for backend and service-to-service integrations.

```http
x-api-key: YOUR_AGENT_API_KEY
x-api-key-secret: YOUR_AGENT_API_KEY_SECRET
Content-Type: application/json
```

Create and copy both from **Access & Security**.

</details>

<details>

<summary>Option 2 — Widget Key</summary>

Best for first-party platform integrations.

```http
x-widget-key: YOUR_AGENT_WIDGET_KEY
Content-Type: application/json
```

Create and copy it from **Access & Security**.

</details>

#### Trigger an agent

```
POST /agent-executor/1.4/agents/:agentId/trigger
```

Starts a new agent execution or resumes a paused one.

**Path parameters**

| Name      | Type   | Required | Description                                |
| --------- | ------ | -------- | ------------------------------------------ |
| `agentId` | string | Yes      | The unique identifier of the agent to run. |

**Request body** — provide either `message` or `resumeData`; all other fields are optional.

| Field            | Type   | Description                                                                       |
| ---------------- | ------ | --------------------------------------------------------------------------------- |
| `message`        | string | The instruction sent to the agent. Required for new executions.                   |
| `payload`        | object | Structured data sent alongside `message` for programmatic inputs.                 |
| `documents`      | array  | File attachments. See **Document handling**.                                      |
| `executionId`    | string | Specific execution ID. Auto-generated if omitted.                                 |
| `executionMode`  | string | `async` (default) or `sync`. Use `sync` only when you need an immediate response. |
| `responseFormat` | string | `Markdown` (default) or `Json`.                                                   |
| `webhooks`       | array  | Webhook URLs to receive execution updates. See **Webhooks**.                      |

```bash
curl -X POST "<BASE_URL>/agent-executor/1.4/agents/:agentId/trigger" \
  -H "x-api-key: YOUR_AGENT_API_KEY" \
  -H "x-api-key-secret: YOUR_AGENT_API_KEY_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"message": "Summarize the latest sales report"}'
```

Success response: `{ "executionId": "exec_123" }`

That is an acknowledgement, not an answer — executions default to async. Poll the execution or receive a webhook to turn an `executionId` into a result.

#### Document handling

Attaching documents is a two-step process: upload the file, then reference it in the trigger request.

<details>

<summary>Step 1 — Get a signed upload URL</summary>

```
POST /agent-executor/1.4/agents/:agentId/uploads/signed-urls
```

```bash
curl -X POST "<BASE_URL>/agent-executor/1.4/agents/:agentId/uploads/signed-urls" \
  -H "x-widget-key: YOUR_AGENT_WIDGET_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "count": 1 }'
```

| Field         | Type   | Required | Description                                     |
| ------------- | ------ | -------- | ----------------------------------------------- |
| `count`       | number | No       | Number of signed URLs to generate. Default `1`. |
| `executionId` | string | No       | Execution ID to associate the upload with.      |

Response:

```json
{
  "message": "Signed URL generated successfully.",
  "data": [
    { "id": "document-id", "url": "https://storage.googleapis.com/.../uploads/...", "agentId": "agent-id" }
  ]
}
```

`PUT` your file to the returned `url`, then use the `id` when triggering the agent.

{% hint style="warning" %}
The previous endpoint `POST /agent-executor/1.4/agents/:agentId/documents/presigned-url` is **deprecated** and will be removed — migrate to `uploads/signed-urls`.
{% endhint %}

</details>

<details>

<summary>Step 2 — Attach the document to the trigger request</summary>

```bash
curl -X POST "<BASE_URL>/agent-executor/1.4/agents/:agentId/trigger" \
  -H "x-api-key: YOUR_AGENT_API_KEY" \
  -H "x-api-key-secret: YOUR_AGENT_API_KEY_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Analyze financial risk",
    "documents": [
      { "id": "<document-id>", "fileName": "balance-sheet.pdf", "mimeType": "application/pdf" }
    ]
  }'
```

| Field       | Type   | Description                                                  |
| ----------- | ------ | ------------------------------------------------------------ |
| `id`        | string | Document ID returned from the upload endpoint.               |
| `signedUrl` | string | Alternative to `id` — the signed URL of the uploaded file.   |
| `fileName`  | string | Original filename. Recommended for better agent context.     |
| `mimeType`  | string | MIME type of the file. Recommended for better agent context. |

</details>

#### Passing variables and a business ID

Two more fields on the trigger request, alongside `message` and `documents`:

| Field        | Type   | Description                                                                                                                                                                                   |
| ------------ | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `uid`        | string | The calling user's ID in your system — the same identity concept as the widget's `user.uid`.                                                                                                  |
| `variables`  | object | Key/value pairs the agent's instructions can reference. **Every key must already be declared** in the agent's **Agent Variables** section under Manage Agent — an undeclared key is rejected. |
| `businessId` | string | Attributes this run to a business or tenant of your own. Accepted on every trigger request.                                                                                                   |

```bash
curl -X POST "<BASE_URL>/agent-executor/1.4/agents/:agentId/trigger" \
  -H "x-api-key: YOUR_AGENT_API_KEY" \
  -H "x-api-key-secret: YOUR_AGENT_API_KEY_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Compare a 15-year and 30-year fixed mortgage.",
    "executionMode": "sync",
    "uid": "user_123",
    "variables": { "customerName": "John", "region": "US" },
    "businessId": "<businessId>"
  }'
```

#### Checking and managing a running execution

Once an execution is triggered, four more endpoints let you check on it or stop it — all under the same `:agentId` path used to trigger it.

<details>

<summary>Check where an execution sits in the queue</summary>

```
GET /agent-executor/1.4/agents/:agentId/executions/:executionId/queue-status
```

Messages sent to the same `executionId` are processed serially — one item shows `Executing`, the rest `Pending`.

```bash
curl "<BASE_URL>/agent-executor/1.4/agents/:agentId/executions/:executionId/queue-status" \
  -H "x-api-key: YOUR_AGENT_API_KEY" \
  -H "x-api-key-secret: YOUR_AGENT_API_KEY_SECRET"
```

Response: `{ "data": [{ "state": "Executing", "content": { "messageId": "<messageId>" } } ] }`

For a **sync** call, the reply instead blocks until done, with the result in `result.content`: `{ "executionId": "exec_123", "result": { "type": "done", "content": "..." } }`.

</details>

<details>

<summary>Cancel a message that is still Pending</summary>

```bash
curl -X DELETE "<BASE_URL>/agent-executor/1.4/agents/:agentId/executions/:executionId/queue/:messageId" \
  -H "x-api-key: YOUR_AGENT_API_KEY" \
  -H "x-api-key-secret: YOUR_AGENT_API_KEY_SECRET"
```

</details>

<details>

<summary>Abort a running execution</summary>

```
POST /agent-executor/1.4/agents/:agentId/executions/:executionId/abort
```

The agent stops and emits a terminal `done` event.

```bash
curl -X POST "<BASE_URL>/agent-executor/1.4/agents/:agentId/executions/:executionId/abort" \
  -H "x-api-key: YOUR_AGENT_API_KEY" \
  -H "x-api-key-secret: YOUR_AGENT_API_KEY_SECRET"
```

</details>

#### Listing and inspecting conversations

<details>

<summary>List this agent's conversations</summary>

```
GET /agent-executor/1.4/agents/:agentId/conversations
```

Returns titles and metadata only, not transcripts. Add `?initiatedBy=user_123` to filter to one user's conversations.

```bash
curl "<BASE_URL>/agent-executor/1.4/agents/:agentId/conversations" \
  -H "x-api-key: YOUR_AGENT_API_KEY" \
  -H "x-api-key-secret: YOUR_AGENT_API_KEY_SECRET"
```

</details>

<details>

<summary>Fetch a single conversation's transcript by executionId</summary>

```bash
curl "<BASE_URL>/agent-executor/1.4/agents/:agentId/conversation/:executionId" \
  -H "x-api-key: YOUR_AGENT_API_KEY" \
  -H "x-api-key-secret: YOUR_AGENT_API_KEY_SECRET"
```

</details>

#### Webhooks

{% hint style="info" %}
Webhooks are available on **Agent Executor Version 1.2 and onwards**.
{% endhint %}

Register webhooks in the trigger request to receive real-time updates when an execution completes or needs input:

```json
{
  "webhooks": [
    { "url": "https://your-service.com/webhook", "metadata": "optional-context-id" }
  ]
}
```

Your endpoint receives:

```json
{
  "executionId": "exec_123",
  "success": true,
  "result": { "message": "Agent response..." },
  "error": null,
  "metadata": "optional-context-id"
}
```

<details>

<summary>Verify the webhook signature</summary>

Each webhook includes an `X-Webhook-Signature` header — a hex-encoded RSA-SHA256 signature of the raw JSON body. Verify it against the platform's public key (available on the agent's Agent API screen):

```js
const crypto = require('crypto');

function verifyWebhook(rawBody, signatureHex, publicKey) {
  const signature = Buffer.from(signatureHex, 'hex');
  return crypto.verify('RSA-SHA256', Buffer.from(rawBody), publicKey, signature);
}
```

</details>

#### Common examples

<details>

<summary>Send structured data with a message</summary>

```bash
curl -X POST "<BASE_URL>/agent-executor/1.4/agents/:agentId/trigger" \
  -H "x-api-key: YOUR_AGENT_API_KEY" \
  -H "x-api-key-secret: YOUR_AGENT_API_KEY_SECRET" \
  -H "Content-Type: application/json" \
  -d '{ "message": "Generate quarterly report", "payload": { "quarter": "Q4", "year": 2024 } }'
```

</details>

<details>

<summary>Resume a paused execution</summary>

```bash
curl -X POST "<BASE_URL>/agent-executor/1.4/agents/:agentId/trigger" \
  -H "x-api-key: YOUR_AGENT_API_KEY" \
  -H "x-api-key-secret: YOUR_AGENT_API_KEY_SECRET" \
  -H "Content-Type: application/json" \
  -d '{ "executionId": "exec_123", "resumeData": { "lastStep": "analysis" } }'
```

</details>

<details>

<summary>Pin a specific reasoning model (advanced)</summary>

By default the platform picks the reasoning model. To override:

```json
{ "message": "Analyze this contract", "agentStrategy": { "reasoningModelId": "your-model-id" } }
```

</details>

#### Error responses

| Status | Meaning         | Example                                                          |
| ------ | --------------- | ---------------------------------------------------------------- |
| `400`  | Invalid request | `{ "error": "Message or resume data is required" }`              |
| `401`  | Bad credentials | `{ "error": "Invalid or missing agent API key" }`                |
| `403`  | Forbidden       | `{ "message": "You're not authorized to perform this action." }` |
| `500`  | Server error    | `{ "message": "Something went wrong. Please try again later." }` |

{% hint style="info" %}
Executions default to **async** — use `sync` only when you must block on the result. The trigger endpoint is **not idempotent**: each call starts a new execution unless you pass an existing `executionId`.
{% endhint %}

### TypeScript SDK client

Select **TypeScript SDK** as the Client to drive the agent from your own code instead of raw HTTP. The **Headless Agent JS SDK** lets you build a custom chat interface while it handles the socket connection, real-time agent events, and file uploads automatically. Runs in the browser (React, Vue, or vanilla JS). Entry point: `createHeadlessAgentInstance(params)`, which returns an instance with `emit()`, `on()`, and `cleanup()` methods.

**Install & import**

```bash
npm install @uptiqai/widgets-sdk@1.295.0
```

```ts
import { createHeadlessAgentInstance } from '@uptiqai/widgets-sdk';
// TypeScript projects also import the types:
import type { HeadlessAgentInstance, AgentInterruptEvent } from '@uptiqai/widgets-sdk';
```

Authentication uses the **Widget Key**; your application's domain must be whitelisted (see **Shared prerequisites** above).

#### Create an instance

```ts
const instance = createHeadlessAgentInstance({
  config: { serverUrl: '<BASE_URL>', agentId: '<agent-id>', widgetKey: '<your-widget-key>', agentExecutorVersion: '1.4' },
  user: { uid: 'user-123', firstName: 'Jane', lastName: 'User', email: 'jane@example.com' },
  instanceId: 'my-chat-instance',
});
```

| Parameter    | Type           | Required | Description                                                           |
| ------------ | -------------- | -------- | --------------------------------------------------------------------- |
| `config`     | `WidgetConfig` | Yes      | `serverUrl`, `agentId`, `widgetKey`, optional `agentExecutorVersion`. |
| `user`       | `WidgetUser`   | Yes      | `uid`, `firstName`, `email` (required); `lastName` (optional).        |
| `instanceId` | string         | Yes      | Unique identifier used for socket scoping.                            |

#### Instance API

| Method    | Signature                                           | Description                                                   |
| --------- | --------------------------------------------------- | ------------------------------------------------------------- |
| `emit`    | `(event: 'query', payload: QueryPayload) => void`   | Send a query to the agent, optionally with file attachments.  |
| `on`      | `(event: 'agent-interrupt', handler) => () => void` | Subscribe to agent events. Returns an unsubscribe function.   |
| `cleanup` | `() => void`                                        | Remove listeners and disconnect the socket (call on unmount). |

<details>

<summary>Sending messages — emit('query', payload)</summary>

| Property      | Type     | Required | Description                                                  |
| ------------- | -------- | -------- | ------------------------------------------------------------ |
| `content`     | string   | Yes      | The user's message text (use `' '` when sending only files). |
| `executionId` | string   | No       | Existing execution ID to continue a conversation.            |
| `files`       | `File[]` | No       | Browser `File` objects to upload and attach.                 |

The SDK obtains presigned upload URLs, uploads each file to cloud storage, and attaches the metadata to the message automatically — just pass the `File` objects.

```ts
// New conversation
instance.emit('query', { content: 'Hello, can you help me?' });

// With attachments
instance.emit('query', { content: 'Analyze these documents', files: [file1, file2] });

// Continue an existing conversation
instance.emit('query', { content: 'Tell me more', executionId: 'existing-execution-uuid' });

// Files only (no text)
instance.emit('query', { content: ' ', files: [selectedFile] });
```

</details>

<details>

<summary>Receiving events — on('agent-interrupt', handler)</summary>

The handler receives an `AgentInterruptEvent`; branch on its `type`:

| Event `type`    | Description                  | Key fields           |
| --------------- | ---------------------------- | -------------------- |
| `agent_message` | Agent text response          | `content`, `subtype` |
| `status_update` | Progress indicator           | `status`             |
| `done`          | Execution completed          | `content` (optional) |
| `error`         | Error occurred               | `error`              |
| `tool_call`     | Agent is calling a tool      | tool details         |
| `tool_result`   | Tool call completed          | tool result          |
| `plan_update`   | Agent created/updated a plan | plan details         |

`agent_message` events carry a `subtype`: `intermediate` (streaming), `final` (complete), `question` (needs user response), `final_stream`, `output_files`, `ask_permission`.

{% hint style="warning" %}
**Don't filter only by `subtype === 'final'`** or you'll miss agent questions and streamed replies — handle `final`, `question`, and `final_stream` at minimum.
{% endhint %}

```ts
const unsubscribe = instance.on('agent-interrupt', event => {
  switch (event.type) {
    case 'agent_message':
      if (['final', 'question', 'final_stream'].includes(event.subtype) && event.content) {
        displayMessage({ role: 'agent', content: event.content });
      }
      break;
    case 'error':
      displayMessage({ role: 'system', content: event.error ?? 'An error occurred' });
      break;
    case 'status_update':
    case 'done':
    case 'tool_call':
    case 'tool_result':
    case 'plan_update':
      // optional UI handling
      break;
    default:
      console.log('Unknown event type:', event.type);
  }
});
```

</details>

<details>

<summary>Cleanup</summary>

Always call `cleanup()` (and the unsubscribe function) when you're done — e.g. on component unmount:

```ts
unsubscribe();
instance.cleanup();
```

</details>

#### React integration example

```tsx
import { createHeadlessAgentInstance } from '@uptiqai/widgets-sdk';
import type { HeadlessAgentInstance, AgentInterruptEvent } from '@uptiqai/widgets-sdk';
import { useEffect, useRef, useState } from 'react';

const config = { serverUrl: '<BASE_URL>', agentId: '<agent-id>', widgetKey: '<your-widget-key>', agentExecutorVersion: '1.4' };
const user = { uid: 'user-123', firstName: 'Jane', lastName: 'User', email: 'jane@example.com' };

export const ChatComponent = () => {
  const [messages, setMessages] = useState<Array<{ role: 'user' | 'agent'; content: string }>>([]);
  const instanceRef = useRef<HeadlessAgentInstance | null>(null);

  useEffect(() => {
    const instance = createHeadlessAgentInstance({ config, user, instanceId: 'my-chat-instance' });
    instanceRef.current = instance;

    const unsubscribe = instance.on('agent-interrupt', (event: AgentInterruptEvent) => {
      if (event.type === 'agent_message'
          && ['final', 'question', 'final_stream'].includes(event.subtype ?? '')
          && event.content) {
        setMessages(prev => [...prev, { role: 'agent', content: event.content! }]);
      }
    });

    return () => { unsubscribe(); instance.cleanup(); };
  }, []);

  const sendMessage = (text: string, files?: File[]) => {
    setMessages(prev => [...prev, { role: 'user', content: text }]);
    instanceRef.current?.emit('query', { content: text, files });
  };

  return <div>{messages.map((m, i) => <div key={i}>{m.role}: {m.content}</div>)}</div>;
};
```

<details>

<summary>TypeScript types</summary>

```ts
import type {
  HeadlessAgentInstance,
  QueryPayload,
  AgentInterruptEvent,
  CreateHeadlessAgentInstanceParams,
} from '@uptiqai/widgets-sdk';

type HeadlessAgentInstance = {
  emit: (event: 'query', payload: QueryPayload) => void;
  on: (event: 'agent-interrupt', handler: (event: AgentInterruptEvent) => void) => () => void;
  cleanup: () => void;
};

type QueryPayload = { content: string; executionId?: string; files?: File[] };
```

</details>

#### Best practices

* **Single instance** — create one instance per chat context and reuse it for the whole conversation.
* **Subscribe before sending** — attach your `on('agent-interrupt', …)` handler before the first `emit` so no responses are missed.
* **Handle multiple subtypes** — capture `final`, `question`, and `final_stream`, not just `final`.
* **Always clean up** — call `cleanup()` on unmount to prevent memory leaks.
* **Persist `executionId`** — store and pass it to continue a conversation across page reloads.
* **Let the SDK handle uploads** — pass `File` objects; presigned-URL upload is automatic.

{% hint style="info" %}
The SDK manages socket connections and reconnection automatically, and shares the socket across instances that use the same `user` and `config`. For server-side or backend-only execution with no browser, use the **raw (HTTP)** client instead.
{% endhint %}

## How this relates to the agent's other settings

Whichever integration you choose, a few other settings shape how it behaves:

* **Access & Security** (documented for now as [Authentication](/console/agent-builder/deploy/authentication.md) and [Whitelisted Domains](/console/agent-builder/deploy/whitelisted-domains.md)) — the Access Keys are the credentials your Embedded Chat widget, TypeScript SDK client, or Agent API integration uses; the Allowed Domains list governs where the widget and TypeScript SDK client can run.
* [Secrets & Variables](/console/agent-builder/build/secrets-and-variables.md) — the credentials and values the agent uses at runtime; the widget, SDK, and API all invoke the agent against these same configured secrets.

Tighten these before you publish embeds or share API credentials — once a widget is live on a page, every visitor reaches the agent through whatever auth and domain rules you have set.

{% hint style="info" %}
To export the agent's full configuration as a portable package instead of running it live, see [Export Agent](/console/agent-builder/deploy/export-agent.md).
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.uptiq.ai/console/agent-builder/deploy/agent-integration.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
