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

# Query Instance Methods

> Methods available on Query instances for session control

The `Query` class returned by `query()` provides methods for controlling the query session, inspecting state, and modifying behavior mid-session.

## Overview

A `Query` instance implements `AsyncIterable<SDKMessage>`, allowing you to iterate over messages:

```typescript theme={null}
import { query } from '@qwen-code/sdk';

const q = query({
  prompt: 'Hello',
  options: {},
});

// Iterate over messages
for await (const message of q) {
  console.log(message);
}

// Or use methods
const sessionId = q.getSessionId();
```

## Methods

### getSessionId()

Get the unique session identifier.

```typescript theme={null}
getSessionId(): string
```

#### Returns

<ResponseField name="sessionId" type="string">
  The session ID (UUID format).
</ResponseField>

#### Example

```typescript theme={null}
const q = query({
  prompt: 'Hello',
  options: {},
});

const sessionId = q.getSessionId();
console.log('Session ID:', sessionId);
// Output: Session ID: 123e4567-e89b-12d3-a456-426614174000
```

#### Use Cases

* Resume sessions later with the `resume` option
* Track sessions across multiple queries
* Link sessions with external systems
* Debug and logging

### isClosed()

Check if the query session has been closed.

```typescript theme={null}
isClosed(): boolean
```

#### Returns

<ResponseField name="closed" type="boolean">
  `true` if the session is closed, `false` otherwise.
</ResponseField>

#### Example

```typescript theme={null}
const q = query({
  prompt: 'Hello',
  options: {},
});

console.log('Closed?', q.isClosed()); // false

for await (const message of q) {
  // Process messages
}

console.log('Closed?', q.isClosed()); // true (after iteration completes)
```

#### Use Cases

* Check session state before calling methods
* Conditional logic based on session status
* Resource cleanup verification

### interrupt()

Interrupt the current operation. The AI will stop what it's doing and await further instructions.

```typescript theme={null}
interrupt(): Promise<void>
```

#### Returns

<ResponseField name="promise" type="Promise<void>">
  Promise that resolves when the interrupt is acknowledged.
</ResponseField>

#### Example

```typescript theme={null}
const q = query({
  prompt: 'Analyze this large codebase',
  options: {},
});

// Interrupt after 5 seconds
setTimeout(async () => {
  await q.interrupt();
  console.log('Operation interrupted');
}, 5000);

for await (const message of q) {
  console.log(message);
}
```

#### Notes

* Throws an error if the query is already closed
* The interrupt is sent as a control request to the CLI
* The AI will finish the current tool execution before stopping

### setPermissionMode()

Change the permission mode during the session.

```typescript theme={null}
setPermissionMode(mode: PermissionMode): Promise<void>
```

#### Parameters

<ParamField path="mode" type="PermissionMode" required>
  The new permission mode: `'default'`, `'plan'`, `'auto-edit'`, or `'yolo'`.
</ParamField>

#### Returns

<ResponseField name="promise" type="Promise<void>">
  Promise that resolves when the mode change is acknowledged.
</ResponseField>

#### Example

```typescript theme={null}
import { query } from '@qwen-code/sdk';

const q = query({
  prompt: 'First, show me what you would do',
  options: {
    permissionMode: 'plan', // Start in plan mode
  },
});

let planShown = false;

for await (const message of q) {
  if (message.type === 'assistant' && !planShown) {
    console.log('Plan:', message.message.content);
    planShown = true;
    
    // Switch to auto-edit after seeing the plan
    await q.setPermissionMode('auto-edit');
    console.log('Switched to auto-edit mode');
  }
}
```

#### Notes

* Changes take effect immediately for subsequent tool requests
* Does not affect ongoing tool executions
* Throws an error if the query is closed

### setModel()

Change the AI model during the session.

```typescript theme={null}
setModel(model: string): Promise<void>
```

#### Parameters

<ParamField path="model" type="string" required>
  The new model identifier (e.g., `'gpt-4'`, `'qwen-max'`).
</ParamField>

#### Returns

<ResponseField name="promise" type="Promise<void>">
  Promise that resolves when the model change is acknowledged.
</ResponseField>

#### Example

```typescript theme={null}
const q = query({
  prompt: 'Start with a simple task',
  options: {
    model: 'gpt-3.5-turbo', // Start with faster model
  },
});

let taskCount = 0;

for await (const message of q) {
  if (message.type === 'result') {
    taskCount++;
    
    if (taskCount === 1) {
      // Switch to more powerful model for complex tasks
      await q.setModel('gpt-4');
      console.log('Switched to GPT-4');
    }
  }
}
```

#### Notes

* The new model is used for subsequent AI requests
* Does not affect the current ongoing request
* Throws an error if the query is closed

### close()

Manually close the query session and cleanup resources.

```typescript theme={null}
close(): Promise<void>
```

#### Returns

<ResponseField name="promise" type="Promise<void>">
  Promise that resolves when the session is fully closed.
</ResponseField>

#### Example

```typescript theme={null}
const q = query({
  prompt: 'Long running task',
  options: {},
});

let messageCount = 0;

for await (const message of q) {
  messageCount++;
  
  // Close after 10 messages
  if (messageCount >= 10) {
    await q.close();
    break;
  }
}

console.log('Session closed');
```

