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

# Multi-turn Conversation

`query()` supports two input modes:

* **Single-message query mode**: submit one user message; the SDK closes the session after the current reply completes. See the [Quickstart](/en/cli/sdk/quick-start).
* **Multi-message session mode**: keep the session open and carry on a multi-turn conversation with the model.

***

<div id="multi-message-session" />

## Multi-message session

Define a sequence that yields user messages in order:

```typescript theme={null}
import { qodercliAuth, query, type SDKUserMessage } from '@qoder-ai/qoder-agent-sdk';

async function* messages(): AsyncGenerator<SDKUserMessage> {
  yield {
    type: 'user',
    message: { role: 'user', content: [{ type: 'text', text: 'Analyze this codebase for security issues' }] },
    parent_tool_use_id: null,
  };

  // You can wait for any external condition before yielding the next message
  await new Promise((resolve) => setTimeout(resolve, 2000));

  yield {
    type: 'user',
    message: { role: 'user', content: [{ type: 'text', text: 'Now write a short report' }] },
    parent_tool_use_id: null,
  };
}

for await (const msg of query({
  prompt: messages(),
  options: {
    auth: qodercliAuth(),
    allowedTools: ['Read', 'Grep'],
  },
})) {
  if (msg.type === 'result' && msg.subtype === 'success') {
    console.log(msg.result);
  }
}
```

The model replies once for each user message it receives. Once the message sequence finishes, the session closes automatically. For message field definitions see [`SDKUserMessage`](/en/cli/sdk/references#sdkusermessage).

***

<div id="interrupting-the-current-turn" />

## Interrupting the current turn

When the user wants to stop the current response but continue the conversation later, call `await q.interrupt()`. After the call completes, the current generation or tool execution has stopped.

```typescript theme={null}
import { qodercliAuth, query } from '@qoder-ai/qoder-agent-sdk';

const q = query({
  prompt: 'Inspect every file in this repository.',
  options: { auth: qodercliAuth() },
});

const interruptTimer = setTimeout(() => {
  void q.interrupt().catch(console.error);
}, 5_000);

try {
  for await (const msg of q) {
    console.dir(msg, { depth: null });
  }
} finally {
  clearTimeout(interruptTimer);
}
```

`interrupt()` only stops the active turn; it does not close the session. A multi-message session can continue with another turn. See [Managing the session lifecycle](#managing-the-session-lifecycle) for ways to end the entire session.

***

<div id="managing-the-session-lifecycle" />

## Managing the session lifecycle

The SDK closes the session automatically after a string input or finite message sequence ends. To end the session earlier, use an `AbortController` to define when it should end, or call `q.close()` directly.

### Define when the session ends

To end the session when a custom business condition is met, create an `AbortController` and pass it through `options.abortController` when calling `query()`. Call `abort()` on the same controller when that condition is met. The condition can come from a user action, upstream request, task timeout, application shutdown, or other application logic:

```typescript theme={null}
import { qodercliAuth, query } from '@qoder-ai/qoder-agent-sdk';

const abortController = new AbortController();
const q = query({
  prompt: 'Inspect every file in this repository.',
  options: { auth: qodercliAuth(), abortController },
});

const taskTimeout = setTimeout(() => abortController.abort(), 5_000);
try {
  for await (const msg of q) {
    console.dir(msg, { depth: null });
  }
} finally {
  clearTimeout(taskTimeout);
}
```

Calling `abort()` closes the entire session and ends message iteration. It cannot accept more messages afterward.

### Close a session explicitly

When the current code no longer needs the session, call `await q.close()` directly. This works for normal completion, early exit, and error cleanup; placing it in `finally` ensures related resources finish closing:

```typescript theme={null}
import { qodercliAuth, query } from '@qoder-ai/qoder-agent-sdk';

const q = query({
  prompt: 'Inspect every file in this repository.',
  options: { auth: qodercliAuth() },
});

try {
  for await (const msg of q) {
    console.dir(msg, { depth: null });
  }
} finally {
  await q.close();
}
```
