Skip to Content
デベロッパーガイドTypeScript SDK

TypeScript SDK

@qwen-code/sdk

Qwen Code にプログラムからアクセスするための、最小限の実験的な TypeScript SDK です。

機能リクエストや issue / PR はお気軽に送ってください。

インストール

npm install @qwen-code/sdk

必要条件

  • Node.js >= 22.0.0
  • Qwen Code  >= 0.4.0(安定版)。SDK はデフォルトでバンドル CLI を使用します。カスタムの qwen バイナリまたは CLI バンドルを実行する必要がある場合にのみ pathToQwenExecutable を設定してください。

クイックスタート

import { query } from '@qwen-code/sdk'; // シングルターンのクエリ const result = query({ prompt: '今いるディレクトリにはどんなファイルがありますか?', 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> - 送信するプロンプト。シングルターンのクエリには文字列、マルチターンの会話には非同期イテラブルを使用します。
  • options: QueryOptions - クエリセッションの設定オプション。

QueryOptions

オプションデフォルト説明
cwdstringprocess.cwd()クエリセッションの作業ディレクトリ。ファイル操作やコマンドの実行コンテキストを決定します。
modelstring-使用する AI モデル(例: 'qwen-max''qwen-plus''qwen-turbo')。OPENAI_MODEL および QWEN_MODEL 環境変数より優先されます。
pathToQwenExecutablestringバンドル CLIQwen 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 ランタイムを強制)。未指定の場合、SDK はパッケージに同梱されたバンドル CLI を使用します。
permissionMode'default' | 'plan' | 'auto-edit' | 'auto' | 'yolo''default'ツール実行の承認を制御するパーミッションモード。詳細は パーミッションモード を参照。
canUseToolCanUseTool-ツール実行承認のためのカスタムパーミッションハンドラ。ツールが確認を必要とするときに呼び出されます。60 秒以内に応答しないと自動拒否されます。カスタムパーミッションハンドラ を参照。
envRecord<string, string>-Qwen Code プロセスに渡す環境変数。現在のプロセス環境とマージされます。
systemPromptstring | QuerySystemPromptPreset-メインセッションのシステムプロンプト設定。文字列を使用すると組み込みの Qwen Code システムプロンプトを完全に上書きし、プリセットオブジェクトを使用すると組み込みプロンプトを維持しつつ追加の指示を付け加えます。
mcpServersRecord<string, McpServerConfig>-接続する MCP(Model Context Protocol)サーバー。外部サーバー(stdio/SSE/HTTP)と SDK 組み込みサーバーをサポート。外部サーバーは commandargsurlhttpUrl などのトランスポートオプションで設定します。SDK サーバーは { type: 'sdk', name: string, instance: Server } を使用します。
abortControllerAbortController-クエリセッションをキャンセルするコントローラ。abortController.abort() を呼び出すとセッションを終了しリソースをクリーンアップします。
debugbooleanfalseデバッグモードを有効にし、CLI プロセスからの詳細ログを出力します。
maxSessionTurnsnumber-1(無制限)セッションが自動終了するまでの最大会話ターン数。整数である必要があります。1 ターンはユーザーメッセージとアシスタント応答で構成されます。
coreToolsstring[]-レガシーの coreTools / CLI --core-tools 許可リストセマンティクスを使用します。指定された場合、一致するコアツールのみがセッションに登録されます。これは組み込みツールの登録を制限する唯一の許可リスト形式のオプションであり、ツール全体の permissions.deny / excludeTools ルール(および settings.json の tools.disabled)もツールをレジストリから削除します。settings.json の permissions.allow は純粋な自動承認であり、ツールを削除・降格・非表示にすることはありません(#10075)。ツールのスキーマを初期モデルリクエストから除外するには、settings.json の tools.eager を使用します(再起動が必要、#9827)— tool_searchstructured_output、プランモードのライフサイクルツール、task_stopmcp__* および computer_use__* ツールはその許可リストの対象外であり、通常の読み込みを維持します。ツールを完全に削除するには、ツール全体の excludeTools / permissions.deny ルールを使用します — 指定子付きのルール('Bash(rm *)' など)は実行時に一致する呼び出しのみを拒否します。MCP ツールは deny ベースの削除の対象外です。パーサーバーの excludeTools / tools.disabled フィルタで非表示にします(deny は実行時にその呼び出しをブロックします)。例: ['read_file', 'edit', 'run_shell_command']
excludeToolsstring[]-settings.json の permissions.deny と同等です。除外されたツールは即座にパーミッションエラーを返します。他のすべてのパーミッション設定より最優先されます。ツール名のエイリアスとパターンマッチングをサポート: ツール名('write_file')、シェルコマンドプレフィックス('Bash(rm *)')、パスパターン('Read(.env)''Edit(/src/**)')。
allowedToolsstring[]-自動承認用の settings.json の permissions.allow と同等です。一致するツールは canUseTool コールバックをバイパスし自動的に実行されます。ツールが確認を必要とする場合にのみ適用されます。permissions.allow と同様に、これは純粋な自動承認であり、どのツールが登録されるかやどのスキーマが送信されるかには影響しません(#10075)。excludeTools と同じパターンマッチングをサポートします。例: ['Bash(git status)', 'Bash(npm test)']
authType'openai' | 'anthropic' | 'qwen-oauth' | 'gemini' | 'vertex-ai'-AI サービスの認証タイプ。指定すると、SDK は CLI に --auth-type として転送します。
agentsSubagentConfig[]-セッション中に呼び出し可能なサブエージェントの設定。サブエージェントは特定のタスクやドメインに特化した AI エージェントです。
includePartialMessagesbooleanfalsetrue に設定すると、SDK は生成中の不完全なメッセージを出力し、AI の応答をリアルタイムでストリーミングできるようにします。
resumestring-セッション ID を指定して以前のセッションを再開します。CLI の --resume フラグと同等です。
sessionIdstring-新しいセッションにセッション ID を指定します。履歴を再開せずに SDK と CLI が同じ ID を使用することを保証します。CLI の --session-id フラグと同等です。

[!note] coreTools では ReadEditBash のようなエイリアスも使用できますが、Bash(git *) のような呼び出し指定子は削除されます。coreTools はツールの登録を制限するものであり、呼び出しパターンを制限するものではありません。

タイムアウト

SDK は以下のデフォルトタイムアウトを適用します。

タイムアウトデフォルト説明
canUseTool1 分canUseTool コールバックの最大応答時間。超過するとツールリクエストは自動拒否されます。
mcpRequest1 分SDK MCP ツール呼び出しの完了までの最大時間。
controlRequest1 分initialize()setModel()setPermissionMode()getContextUsage()interrupt() などの制御操作の完了までの最大時間。
streamClose1 分マルチターンモードで SDK MCP サーバーを使用する際、CLI の stdin を閉じる前に初期化が完了するのを待つ最大時間。

これらのタイムアウトは timeout オプションでカスタマイズできます。

const q = query({ prompt: 'Your prompt', options: { timeout: { canUseTool: 60000, // 60 seconds for permission callback mcpRequest: 600000, // 10 minutes for MCP tool calls controlRequest: 60000, // 60 seconds for control requests streamClose: 15000, // 15 seconds for stream close wait }, }, });

メッセージタイプ

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: 'こんにちは', 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();

interrupt() はアクティブなターンのみをキャンセルします。非同期イテラブルプロンプトで作成されたマルチターンのクエリでは、クエリとその入力ストリームはオープンなままとなり、イテラブルからの後続のメッセージが通常通り処理されます。セッション全体を終了したい場合は、close() を使用するか、設定した AbortController をアボートしてください。

デーモンでの呼び出し元指定セッション ID

DaemonClient.createOrAttachSession は、セッション作成前に ID を永続化する必要がある呼び出し元のために、オプションの sessionId を受け付けます。

import { DaemonClient } from '@qwen-code/sdk'; const daemon = new DaemonClient({ baseUrl: 'http://127.0.0.1:4170' }); const session = await daemon.createOrAttachSession({ workspaceCwd: '/path/to/project', sessionId: '550E8400-E29B-41D4-A716-446655440000', }); console.log(session.sessionId); // 550e8400-e29b-41d4-a716-446655440000

SDK は変更を送信する前にデーモンの session_id_override ケーパビリティを要求します。REST モードでは sessionId が直接シリアライズされ、アクティブな ACP アダプタはそれを session/new._meta["qwen-code/sessionId"] にマッピングします。SDK は成功レスポンスを検証し、デーモンが異なる ID を返した場合に DaemonSessionIdProtocolError をスローします。

このオプションは常に新しいスレッドセッションを作成し、冪等なアタッチではありません。作成の結果が曖昧な場合は、既知の ID を使用して load または resume してください。オプションを省略すると、既存の create-or-attach 動作が維持されます。

実行中のセッションとの通信

@qwen-code/sdk/peer を使用すると、Qwen Code セッションではないプログラムが、同じマシン上の同じユーザーとして実行されているセッションに参加できます — ボイスフロントエンド、リレー、ビルドウォッチャーなどです。このプログラムは qwen sessions ps に表示され、agents.crossSessionMessaging が有効になっているすべてのセッションの list_agents に表示されます。これは、これらのセッションが send_message で名前でメッセージを送信できるようにする機能でもあります。このプログラムはそれらのセッションにメッセージを送信することもできます。Node でのみ動作し、Node 自体以外のものは必要ありません。

import { PeerEndpoint } from '@qwen-code/sdk/peer'; const endpoint = await PeerEndpoint.start({ name: 'voice-bridge', onMessage: (message) => console.log(`${message.fromName}: ${message.content}`), }); const [session] = await endpoint.list(); if (session) { const sent = await endpoint.send({ to: session.address, content: 'What are you working on?', }); if (sent.kind === 'sent') { const receipt = await endpoint.awaitReceipt(sent.msgId, { final: true }); console.log(receipt?.status); // delivered, denied, refused, ... } } await endpoint.close();

このようなメッセージは、セッションのユーザーが確認するために保持されます。確認なしにセッションを操作するには、qwen sessions controllers add --label voice-bridge でコントローラートークンを作成し、それをエンドポイントに提供して、それを提示すべき送信にマークを付けます。

const endpoint = await PeerEndpoint.start({ name: 'voice-bridge', controllerToken: process.env['QWEN_CONTROLLER_TOKEN'], }); await endpoint.send({ to: 'my-app-3f', content: 'run the tests', controller: true, });

注意すべき点:

  • セッションは、agents.crossSessionMessaging 設定がオンの間のみ受信トレイを持ちます。この設定はデフォルトでオフです。これがないと、セッションは list() に表示されず、セッション自身の list_agentssend_message もプログラムを見たり到達したりできません。qwen sessions ps はこの設定に関係なくプログラムをリストします。
  • メッセージが確認なしに配信されるのは正確に2つのケースです。送信がコントローラートークンを提示する場合(controller: true)、または fromMode が受信セッション自身のレビュークラスを指定している場合です。fromMode は何も認証しない主張なので、コーディングセッションではないプログラムはそれを省略する必要があります。レコード内の何も — kindname も — 配信を保証しません。受信セッションの agents.crossSessionInbound 設定が両方より優先されます。そこでの hold または refuse はコントローラートークンより優先されます。
  • セッションを操作するための送信のみをマークしてください。アドレスは、あなたとして実行されている任意のプログラムが書き込めるレコードから解決されるため、コントローラー送信はそのアドレスに答えるプロセスのレコードにトークンを提示します。別の peer エンドポイントへのコントローラー送信は読まれずにドロップされます。エンドポイントの受信トレイは独自のトークンのみを受け付けるためです。
  • エンドポイントの受信トレイは、Qwen Code セッションが自身の受信トレイに適用する保護のいずれも適用しません。レート制限もなく、保留もなく、最後に応答した200メッセージを超える重複ウィンドウもありません。すべてのメッセージは delivered として応答され、到着時に onMessage に渡されます。必要に応じてそこで独自の制限を適用してください。onMessage がない場合、すべてのメッセージは refused として応答されます。
  • 終了する前に close() を呼び出してください。独自のシグナルハンドラからも含みます。close せずに kill されたプロセスは、Qwen Code セッションがディレクトリをリストしてプロセスがいなくなったことを確認するまで、そのレコードを残します。
  • UNIX ドメインソケットのみ: Windows はまだサポートされていません。

レコードスキーマ、ワイヤ形式、および受信状態は Cross-Session Protocol に文書化されています。

パーミッションモード

SDK はツール実行を制御するための異なるパーミッションモードをサポートしています。

  • default: 書き込みツールは canUseTool コールバックまたは allowedTools で承認されない限り拒否されます。読み取り専用ツールは確認なしで実行されます。
  • plan: すべての書き込みツールをブロックし、AI にまず計画を提示するよう指示します。
  • auto-edit: 編集ツール(editwrite_filenotebook_edit)を自動承認し、その他のツールは確認が必要です。
  • auto: 組み込みのクラシファイアを使用して安全なツール呼び出しを自動承認し、リスクのあるものをブロックします。ポリシーによる繰り返しブロックまたはクラシファイアの障害後には手動承認フォールバックに切り替わります。
  • yolo: すべてのツールが確認なしで自動実行されます。

パーミッションの優先順位チェーン

決定の優先順位(高い順): deny > ask > allow > (デフォルト/インタラクティブモード)

最初に一致したルールが適用されます。

  1. excludeTools / permissions.deny - ツールを完全にブロック(パーミッションエラーを返す)
  2. permissions.ask - 常にユーザーの確認を要求
  3. permissionMode: 'plan' - 読み取り専用以外のすべてのツールをブロック
  4. permissionMode: 'yolo' - すべてのツールを自動承認
  5. allowedTools / permissions.allow - 一致するツールを自動承認
  6. permissionMode: 'auto' - 残りのツールのクラシファイア仲介の承認
  7. canUseTool コールバック - カスタム承認ロジック(指定された場合、許可されたツールでは呼び出されない)
  8. デフォルト動作 - 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: 'hello.txt ファイルを作成してください' }, parent_tool_use_id: null, }; // 何らかの条件やユーザー入力を待つ yield { type: 'user', session_id: 'my-session', message: { role: 'user', content: '今度はそのファイルを読み込んでください' }, 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(`${toolName} を許可しますか?`); if (userApproved) { return { behavior: 'allow', updatedInput: input }; } return { behavior: 'deny', message: 'ユーザーが操作を拒否しました' }; }; const result = query({ prompt: '新しいファイルを作成してください', options: { canUseTool, }, });

外部 MCP サーバーとの連携

import { query } from '@qwen-code/sdk'; const result = query({ prompt: 'MCP サーバーのカスタムツールを使ってください', 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: '1文で挨拶してください。', options: { systemPrompt: 'あなたは簡潔なアシスタントです。ちょうど1文で答えてください。', }, });

組み込みシステムプロンプトへの追記

import { query } from '@qwen-code/sdk'; const result = query({ prompt: '現在のディレクトリをレビューしてください。', options: { systemPrompt: { type: 'preset', preset: 'qwen_code', append: '簡潔にし、具体的な発見に焦点を当ててください。', }, }, });

SDK組み込みMCPサーバー

SDKは、toolcreateSdkMcpServerを提供し、SDKアプリケーションと同じプロセス内で動作するMCPサーバーを作成します。これは、別のサーバープロセスを実行せずに、AIにカスタムツールを公開したい場合に便利です。

tool(name, description, inputSchema, handler)

Zodスキーマの型推論を使用してツール定義を作成します。

パラメータ説明
namestringツール名(1〜64文字、英字で始まり、英数字とアンダースコア)
descriptionstringツールの動作を説明する人間が読める形式の説明
inputSchemaZodRawShapeツールの入力パラメータを定義する Zod スキーマオブジェクト
handler(args, extra) => Promise<Result>ツールを実行し、MCP コンテンツブロックを返す非同期関数

ハンドラーは以下の構造を持つ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サーバーインスタンスを作成します。

オプションデフォルト説明
namestring必須MCP サーバーの一意の名前
versionstring'1.0.0'サーバーバージョン
toolsSdkMcpToolDefinition[]-tool() で作成されたツールの配列

mcpServersオプションに直接渡すことができるMcpSdkServerConfigWithInstanceオブジェクトを返します。

import { z } from 'zod'; import { query, tool, createSdkMcpServer } from '@qwen-code/sdk'; // Zodスキーマでツールを定義 const calculatorTool = tool( 'calculate_sum', '2つの数値を加算', { 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: '長時間実行タスク...', options: { abortController, }, }); // 5秒後に中断 setTimeout(() => abortController.abort(), 5000); try { for await (const message of result) { console.log(message); } } catch (error) { if (isAbortError(error)) { console.log('クエリが中断されました'); } else { throw error; } }

エラーハンドリング

SDKは、中断されたクエリを処理するためのAbortErrorクラスを提供します:

import { AbortError, isAbortError } from '@qwen-code/sdk'; try { // ... クエリ操作 } catch (error) { if (isAbortError(error)) { // 中断の処理 } else { // その他のエラーの処理 } }
Last updated on