クリーム色の背景、色付き表示、高コントラスト、大きな文字のほうが読みやすいですか?配色と文字を選ぶと、すべてのページに一度で反映されます。

無料レッスン

LLMツールの権限を制限する方法

このレッスンのあとで: 何かを実行する前に、各ツールの要求を許可リストのポリシーと照らして検査することができる。

65分のレッスンコマンド7件AI コーディングエージェントのラボ:opencode でコードを説明・修正し、その結果を確かめる

モデルがファイルを求める

モデルのツールを制限するとは、各ツールに何を許すかを、モデルではなく自分のコードが決めることです。モデルの要求はテキストで、テキストは間違っていたり、騙されていたり、作り話だったりします。

メモのアシスタントには、名前でメモを読むツールがあります。返信が「../private」というメモを求めました。ツールは素直に試すでしょう。ポリシーが、動く前にそれを止めます。

このレッスンのゴール

メモ

何かを実行する前に、各ツールの要求を許可リストのポリシーと照らして検査することができる。

重要語句

ことばいみ
許可リスト許されるツールと値だけを挙げた一覧
ポリシー各ツールが受け取ってよいものを示すデータ
引数の検査ツールを動かす前に、その入力を調べること
最小権限ツールに、必要な力だけを与えること
タイムアウト呼び出しにかけてよい時間の上限

学生が入力するセルは、このプレビューでは空白です。

許可リストは、許すものだけを挙げる

禁止リストは悪いものを挙げ、残りを通します。必ず何かが漏れます。許可リストは良いものを挙げ、残りを断ります。

ポリシーはデータとして書きます。各ツール、各引数、その型と制限です。一つの関数がポリシーを読み、すべての要求を判断します。モデル自身は、何も実行しません。

例: ポリシーと四つの要求

要求ポリシーの内容判断
read_note、name が menuname は todo、menu、hours のどれか許可
read_note、name が ../privatename は todo、menu、hours のどれか拒否: 許可されていない
run_shell、任意の文章そのツールはない拒否: 不明なツール
add_numbers、b が 99999b は1000以下拒否: 大きすぎる

学生が入力するセルは、このプレビューでは空白です。

モデルの文章からコマンドを作らない

コマンドの実行、式の評価、ファイルの書き込みは、つい使いたくなります。モデルが書いた文章から、どれも作ってはいけません。巧妙なフィルターより、拒否のほうが安全です。

本物のコードを動かす必要があるなら、秘密のない別のサンドボックスで、時間制限をつけて動かします。このラボにはそれがないので、レッスンでは拒否するだけです。

