Documentation Index
Fetch the complete documentation index at: https://docs.qoder.com/llms.txt
Use this file to discover all available pages before exploring further.
Qoder Agent SDK の権限制御機能は、1 回の query() セッション内でモデルが何を実行できるかを管理します。モデルに見えるツールの制限、デフォルト認可ポリシーの設定、ツール実行前のホストアプリケーションによる承認、ユーザー承認後の新しいルールの現在のセッションへの適用などが可能です。
権限制御は単独の API ではなく、QoderAgentOptions に配置される設定の集合です。通常、まず今回のセッションでモデルが使用できるツールを決め、次にそれらのツールがどのような条件で実行可能かを決め、最後に必要に応じてランタイム承認、動的ルール更新、settings、hooks を接続します。
from qoder_agent_sdk import QoderAgentOptions, query
async for message in query(
prompt="Inspect the repository and summarize risky changes.",
options=QoderAgentOptions(
cwd="/path/to/project",
tools=["Read", "Grep", "Bash"],
allowed_tools=["Read", "Grep"],
disallowed_tools=["Bash"],
permission_mode="default",
),
):
print(message)
上記の例は一般的なポリシーを表現しています。モデルは Read、Grep、Bash を参照でき、そのうち Read と Grep は事前承認済み、Bash は実行禁止です。実際のプロジェクトでは、さらに can_use_tool を追加して、事前承認されていない操作を独自のプロダクト UI、承認システム、リスク管理サービスに委ねることができます。
機能概要
query() の権限関連 options は大きく 4 つに分類されます。1 つ目はデフォルトポリシーを決定するもので、計画モード、編集の自動許可、対話的な確認の禁止などです。2 つ目はツール範囲とツールルールを決定します。3 つ目はホストアプリケーションをランタイム承認に参加させます。4 つ目はより高度な settings、hooks、MCP ツールポリシーに使用されます。
| 解決したい課題 | 推奨エントリ | 説明 |
|---|
| セッションのデフォルト権限動作を設定 | permission_mode | 明示的なルールに該当しない場合のツール呼び出しの処理方法を決定 |
| 権限チェックのスキップを明示的に確認 | allow_dangerously_skip_permissions | bypassPermissions または yolo と組み合わせて使用 |
| 今回のセッションで参照可能なツールを制限 | tools | 含まれていないツールは利用可能ツールとしてモデルに提供されない |
| 一部のツールを事前承認 | allowed_tools | マッチ後は通常、承認確認に入らない |
| 一部のツールを禁止 | disallowed_tools | マッチ後は拒否、allow より優先 |
| ホストアプリケーションによるツール呼び出し承認 | can_use_tool | SDK ホストがランタイムで allow または deny を返す |
| 承認を外部の prompt tool に委任 | permission_prompt_tool_name | 実行環境が既に permission prompt tool を提供しているシーンに適する |
| 承認後に現在のセッションのルールを更新 | PermissionUpdate | 「今回許可」または「このセッションで常に許可」によく使われる |
| cwd 外のディレクトリへのアクセスを許可 | add_dirs | 今回のセッションでアクセス可能なディレクトリ範囲を拡張 |
| settings から権限ルールを設定 | settings | セッション開始時に静的な権限設定を提供するのに適する |
| ライフサイクルでインターセプトまたは監査 | hooks | 高度なインターセプト、監査、アラートに適する |
| MCP server にツールポリシーを宣言 | MCP tool policy | MCP server 設定でツールレベルの allow/ask/deny を宣言 |
一般的な選択方法:
- モデルにコードを読ませるだけで、変更を許可しない場合:
tools を設定し、allowed_tools で Read、Grep を事前承認、disallowed_tools で Write、Edit、Bash を禁止。
- モデルに先に計画を出力させ、実際の変更を行わせない場合:
permission_mode="plan" を使用。
- 安全な編集を自動的に通過させたい場合:
permission_mode="acceptEdits" または "auto" を使用。
- 独自の UI で承認ダイアログを表示したい場合:
can_use_tool を使用。
- ユーザーに「このセッションで常に許可」を選択させたい場合:
can_use_tool の allow 結果に updated_permissions を返す。
- 完全に対話的確認を行わず、事前承認されていないものを直接拒否したい場合:
permission_mode="dontAsk" を使用。
- monorepo 外の共有ディレクトリにアクセスしたい場合:
add_dirs を使用。
後続の例では権限設定に焦点を絞るため、メッセージのトラバーサルコードは省略しますが、実際の使用時には query() から返される非同期メッセージストリームを引き続き消費する必要があります。Python SDK はデフォルトでローカルの qodercli ログイン状態を使用できますが、アプリケーションが明示的な認証を必要とする場合は、QoderAgentOptions.auth に独自の認証設定を渡せます。
クイックスタート:ホストアプリケーションによるツール呼び出し承認
ツール呼び出しを独自の承認ロジックに接続する場合は、can_use_tool を使用します。SDK はランタイムでツール名、ツール入力パラメータ、および表示可能な承認情報をコールバックに渡します。コールバックが PermissionResultAllow を返すとツールは実行を続け、PermissionResultDeny を返すとツールは拒否されます。
from typing import Any
from qoder_agent_sdk import create_sdk_mcp_server, query, tool
from qoder_agent_sdk.types import (
PermissionResultAllow,
PermissionResultDeny,
QoderAgentOptions,
ToolPermissionContext,
)
@tool("read_order", "Read an order by ID.", {"order_id": str})
async def read_order(args: dict[str, Any]) -> dict[str, Any]:
return {"content": [{"type": "text", "text": f"order:{args['order_id']}"}]}
server = create_sdk_mcp_server(name="orders", tools=[read_order])
async def can_use_tool(
tool_name: str,
input_data: dict[str, Any],
context: ToolPermissionContext,
):
if tool_name != "mcp__orders__read_order":
return PermissionResultDeny(
message="Only order reads are allowed in this workflow."
)
return PermissionResultAllow(updated_input=input_data)
async for _ in query(
prompt="Read order 1001.",
options=QoderAgentOptions(
mcp_servers={"orders": server},
permission_mode="default",
can_use_tool=can_use_tool,
),
):
pass
この例では、read_order は SDK MCP ツールです。モデルがこれを呼び出す際、完全なツール名は mcp__orders__read_order になります。can_use_tool はこのツールのみ実行を許可し、元の入力パラメータを updated_input として返します。
デフォルトポリシーの制御:permission_mode
permission_mode はセッションのデフォルト権限ポリシーを決定します。「今回のセッション全体がどのモードか」を表現するのに適しています(例:先に計画、編集の自動受け入れ、確認なしの直接拒否、制御環境での権限チェックのスキップ)。
QoderAgentOptions(
cwd="/path/to/project",
permission_mode="plan",
)
plan モードはモデルに先に計画を出力させるのに適しており、デフォルトでは実際の変更を行いません。
| Mode | 動作 |
|---|
default | 標準の権限動作。ツール呼び出しは tools、allow/deny ルール、動的承認、ランタイムポリシーに従って処理 |
acceptEdits | ファイル編集操作を自動受け入れ。ワークスペースの変更が確認済みの場合に適する |
bypassPermissions | 権限チェックをスキップ。allow_dangerously_skip_permissions=True の同時設定が必須 |
yolo | bypassPermissions の互換エイリアス。同様に allow_dangerously_skip_permissions=True の設定が必須 |
plan | 計画モード。実行計画の出力に適し、デフォルトでは実際の変更を行わない |
dontAsk | 対話的確認を行わない。事前承認されていない、ルールで許可されていない操作は拒否される |
auto | ランタイム機能により自動的に allow または deny を判断。安全なワークスペース内ファイル編集は自動通過の可能性あり |
同一セッション内でモードを切り替える必要がある場合は、QoderSDKClient を使用できます:
from qoder_agent_sdk import QoderSDKClient
async with QoderSDKClient(
options=QoderAgentOptions(
cwd="/path/to/project",
permission_mode="plan",
)
) as client:
await client.set_permission_mode("default")
bypassPermissions と yolo はどちらも高リスクモードです。SDK は明示的に allow_dangerously_skip_permissions=True を渡すことを要求し、呼び出し側が誤って通常のセッションを権限チェックスキップのセッションに変えてしまうのを防ぎます。
QoderAgentOptions(
cwd="/path/to/project",
permission_mode="bypassPermissions",
allow_dangerously_skip_permissions=True,
)
ツール制御は「モデルがどのツールを参照でき、どのツールがデフォルトで許可または禁止か」という問題に答えます。この 3 つのフィールドは一緒に使用されることが多いですが、意味が異なります。
QoderAgentOptions(
cwd="/path/to/project",
tools=["Read", "Grep", "Bash"],
allowed_tools=["Read", "Grep"],
disallowed_tools=["Bash"],
)
この設定の意味:今回のセッションでは Read、Grep、Bash の 3 つのツールのみ提供され、Read と Grep は事前承認済み、Bash は禁止(モデルが呼び出そうとしても実行されない)。
| フィールド | 役割 | 適するシーン |
|---|
tools | 今回のセッションで利用可能なツール集合の制限 | モデルの能力境界を縮小 |
allowed_tools | 許可ルールの追加 | 低リスクツールで繰り返し承認を不要にする |
disallowed_tools | 拒否ルールの追加 | 高リスクツールの明示的禁止 |
同じツールが allow と deny の両方にマッチする場合、deny が優先されます。これにより、より広い許可ルールによって禁止ルールがバイパスされることを防ぎます。
MCP ツールも完全なツール名でマッチします。例えば SDK MCP server 名が orders、ツール名が read_order の場合、完全なツール名は mcp__orders__read_order です。
QoderAgentOptions(
mcp_servers={"orders": server},
allowed_tools=["mcp__orders__read_order"],
)
can_use_tool はホストアプリケーションが承認に参加する必要があるシーンに適しています。例えば、権限リクエストを独自の UI に表示してユーザーに「1 回許可」「このセッションで常に許可」「拒否」を選択させたい場合や、企業のリスク管理サービスを呼び出してコマンドが実行可能かを判断したい場合です。
async def can_use_tool(
tool_name: str,
input_data: dict[str, Any],
context: ToolPermissionContext,
):
show_approval_dialog(
title=context.title or tool_name,
description=context.description,
input_data=input_data,
)
approved = await wait_for_user_approval(context.signal)
if not approved:
return PermissionResultDeny(message="Rejected by user.")
return PermissionResultAllow(updated_input=input_data)
QoderAgentOptions(
cwd="/path/to/project",
permission_mode="default",
can_use_tool=can_use_tool,
)
can_use_tool のシグネチャは以下の通りです:
CanUseTool = Callable[
[str, dict[str, Any], ToolPermissionContext],
Awaitable[PermissionResult],
]
主要フィールドの説明:
| フィールド | 説明 |
|---|
tool_name | 完全なツール名(例: Read、Bash、mcp__orders__read_order) |
input_data | 今回のツール呼び出しの元のパラメータ |
context.tool_use_id | 今回のツール呼び出し ID |
context.signal | 承認リクエストがキャンセルされると設定される。UI やリモート承認はこれを監視すべき |
context.title / display_name / description | ランタイムで生成された人間が読める文言。承認 UI に直接使用可能 |
context.suggestions | ランタイムが提案する権限更新。「このセッションで常に許可」に使用可能 |
context.blocked_path | パス関連の承認シーンにおける制限されたパス |
context.decision_reason | ランタイムが提供する承認理由の説明。表示や監査に使用可能 |
context.agent_id | サブエージェントがツール呼び出しを発行した際のエージェント ID |
PermissionResultAllow を返すとツールの実行が継続されます:
return PermissionResultAllow(updated_input=input_data)
updated_input はツールが最終的に受け取るパラメータです。そのまま返すこともできますし、承認通過後にパラメータを変更することもできます。例えば、クエリにテナント ID を追加したり、パスを安全なディレクトリに書き換えたり、許可されないフィールドを削除したりできます。
PermissionResultDeny を返すとツールは拒否されます:
return PermissionResultDeny(
message="This command is not allowed in the current workspace."
)
deny.message は必須で、拒否理由の一部となり、モデル、ログ、またはホストアプリケーションに表示されます。SDK が CLI からの承認リクエストを受け取ったが can_use_tool が設定されていない場合、エラーを返し、デフォルトでは許可しません。
権限システムがツール呼び出しを直接拒否した場合、メッセージストリームに構造化された権限拒否メッセージが表示されることがあります:
from qoder_agent_sdk import SDKPermissionDeniedMessage
if isinstance(message, SDKPermissionDeniedMessage):
print(
message.tool_name,
message.tool_use_id,
message.message,
message.decision_reason,
message.decision_reason_type,
)
このタイプのメッセージは permission_mode="dontAsk"、自動拒否、ルール拒否などのシーンでよく見られます。ホストアプリケーションはこれを使って UI 状態を更新したり、監査ログを書き込んだりできます。
セッション内での権限更新:PermissionUpdate
PermissionUpdate は 1 回の承認後に現在のセッション内の権限ルールを更新するために使用します。最も一般的なシーンは、ユーザーが承認 UI で「このセッションで常に許可」を選択する場合です。この場合、ランタイムが提供する suggestions をそのまま返すことも、明示的なルールを自分で構築することもできます。
async def can_use_tool(
tool_name: str,
input_data: dict[str, Any],
context: ToolPermissionContext,
):
decision = await show_approval_dialog(
tool_name=tool_name,
suggestions=context.suggestions,
)
if decision == "always-allow-this-session":
return PermissionResultAllow(
updated_input=input_data,
updated_permissions=context.suggestions,
)
if decision == "allow-once":
return PermissionResultAllow(updated_input=input_data)
return PermissionResultDeny(message="Rejected by user.")
ルールを直接構築することもできます:
from qoder_agent_sdk.types import PermissionRuleValue, PermissionUpdate
return PermissionResultAllow(
updated_input=input_data,
updated_permissions=[
PermissionUpdate(
type="addRules",
behavior="allow",
destination="session",
rules=[PermissionRuleValue(tool_name="mcp__orders__read_order")],
)
],
)
サポートされる更新タイプ:
| タイプ | 役割 |
|---|
addRules | allow、ask、deny ルールの追加 |
replaceRules | ルールの置換 |
removeRules | ルールの削除 |
setMode | 権限モードの切り替え |
addDirectories | アクセス許可ディレクトリの追加 |
removeDirectories | ディレクトリ承認の削除 |
動的権限更新は現在のセッションに書き込むことを推奨します:
session は現在の query セッションの後続の権限チェックにのみ影響します。ローカル、プロジェクト、またはユーザーレベルの設定に永続化する必要がある場合は、単一のツール承認コールバック内の動的更新に依存するのではなく、settings 管理フローを優先的に使用してください。
追加ディレクトリへのアクセス:add_dirs
デフォルトでは、セッションは cwd を主要な作業ディレクトリとします。モデルが cwd 外のディレクトリを読み取りまたは変更する必要がある場合は、明示的に add_dirs を渡す必要があります。
QoderAgentOptions(
cwd="/repo/app",
add_dirs=["/repo/packages/shared"],
)
この設定は、セッションの主要作業ディレクトリが /repo/app であり、同時にモデルが /repo/packages/shared にアクセスすることを許可することを意味します。これは monorepo、クロスリポジトリデバッグ、共有ライブラリの調査などのシーンに適しています。
実行中に PermissionUpdate を通じてディレクトリ承認を調整することもできます:
return PermissionResultAllow(
updated_input=input_data,
updated_permissions=[
PermissionUpdate(
type="addDirectories",
destination="session",
directories=["/repo/packages/shared"],
)
],
)
ディレクトリ承認は権限境界の一部です。広範囲のディレクトリを汎用デフォルト値として add_dirs に追加しないでください。より安全なアプローチは、タスクの必要に応じて最小限のディレクトリセットを追加することです。
permission_prompt_tool_name は権限リクエストを SDK ホスト内で can_use_tool を実装する代わりに、実行環境の permission prompt tool に委任するために使用します。既存の外部承認ツール、リモート実行環境、または統一権限ゲートウェイがあるシーンに適しています。
QoderAgentOptions(
permission_prompt_tool_name="mcp__permission_server__approve",
)
使用時の注意点は 3 つあります:
permission_prompt_tool_name は現在の実行環境が認識できる prompt tool 名である必要があります。
permission_prompt_tool_name と can_use_tool は排他的であり、同時に渡すことはできません。
- SDK ホスト自体が承認を決定する場合は、
can_use_tool を優先的に使用してください。
permission prompt tool は以下の入力を受け取ります:
{
"tool_name": "mcp__orders__read_order",
"input": {"order_id": "1001"},
"tool_use_id": "toolu_...",
}
権限結果を返す必要があります:
{
"behavior": "allow",
"updatedInput": {"order_id": "1001"},
"updatedPermissions": [],
"toolUseID": "toolu_...",
}
{
"behavior": "deny",
"message": "Denied by policy.",
"interrupt": True,
"toolUseID": "toolu_...",
}
allow.updatedInput はツール実行時に使用される最終的な入力パラメータです。元の入力パラメータを保持する場合は、受け取った input をそのまま返す必要があります。deny.message は必須です。interrupt=True は拒否後に現在のエージェントフローを中断することを示します。
settings による権限ルールの提供
settings はセッション開始前に静的権限設定を提供するのに適しています。can_use_tool よりも「このプロジェクトでデフォルトで何を許可し、何を拒否し、追加ディレクトリは何か」を表現するのに適しています。
QoderAgentOptions(
cwd="/path/to/project",
settings={
"permissions": {
"allow": ["Read", "Grep"],
"deny": ["Bash"],
"ask": ["Write"],
"defaultMode": "default",
"additionalDirectories": ["/path/to/shared-lib"],
}
},
)
フィールドの説明:
| フィールド | 説明 |
|---|
permissions.allow | 許可ルール |
permissions.deny | 拒否ルール |
permissions.ask | 常に確認ルール |
permissions.defaultMode | デフォルト権限モード |
permissions.disableBypassPermissionsMode | "disable" に設定すると権限チェックスキップモードを無効化 |
permissions.additionalDirectories | 追加アクセス可能ディレクトリ |
アプリケーションが settings のデフォルト権限モードを読み取って適用する場合、高リスクモードの実行前に独自のプロダクトレベルの確認を行うことを推奨します。bypassPermissions、yolo のようなモードは、明確に信頼された環境でのみ使用すべきです。
hooks による高度なインターセプトと監査
hooks は SDK hooks 体系に既に接続しており、ツールのライフサイクルでより細かな制御を行いたい場合に適しています。can_use_tool と比較して、hooks は横断的なロジック(監査、アラート、統一インターセプト、拒否理由の記録など)により適しています。
from qoder_agent_sdk import HookMatcher
async def pre_tool_use_hook(inp, tool_use_id, context):
return {
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "Shell commands are disabled here.",
}
}
QoderAgentOptions(
cwd="/path/to/project",
hooks={
"PreToolUse": [
HookMatcher(matcher="Bash", hooks=[pre_tool_use_hook]),
],
},
)
権限関連の hook は主に 3 種類あります:
| Hook | トリガータイミング | 一般的な用途 |
|---|
PreToolUse | ツール呼び出し前 | 事前の許可、拒否、確認要求、または後続フローへの委任 |
PermissionRequest | 権限リクエスト時 | 通常の prompt 前に直接許可または拒否を返す |
PermissionDenied | 権限拒否後 | 監査、アラート、拒否理由の記録 |
PreToolUse は以下を返すことができます:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "...",
"updatedInput": {},
}
}
その中で permissionDecision は "allow"、"deny"、"ask"、"defer" を取り得ます。
PermissionRequest はツール承認に類似した権限結果を返すことができます:
{
"hookSpecificOutput": {
"hookEventName": "PermissionRequest",
"decision": {
"behavior": "deny",
"message": "Denied by policy.",
},
}
}
PermissionDenied は通常、結果を観察するために使用し、ツールの通過は担当しません。入力には拒否されたツール名、ツール入力パラメータ、ツール呼び出し ID、拒否理由が含まれます。
権限ポリシーが特定の MCP server に自然に属する場合、MCP server config にツールレベルの permission policy を直接宣言することもできます。これによりポリシーが MCP server 設定に付随し、グローバルな allowed_tools や disallowed_tools に分散することを防ぎます。
import os
QoderAgentOptions(
mcp_servers={
"repo_tools": {
"type": "http",
"url": os.environ["REPO_TOOLS_MCP_URL"],
"tools": [
{"name": "search", "permission_policy": "always_allow"},
{"name": "write_file", "permission_policy": "always_ask"},
{"name": "delete_file", "permission_policy": "always_deny"},
],
}
},
)
ポリシーの意味:
| ポリシー | 動作 |
|---|
always_allow | マッチするツールを直接許可 |
always_ask | マッチするツールは承認フローに入る |
always_deny | マッチするツールを直接拒否 |
name は MCP tool の元の名前でも完全なツール名でも指定できます(例: mcp__repo_tools__search)。実際のマッチング時、ランタイムはポリシー名を現在の MCP ツール呼び出しにマッピングします。