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.
Your First Query
Let’s create a simple script that asks the AI to analyze a directory.
Step 1: Install the SDK
npm install @qwen-code/sdk
Step 2: Set Up Authentication
Export your API key:
export OPENAI_API_KEY="your-api-key-here"
Step 3: Create Your Script
Create a file called example.ts:
import { query } from '@qwen-code/sdk';
// Single-turn query
const result = query({
prompt: 'What files are in the current directory?',
options: {
cwd: process.cwd(),
},
});
// Iterate over messages
for await (const message of result) {
if (message.type === 'assistant') {
console.log('Assistant:', message.message.content);
} else if (message.type === 'result') {
console.log('\nResult:', message.result);
console.log('Tokens used:', message.usage.input_tokens + message.usage.output_tokens);
}
}
Step 4: Run It
You should see the AI analyzing your directory and listing files!
Understanding the Output
The SDK emits different message types as the query progresses:
Message Types
Assistant Messages
Contain the AI’s responses:
if (message.type === 'assistant') {
// Access content blocks
for (const block of message.message.content) {
if (block.type === 'text') {
console.log(block.text);
} else if (block.type === 'tool_use') {
console.log(`Using tool: ${block.name}`);
}
}
}
System Messages
Provide session information:
if (message.type === 'system') {
console.log('Session ID:', message.session_id);
console.log('Working directory:', message.cwd);
console.log('Available tools:', message.tools);
console.log('Model:', message.model);
}
Result Messages
Indicate query completion:
if (message.type === 'result') {
if (message.is_error) {
console.error('Error:', message.error);
} else {
console.log('Success:', message.result);
console.log('Duration:', message.duration_ms, 'ms');
console.log('Turns:', message.num_turns);
}
}
Adding Permission Control
By default, the SDK denies all tool executions. Let’s allow the AI to read files:
import { query } from '@qwen-code/sdk';
const result = query({
prompt: 'Read package.json and tell me the project name',
options: {
cwd: process.cwd(),
permissionMode: 'default',
canUseTool: async (toolName, input) => {
// Allow read operations
if (toolName === 'read_file') {
console.log(`Allowing read of: ${input.path}`);
return { behavior: 'allow', updatedInput: input };
}
// Deny everything else
return {
behavior: 'deny',
message: `${toolName} is not allowed`
};
},
},
});
for await (const message of result) {
if (message.type === 'assistant') {
console.log('Assistant:', message.message.content);
}
}
Using Permission Modes
Instead of writing a custom canUseTool handler, use built-in permission modes:
YOLO Mode (Auto-Approve Everything)
const result = query({
prompt: 'Create a hello.txt file with "Hello World"',
options: {
permissionMode: 'yolo', // ⚠️ Use with caution!
},
});
Auto-Edit Mode (Auto-Approve Edits)
const result = query({
prompt: 'Fix the syntax errors in main.ts',
options: {
permissionMode: 'auto-edit', // Auto-approves edit and write_file
},
});
Plan Mode (Block All Writes)
const result = query({
prompt: 'How would you refactor this code?',
options: {
permissionMode: 'plan', // AI will explain instead of executing
},
});
Streaming Partial Messages
Get real-time updates as the AI generates responses:
import { query, isSDKPartialAssistantMessage } from '@qwen-code/sdk';
const result = query({
prompt: 'Explain how async/await works',
options: {
includePartialMessages: true,
},
});
for await (const message of result) {
if (isSDKPartialAssistantMessage(message)) {
const event = message.event;
if (event.type === 'content_block_delta') {
if (event.delta.type === 'text_delta') {
// Stream text as it's generated
process.stdout.write(event.delta.text);
}
}
} else if (message.type === 'assistant') {
console.log('\n[Complete message received]');
}
}
Aborting Queries
Cancel long-running queries:
import { query, isAbortError } from '@qwen-code/sdk';
const abortController = new AbortController();
const result = query({
prompt: 'Analyze this large codebase...',
options: {
abortController,
},
});
// Abort after 10 seconds
setTimeout(() => {
console.log('Aborting...');
abortController.abort();
}, 10000);
try {
for await (const message of result) {
console.log(message);
}
} catch (error) {
if (isAbortError(error)) {
console.log('Query was aborted by user');
} else {
throw error;
}
}
Complete Example
Here’s a complete example that demonstrates multiple features:
import { query, isSDKAssistantMessage, isSDKResultMessage } from '@qwen-code/sdk';
async function main() {
const abortController = new AbortController();
const result = query({
prompt: 'List the TypeScript files in the src directory',
options: {
cwd: process.cwd(),
permissionMode: 'default',
model: 'gpt-4',
abortController,
canUseTool: async (toolName, input, { signal }) => {
// Allow safe read operations
const readTools = ['list_directory', 'read_file', 'list_files'];
if (readTools.includes(toolName)) {
return { behavior: 'allow', updatedInput: input };
}
return { behavior: 'deny', message: 'Only read operations allowed' };
},
stderr: (message) => {
console.error('[CLI Error]:', message);
},
},
});
console.log('Session ID:', result.getSessionId());
for await (const message of result) {
if (isSDKAssistantMessage(message)) {
console.log('\n--- Assistant Message ---');
for (const block of message.message.content) {
if (block.type === 'text') {
console.log(block.text);
} else if (block.type === 'thinking') {
console.log('[Thinking]:', block.thinking);
} else if (block.type === 'tool_use') {
console.log(`[Tool]: ${block.name}(${JSON.stringify(block.input)})`);
}
}
} else if (isSDKResultMessage(message)) {
console.log('\n--- Result ---');
if (message.is_error) {
console.error('Error:', message.error);
} else {
console.log('Success:', message.result);
console.log(`Took ${message.duration_ms}ms (${message.num_turns} turns)`);
console.log('Tokens:', message.usage);
}
}
}
console.log('\nQuery closed:', result.isClosed());
}
main().catch(console.error);
Run it:
npx tsx complete-example.ts
Next Steps
API Reference
Learn about all available options
Message Types
Understand different message types
Permission Modes
Master permission control
Examples
Explore more examples