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

# Talk Commands

> Control persona output using talk commands

## Basic Usage

During a persona session, you can force a response from the persona using the `talk` method. This is useful when the user interacts with a UI element or when you use your own LLM instead of Anam's built-in models.

<Note>
  Both `talk()` and `createTalkMessageStream()` require an active streaming session. Call `stream()` or `streamToVideoElement()` first.
</Note>

```typescript theme={"system"}
await anamClient.talk("Hello, how are you?");
```

This sends the text to the persona, which then speaks it aloud.

<Note>
  To learn more about using the `talk` method with your own LLM, see the [Custom LLMs](/personas/llms/custom-llms) guide.
</Note>

## Streaming Talk Input

For lower latency, stream messages to the persona in chunks. This works well when streaming output from a custom LLM.

```typescript theme={"system"}
const talkMessageStream = anamClient.createTalkMessageStream();

const chunks = ["He", "l", "lo", ", how are you?"];

for (const chunk of chunks) {
  if (talkMessageStream.isActive()) {
    await talkMessageStream.streamMessageChunk(
      chunk,
      chunk === chunks[chunks.length - 1] // endOfSpeech: true on last chunk
    );
  }
}
```

<Note>
  Each `TalkMessageStream` represents one conversation turn. Once the turn ends, create a new stream for the next turn.
</Note>

### Available Methods

The `TalkMessageStream` object provides these methods:

| Method                                     | Description                                                                      |
| ------------------------------------------ | -------------------------------------------------------------------------------- |
| `streamMessageChunk(content, endOfSpeech)` | Send a text chunk. Set `endOfSpeech: true` on the final chunk.                   |
| `endMessage()`                             | End the stream without sending more content. Alternative to `endOfSpeech: true`. |
| `isActive()`                               | Returns `true` if the stream can still accept chunks.                            |
| `getState()`                               | Returns the current state: `UNSTARTED`, `STREAMING`, `INTERRUPTED`, or `ENDED`.  |
| `getCorrelationId()`                       | Returns the correlation ID for this stream.                                      |

### Ending a Stream

End a conversation turn in one of two ways:

**Option 1: Set `endOfSpeech` on the last chunk**

```typescript theme={"system"}
await talkMessageStream.streamMessageChunk("final text", true);
```

**Option 2: Call `endMessage()` separately**

```typescript theme={"system"}
await talkMessageStream.streamMessageChunk("final text", false);
await talkMessageStream.endMessage();
```

### Handling Interruptions

When a user speaks during a stream, the SDK emits `AnamEvent.TALK_STREAM_INTERRUPTED` and closes the stream:

```typescript theme={"system"}
import { AnamEvent } from "@anam-ai/js-sdk";

anamClient.addListener(AnamEvent.TALK_STREAM_INTERRUPTED, (event) => {
  console.log("Stream interrupted:", event.correlationId);
  // Handle the interruption - e.g., stop your LLM generation
});
```

### Checking Stream State

Check whether a stream can still accept chunks:

```typescript theme={"system"}
if (talkMessageStream.isActive()) {
  await talkMessageStream.streamMessageChunk(chunk, false);
}

// Or check the specific state
const state = talkMessageStream.getState();
// Returns: UNSTARTED | STREAMING | INTERRUPTED | ENDED
```

### Error Handling

The `streamMessageChunk` method throws an error if the stream is not active:

```typescript theme={"system"}
try {
  await talkMessageStream.streamMessageChunk("text", false);
} catch (error) {
  // Stream is in INTERRUPTED or ENDED state
  console.error("Cannot send chunk:", error.message);
}
```

## Correlation IDs

Attach a correlation ID to track streams, especially useful for matching interruption events:

```typescript theme={"system"}
const correlationId = "request-123";
const talkMessageStream = anamClient.createTalkMessageStream(correlationId);

// Later, when handling interruptions:
anamClient.addListener(AnamEvent.TALK_STREAM_INTERRUPTED, (event) => {
  if (event.correlationId === correlationId) {
    // This specific stream was interrupted
  }
});
```

<Note>
  Use unique correlation IDs for each `TalkMessageStream`. The ID appears in `TALK_STREAM_INTERRUPTED` events, helping you identify which stream was interrupted.
</Note>

## Next Steps

<Card title="Audio Control" icon="volume" href="/javascript-sdk/reference/audio-control">
  Learn how to control audio input in your Anam sessions
</Card>
