# AI Methods

URL: https://docs.boldvideo.com/sdk/ai-methods



The `ai` namespace is how your app talks to Bold's AI. Every method streams by default (see [Streaming](/sdk/streaming)) and accepts `stream: false` for plain JSON.

## `ai.chat(options)`

Library-wide Q\&A, or scoped to one video by passing `videoId`.

```typescript
// Streaming (default)
const stream = await bold.ai.chat({ prompt: 'How do I price my SaaS?' });
for await (const event of stream) {
  if (event.type === 'text_delta') process.stdout.write(event.delta);
  if (event.type === 'sources') console.log('Sources:', event.sources);
}

// Non-streaming
const response = await bold.ai.chat({
  prompt: 'What are the best closing techniques?',
  stream: false
});
console.log(response.content);
```

**Scoped to one video** (uses only that video's transcript as context):

```typescript
const stream = await bold.ai.chat({
  videoId: 'video-id',
  prompt: 'What is discussed at the 5 minute mark?',
  currentTime: 300   // optional playback position
});
```

**Continue a conversation:**

```typescript
const stream = await bold.ai.chat({
  prompt: 'Tell me more about that',
  conversationId: 'conv-id'   // from message_start / message_complete events
});
```

| Option           | Type           | Default | Description                                                     |
| ---------------- | -------------- | ------- | --------------------------------------------------------------- |
| `prompt`         | `string`       | -       | The question (required)                                         |
| `stream`         | `boolean`      | `true`  | SSE stream vs JSON                                              |
| `videoId`        | `string`       | -       | Scope to a single video                                         |
| `currentTime`    | `number`       | -       | Playback position (with `videoId`)                              |
| `conversationId` | `string`       | -       | Continue an existing conversation                               |
| `collectionId`   | `string`       | -       | Restrict context to a collection                                |
| `tags`           | `string[]`     | -       | Restrict context by tags                                        |
| `images`         | `ImageInput[]` | -       | Attach images (e.g. homework review): `File`, `Blob`, or base64 |

<Callout title="Plan availability">
  Library-wide chat (no `videoId`) is the AI Coach, available on Growth and Enterprise plans. Video-scoped chat works on every plan.
</Callout>

## `ai.search(options)`

Semantic search with a short AI-written summary of the results.

```typescript
const stream = await bold.ai.search({ prompt: 'pricing strategies', limit: 10 });
for await (const event of stream) {
  if (event.type === 'sources') console.log(`Found ${event.sources.length} clips`);
  if (event.type === 'text_delta') process.stdout.write(event.delta);
}
```

| Option                              | Type                 | Default | Description                           |
| ----------------------------------- | -------------------- | ------- | ------------------------------------- |
| `prompt`                            | `string`             | -       | Search query (required)               |
| `stream`                            | `boolean`            | `true`  | SSE stream vs JSON                    |
| `limit`                             | `number`             | -       | Max results                           |
| `collectionId` / `tags` / `videoId` | -                    | -       | Scope the search                      |
| `context`                           | `AIContextMessage[]` | -       | Previous turns, for follow-up queries |

## `ai.recommendations(options)`

Topic-based recommendations, ideal for learning paths and "what should I watch next."

```typescript
const stream = await bold.ai.recommendations({
  topics: ['contract law', 'ethics', 'client management']
});

for await (const event of stream) {
  if (event.type === 'recommendations') {
    for (const rec of event.recommendations) {
      console.log(rec.topic, rec.videos.map(v => v.title));
    }
  }
  if (event.type === 'text_delta') process.stdout.write(event.delta); // AI guidance
}
```

| Option                  | Type                 | Default | Description                   |
| ----------------------- | -------------------- | ------- | ----------------------------- |
| `topics`                | `string[]`           | -       | Topics to cover (required)    |
| `limit`                 | `number`             | `5`     | Max videos per topic (max 20) |
| `includeGuidance`       | `boolean`            | `true`  | Narrative learning-path text  |
| `collectionId` / `tags` | -                    | -       | Scope the pool                |
| `context`               | `AIContextMessage[]` | -       | Previous turns                |
| `stream`                | `boolean`            | `true`  | SSE stream vs JSON            |

## `ai.getConversation(id)`

```typescript
const conversation = await bold.ai.getConversation('conv-id');
for (const message of conversation.messages) {
  console.log(`${message.role}: ${message.content}`);
}
```

## Multi-turn without conversations

Search and recommendations accept a `context` array instead of a conversation ID:

```typescript
const first = await bold.ai.search({ prompt: 'How do indie designers find clients?', stream: false });
const followUp = await bold.ai.search({
  prompt: 'What about cold outreach specifically?',
  context: first.context,
  stream: false
});
```

## Deprecated aliases

`ai.ask()`, `ai.coach()` → use `ai.chat()`. `ai.recommend()` → use `ai.recommendations()`. The old names still work but will be removed in v2.
