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

# Programmatic Control

> Open, close, send messages, and prefill input on the embedded agent from your application code.

`embedWidget()` returns a `WidgetInstance` with methods to control the agent programmatically. This lets you trigger conversations from buttons, links, application events, or any other logic in your app.

```javascript theme={null}
import { embedWidget } from 'agent-embed-widget';
import 'agent-embed-widget/dist/agent-embed-widget.css';

const widget = embedWidget({
  url: 'https://console.thesys.dev/app/your-slug',
  theme: 'dark',
});
```

***

## Methods

### `widget.open()`

Opens the widget and makes it visible.

```javascript theme={null}
widget.open();
```

### `widget.close()`

Closes the widget. The agent stays loaded in the background — reopening is instant.

```javascript theme={null}
widget.close();
```

### `widget.destroy()`

Removes the widget from the DOM entirely and cleans up all resources. After calling `destroy()`, the instance cannot be reopened.

```javascript theme={null}
widget.destroy();
```

### `widget.sendMessage(message, options?)`

Sends a user message to the agent. If the widget is closed, it opens automatically.

```javascript theme={null}
widget.sendMessage('Tell me about pricing');
widget.sendMessage('Start a new topic', { newThread: true });
```

| Parameter           | Type      | Description                                                                  |
| ------------------- | --------- | ---------------------------------------------------------------------------- |
| `message`           | `string`  | The message text to send                                                     |
| `options.newThread` | `boolean` | If `true`, starts a new conversation thread before sending. Default: `false` |

### `widget.setInput(message, options?)`

Prefills the chat input bar **without** sending. The widget opens (if closed) and the user can review, edit, and submit the message themselves.

```javascript theme={null}
widget.setInput('Can you help me understand my recent invoice?');
widget.setInput('New question for a fresh thread', { newThread: true });
```

| Parameter           | Type      | Description                                                                     |
| ------------------- | --------- | ------------------------------------------------------------------------------- |
| `message`           | `string`  | The message text to prefill                                                     |
| `options.newThread` | `boolean` | If `true`, starts a new conversation thread before prefilling. Default: `false` |

### `widget.preload()`

Starts loading the agent iframe in the background so it's ready instantly when the user opens the widget. Useful when you didn't set `preload: true` in the initial options but want to trigger it based on user behavior.

```javascript theme={null}
widget.preload();
```

***

## Examples

### Trigger from buttons

```html theme={null}
<button id="ask-pricing">Ask about pricing</button>
<button id="new-chat">Start fresh</button>
<button id="suggest">Suggest a question</button>

<script type="module">
  import { embedWidget } from 'agent-embed-widget';
  import 'agent-embed-widget/dist/agent-embed-widget.css';

  const widget = embedWidget({
    url: 'https://console.thesys.dev/app/your-slug',
    theme: 'light',
  });

  document.getElementById('ask-pricing').addEventListener('click', () => {
    widget.sendMessage('Tell me about pricing');
  });

  document.getElementById('new-chat').addEventListener('click', () => {
    widget.sendMessage('I need help with my order', { newThread: true });
  });

  document.getElementById('suggest').addEventListener('click', () => {
    widget.setInput('Can you explain how billing works?');
  });
</script>
```

### Preload on scroll

Load the agent in the background as the user scrolls near the bottom of the page:

```javascript theme={null}
const widget = embedWidget({
  url: 'https://console.thesys.dev/app/your-slug',
});

window.addEventListener('scroll', () => {
  if (window.scrollY > document.body.scrollHeight - 1000) {
    widget.preload();
  }
}, { once: true });
```

### Open after a delay

```javascript theme={null}
const widget = embedWidget({
  url: 'https://console.thesys.dev/app/your-slug',
});

setTimeout(() => widget.open(), 5000);
```

### Clean up on navigation (SPA)

In a single-page application, destroy the widget when the user navigates away from the page:

```javascript theme={null}
const widget = embedWidget({
  url: 'https://console.thesys.dev/app/your-slug',
});

// React useEffect cleanup, Vue onUnmounted, etc.
return () => widget.destroy();
```

***

## Pending Messages

If you call `sendMessage()` or `setInput()` before the agent iframe has finished loading, the action is queued and executed automatically once the iframe is ready. You don't need to wait for a "loaded" event.