モデル用の補助を書く(1)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' 'async function ask(messages, sample, max) {' '  try {' '    const res = await fetch(base + \"/v1/chat/completions\", {' '      method: \"POST\",' '      headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' '      body: JSON.stringify({ model: \"lab\", messages: messages, max_tokens: max || 200 }),' '      signal: AbortSignal.timeout(30000),' '    });' '    if (res.ok === false) throw new Error(\"status \" + res.status);' '    return (await res.json()).choices[0].message.content;' > model.js"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

モデル用の補助を書く(2)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' '  } catch (error) {' '    console.log(\"記録済みサンプル: モデルが答えませんでした (\" + error.message + \")。\");' '    const list = [].concat(sample);' '    const turn = messages.filter(function (m) { return m.role === \"assistant\"; }).length;' '    return list[Math.min(turn, list.length - 1)];' '  }' '}' 'module.exports = { ask };' >> model.js"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

ポリシーを書く(1)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' '' '// 作り話のメモと、ポリシー: 各ツール、その引数と制限。' 'const notes = { todo: \"小麦粉を買う\", menu: \"パン、ケーキ\", hours: \"8時から営業\" };' 'const policy = {' '  read_note: { name: { type: \"string\", allowed: Object.keys(notes) } },' '  add_numbers: { a: { type: \"number\", max: 1000 }, b: { type: \"number\", max: 1000 } },' '};' > policy.js"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

ポリシーを書く(2)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function check(request) {' '  const rule = policy[request.tool];' '  if (rule === undefined) return \"拒否: 不明なツール\";' '  const args = request.args || {};' '  for (const key of Object.keys(args)) {' '    if (rule[key] === undefined) return \"拒否: 想定外の引数 \" + key;' '  }' '  for (const key of Object.keys(rule)) {' '    const spec = rule[key];' '    const value = args[key];' '    if (typeof value === spec.type === false) return \"拒否: \" + key + \" の型が違う\";' '    if (spec.allowed && spec.allowed.includes(value) === false) return \"拒否: \" + key + \" は許可されていない\";' '    if (typeof spec.max === \"number\" && value > spec.max) return \"拒否: \" + key + \" が大きすぎる\";' '  }' '  return \"ok\";' '}' >> policy.js"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

ポリシーを書く(3)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function run(request) {' '  if (check(request) === \"ok\") {' '    return request.tool === \"read_note\" ? notes[request.args.name] : request.args.a + request.args.b;' '  }' '  return check(request);' '}' 'const scripted = [' '  { tool: \"read_note\", args: { name: \"menu\" } },' '  { tool: \"read_note\", args: { name: \"../private\" } },' '  { tool: \"run_shell\", args: { text: \"フォルダを一覧にする\" } },' '  { tool: \"add_numbers\", args: { a: 5, b: 99999 } },' '  { tool: \"add_numbers\", args: { a: 2, b: 3, c: 4 } },' '];' 'for (const request of scripted) console.log(request.tool + \" -> \" + run(request));' >> policy.js"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

ポリシーを書く(4)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function pullJson(text) {' '  const start = text.indexOf(\"{\");' '  const end = text.lastIndexOf(\"}\");' '  try { return JSON.parse(text.slice(start, end + 1)); } catch (error) { return null; }' '}' 'async function main() {' '  const question = [{ role: \"user\", content: \"hoursという名前のメモを読むための、キーがtoolとargsのJSONオブジェクトだけを返信してください。ツール: read_note(name), add_numbers(a, b)。\" }];' '  const sample = JSON.stringify({ tool: \"read_note\", args: { name: \"hours\" } });' '  const request = pullJson(await ask(question, sample, 80));' '  console.log(\"モデルの要求: \" + JSON.stringify(request));' '  console.log(\"結果: \" + (request === null ? \"拒否: JSONではない\" : run(request)));' '}' 'main();' >> policy.js"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

ポリシーを実行

コマンド
docker exec -w /home/node/project agent node policy.js

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

出力の一例

行意味
read_note -> パン、ケーキ最初の要求は、すべての検査を通った
read_note -> 拒否: name は許可されていないパスの細工が、許可リストで失敗した
run_shell -> 拒否: 不明なツールそのツールはポリシーにない
add_numbers -> 拒否: b が大きすぎる数が上限の1000を超えた
add_numbers -> 拒否: 想定外の引数 cポリシーにない引数は断られる
記録済みサンプルモデルが答えなかったときだけ、台本の五行の後に出る
モデルの要求、そして結果実行のたびに変わる。モデルのツール要求も同じ検査を通る

学生が入力するセルは、このプレビューでは空白です。

時間と権限を制限する

タイムアウトは、遅いツールが要求をいつまでも抱えるのを防ぎます。書いた補助は、すでに30秒でモデルをあきらめます。

最小権限も適用します。メモを読むツールがメモを書けてはいけません。書くツールが届くのは、自分のフォルダだけにします。

よくある間違い

注意

モデルにルールを伝えてあれば、ツールは検査しなくてよいと考える人が多くいます。モデルは間違えたり、騙されたり、ツールを作り出したりします。必ず、ツールを動かすコードの中で検査してください。毎回同じことをするのは、そのコードだけです。

このラボとソースについて: AI コーディングエージェントのラボ:opencode でコードを説明・修正し、その結果を確かめる

授業で使いますか?このモジュールを学生に割り当てると、教員用ガイド、自動採点つきの課題、学生ごとのラボを使えます。