#### What Gets Cleaned Up

* CLI process terminated
* Pending control requests rejected
* MCP transports closed
* Input stream completed
* Event listeners removed

#### Notes

* Automatically called when iteration completes normally
* Safe to call multiple times (subsequent calls are no-ops)
* Pending operations will be rejected with "Query is closed" error

### streamInput()

Stream user messages for multi-turn conversations.

```typescript theme={null}
streamInput(messages: AsyncIterable<SDKUserMessage>): Promise<void>
```

<Warning>
  This is a low-level method. For most use cases, pass an async iterable as the `prompt` parameter to `query()` instead.
</Warning>

#### Parameters

<ParamField path="messages" type="AsyncIterable<SDKUserMessage>" required>
  Async iterable of user messages to send.
</ParamField>

#### Returns

<ResponseField name="promise" type="Promise<void>">
  Promise that resolves when all messages have been sent.
</ResponseField>

#### Example

```typescript theme={null}
import { query, type SDKUserMessage } from '@qwen-code/sdk';

const q = query({
  prompt: '',
  options: {},
});

// Stream messages programmatically
async function* generateMessages(): AsyncIterable<SDKUserMessage> {
  yield {
    type: 'user',
    session_id: q.getSessionId(),
    message: { role: 'user', content: 'First message' },
    parent_tool_use_id: null,
  };
  
  await new Promise(resolve => setTimeout(resolve, 1000));
  
  yield {
    type: 'user',
    session_id: q.getSessionId(),
    message: { role: 'user', content: 'Second message' },
    parent_tool_use_id: null,
  };
}

q.streamInput(generateMessages());

for await (const message of q) {
  console.log(message);
}
```

### endInput()

Signal that no more user messages will be sent (for multi-turn mode).

```typescript theme={null}
endInput(): void
```

<Warning>
  This is a low-level method. The SDK automatically calls this when using async iterables.
</Warning>

#### Example

```typescript theme={null}
const q = query({
  prompt: '',
  options: {},
});

// Send messages
q.streamInput(someMessages());

// Signal completion
q.endInput();
```

### supportedCommands()

Get the list of control commands supported by the CLI.

```typescript theme={null}
supportedCommands(): Promise<Record<string, unknown> | null>
```

#### Returns

<ResponseField name="commands" type="Record<string, unknown> | null">
  Object containing supported command names and their metadata.
</ResponseField>

#### Example

```typescript theme={null}
const q = query({
  prompt: 'Hello',
  options: {},
});

const commands = await q.supportedCommands();
console.log('Supported commands:', commands);
```

### mcpServerStatus()

Get the status of MCP servers connected to the session.

```typescript theme={null}
mcpServerStatus(): Promise<Record<string, unknown> | null>
```

#### Returns

<ResponseField name="status" type="Record<string, unknown> | null">
  Object containing MCP server status information.
</ResponseField>

#### Example

```typescript theme={null}
const q = query({
  prompt: 'Hello',
  options: {
    mcpServers: {
      calculator: myServer,
    },
  },
});

const status = await q.mcpServerStatus();
console.log('MCP servers:', status);
```

## Complete Example

Here's a comprehensive example using multiple methods:

```typescript theme={null}
import { query, isSDKAssistantMessage, isSDKResultMessage } from '@qwen-code/sdk';

async function advancedSession() {
  const q = query({
    prompt: 'Analyze the codebase',
    options: {
      permissionMode: 'plan',
      model: 'gpt-3.5-turbo',
    },
  });
  
  console.log('Session ID:', q.getSessionId());
  console.log('Closed?', q.isClosed());
  
  let planReceived = false;
  let needsInterrupt = false;
  
  for await (const message of q) {
    if (isSDKAssistantMessage(message) && !planReceived) {
      console.log('\n--- Plan ---');
      console.log(message.message.content);
      
      // Approve the plan and switch modes
      await q.setPermissionMode('auto-edit');
      await q.setModel('gpt-4');
      console.log('Switched to auto-edit + GPT-4');
      
      planReceived = true;
    }
    
    // Interrupt if something goes wrong
    if (needsInterrupt) {
      await q.interrupt();
      console.log('Operation interrupted');
      break;
    }
    
    if (isSDKResultMessage(message)) {
      console.log('\n--- Result ---');
      console.log('Duration:', message.duration_ms, 'ms');
      console.log('Tokens:', message.usage.input_tokens + message.usage.output_tokens);
      
      if (!message.is_error) {
        console.log('Success:', message.result);
      }
    }
  }
  
  console.log('Closed?', q.isClosed());
  
  // Explicit cleanup (optional, happens automatically)
  await q.close();
}

advancedSession().catch(console.error);
```

## Error Handling

All methods throw errors if called on a closed query:

```typescript theme={null}
const q = query({
  prompt: 'Hello',
  options: {},
});

for await (const message of q) {
  // Process messages
}

// Query is now closed
try {
  await q.setModel('gpt-4');
} catch (error) {
  console.error(error.message); // "Query is closed"
}
```

## See Also

* [query() Function](/sdk/api/query) - Create query sessions
* [Permission Modes](/sdk/api/permission-modes) - Understanding permission modes
* [Multi-Turn Example](/sdk/examples/multi-turn) - Multi-turn conversation patterns
