Skip to main content
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:
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.
getSessionId(): string

Returns

sessionId
string
The session ID (UUID format).

Example

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.
isClosed(): boolean

Returns

closed
boolean
true if the session is closed, false otherwise.

Example

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.
interrupt(): Promise<void>

Returns

promise
Promise<void>
Promise that resolves when the interrupt is acknowledged.

Example

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.
setPermissionMode(mode: PermissionMode): Promise<void>

Parameters

mode
PermissionMode
required
The new permission mode: 'default', 'plan', 'auto-edit', or 'yolo'.

Returns

promise
Promise<void>
Promise that resolves when the mode change is acknowledged.

Example

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.
setModel(model: string): Promise<void>

Parameters

model
string
required
The new model identifier (e.g., 'gpt-4', 'qwen-max').

Returns

promise
Promise<void>
Promise that resolves when the model change is acknowledged.

Example

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.
close(): Promise<void>

Returns

promise
Promise<void>
Promise that resolves when the session is fully closed.

Example

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.
streamInput(messages: AsyncIterable<SDKUserMessage>): Promise<void>
This is a low-level method. For most use cases, pass an async iterable as the prompt parameter to query() instead.

Parameters

messages
AsyncIterable<SDKUserMessage>
required
Async iterable of user messages to send.

Returns

promise
Promise<void>
Promise that resolves when all messages have been sent.

Example

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).
endInput(): void
This is a low-level method. The SDK automatically calls this when using async iterables.

Example

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.
supportedCommands(): Promise<Record<string, unknown> | null>

Returns

commands
Record<string, unknown> | null
Object containing supported command names and their metadata.

Example

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.
mcpServerStatus(): Promise<Record<string, unknown> | null>

Returns

status
Record<string, unknown> | null
Object containing MCP server status information.

Example

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:
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:
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