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

# Get Started

> Initialize and use the SDK in minutes.

## Minimal Template

```typescript theme={null}
import { initSidenet, toggleSidenet } from 'sidenetai-sdk';

// Mint the session on your backend, then hand the response straight over.
// It carries the organization, the user and the billing group — so none of
// those are passed here. See Authentication for the full flow.
const tokens = await fetch('/my-backend/sidenet-token').then((r) => r.json());

await initSidenet({
  copilotId: 'copilot-456',   // Copilot identifier
  auth: { ...tokens },        // Session token — required
  contentElement: '#app',     // Push this element aside when the panel opens
  defaultOpen: true,
  keyboardShortcut: 'k',      // Cmd+k / Ctrl+k to toggle
});

// Toggle with a button
document.getElementById('chat-btn').onclick = toggleSidenet;
```

<Note>
  `auth` is the only required option, plus **at least one** of `copilotId`, `agentId` or `agentVersionId`. See [Authentication](/docs/sdk/authentication) for how to mint the session.
</Note>

## Push

Automatically push your page content when the sidebar opens:

```typescript theme={null}
initSidenet({
  copilotId: 'copilot-456',
  auth: { ...tokens },
  position: 'right',
  contentElement: '#app', // CSS selector for your main content
});
```

The element will receive `margin-right` (or `margin-left` for left position) matching the sidebar width.

## All Config Options

All options for `initSidenet()`:

```typescript theme={null}
await initSidenet({
  // Required — the session token from your backend. See "Authentication".
  auth: {
    access_token: string,      // snat_…
    refresh_token: string,     // snrt_… — its presence turns on automatic refresh
    expires_in: number,        // seconds
    onRefresh: (tokens) => {}, // persist the rotated pair (optional)
    onError: (error) => {},    // check error.fatal (optional)
  },

  // Agent target — provide AT LEAST ONE of copilotId, agentId or agentVersionId
  copilotId: string,          // Copilot to route through
                              // agentId / agentVersionId are under "Agent & Threading" below

  // Layout
  position: 'left' | 'right', // Sidebar position (default: 'right')
  width: string,              // Panel width, e.g. '400px', '45vw' (default: '45vw')
  height: string,             // Panel height (modal default: '600px', sidebar: auto)
  layout: 'sidebar' | 'modal' | 'drawer', // Layout mode (default: 'sidebar'). drawer = overlay panel that closes on outside-click/Escape
  offset: {                   // Positioning offsets
    top?: string,
    bottom?: string,
    left?: string,
    right?: string,
  },
  zIndex: string | number,    // Stacking order of the container (default: unset)

  // Behavior
  defaultOpen: boolean,       // Start open or closed (default: false)
  keyboardShortcut: string,   // Key for Cmd/Ctrl shortcut, e.g. 'b'
  contentElement: string,     // CSS selector for content to push aside, e.g. '#app'
  debug: boolean,             // Enable verbose console logs (default: false)

  // Agent & Threading
  agentId: string,            // Run a specific agent's ACTIVE published version (skips agent selection)
  agentVersionId: string,     // Override: run this EXACT agent_versions.id (e.g. preview a draft or a
                              //   non-active published version) instead of the active one
  showAgentDropdown: boolean, // Force-show/hide agent dropdown
                              //   undefined (default) → auto: show if multiple
                              //   agents AND no agentId provided
  groupName: string,          // Group display name — used for reporting in Studio
  groupId: string,            // Stable group identifier — supersedes groupName for matching
                              //   (customer group / billing group / spend limits). When both are
                              //   sent with a different name, the group's name is updated to groupName.
  lastThread: boolean,        // Auto-select most recent thread on init
  threadId: string,           // Pin to specific thread
  read_only: boolean,         // Hide composer (requires threadId)
  use_routing: boolean,       // Enable backend message routing (default: true)

  // Context & Messages
  context: string[],          // Free-form strings injected as a "Session context" section
                              //   at the top of the system prompt (see "Prompt Variables")
  variables: Record<string, Value>,
                              // Values for the {{placeholders}} the agent's prompt blocks declare.
                              //   Value = string | number | boolean | null, an array of those, or a
                              //   nested object — `{ user: { language: 'FR' } }` fills {{user.language}}.
                              //   Call getSidenetVariables() to list what the agents actually declare.
  firstMessage: string,       // Auto-send on first open

  // Theming
  theme: 'light' | 'dark',    // Color scheme (default: 'light')
  customCSS: string,          // Raw CSS injected into Shadow DOM
  customStyles: Record<string, Record<string, string>>, // Structured CSS rules

  // UI chrome
  showClose: boolean,         // Show a close/collapse button in the header (default: false)
  closeOnOutsideClick: 'auto' | 'always' | 'never', // Outside-click / Escape dismissal (default: 'auto')

  // Greeting / placeholder / suggestions / theme tokens (overrides backend sdk_ui)
  // Layers on top of the DB config — only the fields you pass are overridden.
  sdkUi: Partial<SidebarSDKConfig>,

  // Callbacks
  onOpen: (detail) => void,
  onClose: (detail) => void,
  onResize: (detail) => void,
  onReady: (detail) => void,
});
```

## Agent target: `copilotId` / `agentId` / `agentVersionId`

`auth` is always required. On top of it you must provide **at least one** of these three so the backend knows what to run — `initSidenet()` throws if all three are missing:

| Field            | Resolves to                                                                                                                                |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `copilotId`      | Routes through a copilot. Loads its agent list and greeting/suggestions, and (unless `agentId` is also set) shows the agent dropdown.      |
| `agentId`        | Runs a specific agent's **active published version** — a stable `agents.id`. Skips agent selection.                                        |
| `agentVersionId` | Override that runs an **exact** `agent_versions.id` — e.g. to preview a draft or a non-active published version instead of the active one. |

You can combine them: pass `copilotId` for config/greeting loading alongside an `agentId`/`agentVersionId` to pin the agent. When you pass only `agentId` or `agentVersionId` (no `copilotId`), no copilot config is fetched, so greeting/suggestions fall back to defaults (or whatever you pass via `sdkUi`). All three travel in the `/v1/chat` request body.

<Note>
  `agentVersionId` is also updatable at runtime via `updateSidenetConfig({ agentVersionId })` — pass `null` to clear the pin.
</Note>

## `closeOnOutsideClick`

Controls whether clicking outside the panel (or pressing **Escape**) dismisses the SDK. It's a three-way string so the layout-aware default stays explicit and resettable at runtime:

| Value               | Behavior                                                                                                                  |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `'auto'`*(default)* | On for the `drawer` layout only; `sidebar` and `modal` are not dismissed by outside clicks.                               |
| `'always'`          | Every layout closes on outside-click / Escape (e.g. make a `modal` dismissable).                                          |
| `'never'`           | No layout closes on outside-click / Escape, including the `drawer` (close via the button, shortcut, or `closeSidenet()`). |

Settable at init and via `updateSidenetConfig({ closeOnOutsideClick })` — pass `'auto'` to return to the default behavior at runtime.
