Typescript SDK
@qwen-code/sdk
Qwen Code에 프로그래밍 방식으로 접근하기 위한 최소한의 실험적 TypeScript SDK입니다.
기능 요청/이슈/PR을 자유롭게 제출해 주세요.
설치
npm install @qwen-code/sdk요구 사항
- Node.js >= 22.0.0
- Qwen Code >= 0.4.0 (안정) 설치 및 PATH에서 접근 가능
nvm 사용자를 위한 참고 사항: nvm으로 Node.js 버전을 관리하는 경우, SDK가 Qwen Code 실행 파일을 자동으로 감지하지 못할 수 있습니다.
pathToQwenExecutable옵션을qwen바이너리의 전체 경로로 명시적으로 설정해야 합니다.
빠른 시작
import { query } from '@qwen-code/sdk';
// 단일 턴 쿼리
const result = query({
prompt: 'What files are in the current directory?',
options: {
cwd: '/path/to/project',
},
});
// 메시지 반복
for await (const message of result) {
if (message.type === 'assistant') {
console.log('Assistant:', message.message.content);
} else if (message.type === 'result') {
console.log('Result:', message.result);
}
}API 레퍼런스
query(config)
Qwen Code와 새 쿼리 세션을 생성합니다.
파라미터
prompt:string | AsyncIterable<SDKUserMessage>- 전송할 프롬프트. 단일 턴 쿼리에는 문자열을, 멀티 턴 대화에는 async iterable을 사용하세요.options:QueryOptions- 쿼리 세션의 구성 옵션.
QueryOptions
| 옵션 | 타입 | 기본값 | 설명 |
|---|---|---|---|
cwd | string | process.cwd() | 쿼리 세션의 작업 디렉토리. 파일 작업과 명령어가 실행되는 컨텍스트를 결정합니다. |
model | string | - | 사용할 AI 모델 (예: 'qwen-max', 'qwen-plus', 'qwen-turbo'). OPENAI_MODEL 및 QWEN_MODEL 환경 변수보다 우선합니다. |
pathToQwenExecutable | string | 자동 감지 | Qwen Code 실행 파일의 경로. 다양한 형식 지원: 'qwen' (PATH의 네이티브 바이너리), '/path/to/qwen' (명시적 경로), '/path/to/cli.js' (Node.js 번들), 'node:/path/to/cli.js' (Node.js 런타임 강제), 'bun:/path/to/cli.js' (Bun 런타임 강제). 제공되지 않으면 다음에서 자동 감지: QWEN_CODE_CLI_PATH 환경 변수, ~/.volta/bin/qwen, ~/.npm-global/bin/qwen, /usr/local/bin/qwen, ~/.local/bin/qwen, ~/node_modules/.bin/qwen, ~/.yarn/bin/qwen. |
permissionMode | 'default' | 'plan' | 'auto-edit' | 'auto' | 'yolo' | 'default' | 도구 실행 승인을 제어하는 승인 모드. 자세한 내용은 승인 모드를 참조하세요. |
canUseTool | CanUseTool | - | 도구 실행 승인을 위한 커스텀 권한 핸들러. 도구가 확인을 요구할 때 호출됩니다. 60초 이내에 응답해야 하며, 그렇지 않으면 요청이 자동 거부됩니다. 커스텀 권한 핸들러를 참조하세요. |
env | Record<string, string> | - | Qwen Code 프로세스에 전달할 환경 변수. 현재 프로세스 환경과 병합됩니다. |
systemPrompt | string | QuerySystemPromptPreset | - | 메인 세션의 시스템 프롬프트 구성. 문자열을 사용하면 내장 Qwen Code 시스템 프롬프트를 완전히 오버라이드하고, 프리셋 객체를 사용하면 내장 프롬프트를 유지하면서 추가 지시를 덧붙입니다. |
mcpServers | Record<string, McpServerConfig> | - | 연결할 모델 컨텍스트 프로토콜(MCP) 서버. 외부 서버(stdio/SSE/HTTP) 및 SDK 내장 서버를 지원합니다. 외부 서버는 command, args, url, httpUrl 등의 transport 옵션으로 구성합니다. SDK 서버는 { type: 'sdk', name: string, instance: Server }를 사용합니다. |
abortController | AbortController | - | 쿼리 세션을 취소하는 컨트롤러. abortController.abort()를 호출하여 세션을 종료하고 리소스를 정리합니다. |
debug | boolean | false | CLI 프로세스의 상세 로깅을 위한 디버그 모드를 활성화합니다. |
maxSessionTurns | number | -1 (무제한) | 세션이 자동으로 종료되기 전의 최대 대화 턴 수. 정수여야 합니다. 턴은 사용자 메시지와 어시스턴트 응답으로 구성됩니다. |
coreTools | string[] | - | 레거시 coreTools / CLI --core-tools 허용목록 시맨틱스를 사용합니다. 지정되면 일치하는 핵심 도구만 세션에 등록됩니다. 이는 일치하는 도구 호출을 자동 승인하지만 도구 등록을 제한하지는 않는 permissions.allow와 별개입니다. 예시: ['read_file', 'edit', 'run_shell_command']. |
excludeTools | string[] | - | settings.json의 permissions.deny와 동일합니다. 제외된 도구는 즉시 권한 오류를 반환합니다. 다른 모든 권한 설정보다 가장 높은 우선순위를 가집니다. 도구 이름 별칭 및 패턴 매칭 지원: 도구 이름('write_file'), 셸 명령어 접두사('Bash(rm *)'), 또는 경로 패턴('Read(.env)', 'Edit(/src/**)'). |
allowedTools | string[] | - | settings.json의 permissions.allow와 동일합니다. 일치하는 도구는 canUseTool 콜백을 우회하여 자동으로 실행됩니다. 도구가 확인을 요구할 때만 적용됩니다. excludeTools와 동일한 패턴 매칭을 지원합니다. 예시: ['Bash(git status)', 'Bash(npm test)']. |
authType | 'openai' | 'qwen-oauth' | 'openai' | AI 서비스의 인증 유형. Qwen OAuth 무료 티어는 2026-04-15에 중단되었습니다. 새 SDK 설정은 OpenAI 호환 인증 또는 다른 지원 provider를 사용해야 합니다. |
agents | SubagentConfig[] | - | 세션 중에 호출할 수 있는 서브에이전트의 구성. 서브에이전트는 특정 작업이나 도메인을 위한 특화된 AI 에이전트입니다. |
includePartialMessages | boolean | false | true이면, SDK가 생성 중에 미완료 메시지를 방출하여 AI 응답의 실시간 스트리밍을 허용합니다. |
resume | string | - | 세션 ID를 제공하여 이전 세션을 재개합니다. CLI의 --resume 플래그와 동일합니다. |
sessionId | string | - | 새 세션의 세션 ID를 지정합니다. 이력을 재개하지 않고 SDK와 CLI가 동일한 ID를 사용하도록 합니다. CLI의 --session-id 플래그와 동일합니다. |
[!note]
coreTools의 경우,Read,Edit,Bash와 같은 별칭도 작동하지만Bash(git *)와 같은 호출 지정자는 제거됩니다.coreTools는 도구 등록을 제한하며 호출 패턴을 제한하지 않습니다.
타임아웃
SDK는 다음 기본 타임아웃을 적용합니다:
| 타임아웃 | 기본값 | 설명 |
|---|---|---|
canUseTool | 1분 | canUseTool 콜백이 응답할 수 있는 최대 시간. 초과 시 도구 요청이 자동 거부됩니다. |
mcpRequest | 1분 | SDK MCP 도구 호출이 완료될 수 있는 최대 시간. |
controlRequest | 1분 | initialize(), setModel(), setPermissionMode(), getContextUsage(), interrupt()와 같은 제어 작업이 완료될 수 있는 최대 시간. |
streamClose | 1분 | SDK MCP 서버가 있는 멀티 턴 모드에서 CLI stdin을 닫기 전에 초기화가 완료될 때까지 대기하는 최대 시간. |
timeout 옵션을 통해 이 타임아웃을 커스터마이즈할 수 있습니다:
const query = qwen.query('Your prompt', {
timeout: {
canUseTool: 60000, // 권한 콜백에 60초
mcpRequest: 600000, // MCP 도구 호출에 10분
controlRequest: 60000, // 제어 요청에 60초
streamClose: 15000, // 스트림 close 대기에 15초
},
});메시지 타입
SDK는 다양한 메시지 타입을 식별하기 위한 타입 가드를 제공합니다:
import {
isSDKUserMessage,
isSDKAssistantMessage,
isSDKSystemMessage,
isSDKResultMessage,
isSDKPartialAssistantMessage,
} from '@qwen-code/sdk';
for await (const message of result) {
if (isSDKAssistantMessage(message)) {
// 어시스턴트 메시지 처리
} else if (isSDKResultMessage(message)) {
// 결과 메시지 처리
}
}Query 인스턴스 메서드
query()가 반환하는 Query 인스턴스는 여러 메서드를 제공합니다:
const q = query({ prompt: 'Hello', options: {} });
// 세션 ID 가져오기
const sessionId = q.getSessionId();
// 종료 여부 확인
const closed = q.isClosed();
// 현재 작업 중단
await q.interrupt();
// 세션 중 승인 모드 변경
await q.setPermissionMode('yolo');
// 세션 중 모델 변경
await q.setModel('qwen-max');
// 컨텍스트 창 사용량 세부 정보 가져오기 (카테고리별 토큰 수)
const usage = await q.getContextUsage();
// 항목별 세부 정보를 표시하도록 힌트를 전달하려면 true를 전달하세요
const detail = await q.getContextUsage(true);
// 세션 종료
await q.close();승인 모드
SDK는 도구 실행을 제어하기 위해 다양한 승인 모드를 지원합니다:
default: 쓰기 도구는canUseTool콜백이나allowedTools에서 승인되지 않는 한 거부됩니다. 읽기 전용 도구는 확인 없이 실행됩니다.plan: 모든 쓰기 도구를 차단하고 AI에게 먼저 계획을 제시하도록 지시합니다.auto-edit: 편집 도구(edit,write_file,notebook_edit)를 자동 승인하고 다른 도구는 확인을 요구합니다.auto: 내장 분류기를 사용하여 안전한 도구 호출을 자동 승인하고 위험한 호출을 차단합니다. 반복된 정책 차단 또는 분류기 장애 시 수동 승인 폴백을 제공합니다.yolo: 모든 도구가 확인 없이 자동으로 실행됩니다.
권한 우선순위 체인
결정 우선순위 (높은 순): deny > ask > allow > (기본/인터랙티브 모드)
먼저 일치하는 규칙이 적용됩니다.
excludeTools/permissions.deny- 도구를 완전히 차단 (권한 오류 반환)permissions.ask- 항상 사용자 확인을 요구permissionMode: 'plan'- 읽기 전용이 아닌 모든 도구를 차단permissionMode: 'yolo'- 모든 도구를 자동 승인allowedTools/permissions.allow- 일치하는 도구를 자동 승인permissionMode: 'auto'- 나머지 도구에 대한 분류기 중재 승인canUseTool콜백 - 커스텀 승인 로직 (제공된 경우, 허용된 도구에 대해서는 호출되지 않음)- 기본 동작 - SDK 모드에서 자동 거부 (쓰기 도구는 명시적 승인 필요)
예시
멀티 턴 대화
import { query, type SDKUserMessage } from '@qwen-code/sdk';
async function* generateMessages(): AsyncIterable<SDKUserMessage> {
yield {
type: 'user',
session_id: 'my-session',
message: { role: 'user', content: 'Create a hello.txt file' },
parent_tool_use_id: null,
};
// 특정 조건이나 사용자 입력을 대기
yield {
type: 'user',
session_id: 'my-session',
message: { role: 'user', content: 'Now read the file back' },
parent_tool_use_id: null,
};
}
const result = query({
prompt: generateMessages(),
options: {
permissionMode: 'auto-edit',
},
});
for await (const message of result) {
console.log(message);
}커스텀 권한 핸들러
import { query, type CanUseTool } from '@qwen-code/sdk';
const canUseTool: CanUseTool = async (toolName, input, { signal }) => {
// 모든 읽기 작업 허용
if (toolName.startsWith('read_')) {
return { behavior: 'allow', updatedInput: input };
}
// 쓰기 작업에 대해 사용자에게 확인 요청 (실제 앱에서)
const userApproved = await promptUser(`Allow ${toolName}?`);
if (userApproved) {
return { behavior: 'allow', updatedInput: input };
}
return { behavior: 'deny', message: 'User denied the operation' };
};
const result = query({
prompt: 'Create a new file',
options: {
canUseTool,
},
});외부 MCP 서버와 함께 사용
import { query } from '@qwen-code/sdk';
const result = query({
prompt: 'Use the custom tool from my MCP server',
options: {
mcpServers: {
'my-server': {
command: 'node',
args: ['path/to/mcp-server.js'],
env: { PORT: '3000' },
},
},
},
});시스템 프롬프트 오버라이드
import { query } from '@qwen-code/sdk';
const result = query({
prompt: 'Say hello in one sentence.',
options: {
systemPrompt: 'You are a terse assistant. Answer in exactly one sentence.',
},
});내장 시스템 프롬프트에 추가
import { query } from '@qwen-code/sdk';
const result = query({
prompt: 'Review the current directory.',
options: {
systemPrompt: {
type: 'preset',
preset: 'qwen_code',
append: 'Be terse and focus on concrete findings.',
},
},
});SDK 내장 MCP 서버와 함께 사용
SDK는 SDK 애플리케이션과 동일한 프로세스에서 실행되는 MCP 서버를 생성하기 위해 tool과 createSdkMcpServer를 제공합니다. 별도의 서버 프로세스를 실행하지 않고 AI에 커스텀 도구를 노출하고 싶을 때 유용합니다.
tool(name, description, inputSchema, handler)
Zod 스키마 타입 추론을 사용하여 도구 정의를 생성합니다.
| 파라미터 | 타입 | 설명 |
|---|---|---|
name | string | 도구 이름 (1-64자, 문자로 시작, 영숫자 및 밑줄) |
description | string | 도구의 기능을 설명하는 읽기 쉬운 설명 |
inputSchema | ZodRawShape | 도구의 입력 파라미터를 정의하는 Zod 스키마 객체 |
handler | (args, extra) => Promise<Result> | 도구를 실행하고 MCP 콘텐츠 블록을 반환하는 async 함수 |
핸들러는 다음 구조의 CallToolResult 객체를 반환해야 합니다:
{
content: Array<
| { type: 'text'; text: string }
| { type: 'image'; data: string; mimeType: string }
| { type: 'resource'; uri: string; mimeType?: string; text?: string }
>;
isError?: boolean;
}createSdkMcpServer(options)
SDK 내장 MCP 서버 인스턴스를 생성합니다.
| 옵션 | 타입 | 기본값 | 설명 |
|---|---|---|---|
name | string | 필수 | MCP 서버의 고유 이름 |
version | string | '1.0.0' | 서버 버전 |
tools | SdkMcpToolDefinition[] | - | tool()로 생성된 도구의 배열 |
mcpServers 옵션에 직접 전달할 수 있는 McpSdkServerConfigWithInstance 객체를 반환합니다.
예시
import { z } from 'zod';
import { query, tool, createSdkMcpServer } from '@qwen-code/sdk';
// Zod 스키마로 도구 정의
const calculatorTool = tool(
'calculate_sum',
'Add two numbers',
{ a: z.number(), b: z.number() },
async (args) => ({
content: [{ type: 'text', text: String(args.a + args.b) }],
}),
);
// MCP 서버 생성
const server = createSdkMcpServer({
name: 'calculator',
tools: [calculatorTool],
});
// 쿼리에서 서버 사용
const result = query({
prompt: 'What is 42 + 17?',
options: {
permissionMode: 'yolo',
mcpServers: {
calculator: server,
},
},
});
for await (const message of result) {
console.log(message);
}쿼리 중단
import { query, isAbortError } from '@qwen-code/sdk';
const abortController = new AbortController();
const result = query({
prompt: 'Long running task...',
options: {
abortController,
},
});
// 5초 후 중단
setTimeout(() => abortController.abort(), 5000);
try {
for await (const message of result) {
console.log(message);
}
} catch (error) {
if (isAbortError(error)) {
console.log('Query was aborted');
} else {
throw error;
}
}오류 처리
SDK는 중단된 쿼리를 처리하기 위한 AbortError 클래스를 제공합니다:
import { AbortError, isAbortError } from '@qwen-code/sdk';
try {
// ... 쿼리 작업
} catch (error) {
if (isAbortError(error)) {
// 중단 처리
} else {
// 다른 오류 처리
}
}