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

無料レッスン

LLM エージェント向けツールの設計

このレッスンのあとで: モデルが正しく使えるツールを、分かりやすい名前、示した制限、役に立つエラーで書ける。

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

ツールはモデルの説明書

エージェント向けのツールを設計するとは、モデルが正しく使えるように、名前、説明、引数、エラーを書くことです。これらの言葉が、モデルにとって唯一の説明書です。

do という名前で、曖昧なオプションが五つあるツールは、当てずっぽうで使われます。read_file という名前で、パスが一つのツールは、うまく使われます。

このレッスンのゴール

メモ

モデルが正しく使えるツールを、分かりやすい名前、示した制限、役に立つエラーで書ける。

キーワード

ことばいみ
ツールエージェントがハーネスに実行を頼める関数
説明いつツールを使うかをモデルに伝える言葉
狭いツール仕事を一つだけするツール
引数ツールが受け取る、名前の付いた入力
曖昧さ一つの作業に合いそうに見える二つのツール
ツールのエラーツールが失敗したときに返す文章

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

狭いツールは広いツールに勝つ

狭いツールは、仕事を一つだけして、引数も少ないツールです。run_anything(options) のような広いツールは、モデルに小さな言語を作らせるので、よく間違えます。

仕事ごとにツールを分けます。read_file、write_file、list_files のようにします。引数は四つ以下にします。それ以上必要なツールは、たいてい二つのツールです。

名前と説明は、使わない場面も伝える

名前は動詞と名詞にします。helper ではなく search_text です。説明は、ツールが何をするかに加えて、いつ使わないかも書きます。

この二つ目の文が、似た二つのツールを分けます。これがないと、モデルは read_file と search_text を当てずっぽうで選び、トレースを見て初めて気づきます。

確かめる欠点

欠点見た目直し方
曖昧な名前`do`、`helper`動詞と名詞にする
短い説明`いろいろします`何を読み、何を変えるかを書く
制限がない「使わないでください」がない何には向かないかを足す
引数が多すぎる五つ以上ツールを分ける

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

エラーはモデルのために書く

ツールのエラーは、モデルが次に読む入力です。だからモデルのために書きます。何がうまくいかなかったかと、次に何をするかです。

エラー: src/app.pyy にファイルがありません。list_files を呼んでから、もう一度試してください。 は、立ち直り方を伝えます。ENOENT(ファイルがないときにシステムが返す記号)だけでは伝わりません。拒否のときは、再試行しないよう書きます。そうしないと、モデルは何度も繰り返します。

よくある間違い

注意

多くの人は、ツールの言葉を自分のために、短く書きます。モデルには、それしか手がかりがありません。コードを一度も見ていない同僚に向けて、説明を書きます。

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

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' '// 応答に含まれるトークン数。なければ null。' 'function count(data, name) {' '  return data.usage && typeof data.usage[name] === \"number\" ? data.usage[name] : null;' '}' > model.js"

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

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

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' '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 || 100 }),' '      signal: AbortSignal.timeout(30000),' '    });' '    if (res.ok === false) throw new Error(\"status \" + res.status);' '    const d = await res.json();' '    return { text: d.choices[0].message.content, inTokens: count(d, \"prompt_tokens\"), outTokens: count(d, \"completion_tokens\"), recorded: false };' '  } catch (error) {' '    console.log(\"記録済みサンプル: モデルが答えませんでした (\" + error.message + \")。\");' '    return { text: sample, inTokens: null, outTokens: null, recorded: true };' '  }' '}' 'module.exports = { ask };' >> model.js"

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

ツールの点検を書く(1)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' 'const VAGUE = [\"do\", \"run\", \"handle\", \"tool\", \"helper\", \"process\", \"util\"];' 'const tools = [' '  { name: \"read_file\", description: \"ファイルのパスを受け取り、その文字を読みます。フォルダには使わないでください。\", params: [\"path\"] },' '  { name: \"search_text\", description: \"プロジェクトの全ファイルから、ある単語を含む行を探します\", params: [\"word\"] },' '  { name: \"do\", description: \"いろいろします\", params: [\"a\", \"b\", \"c\", \"d\", \"e\"] },' '];' > tools2.js"

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

ツールの点検を書く(2)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function faults(tool) {' '  const found = [];' '  if (VAGUE.includes(tool.name)) found.push(\"vague-name\");' '  if (Array.from(tool.description).length < 20) found.push(\"short-description\");' '  if (tool.description.includes(\"使わないでください\") === false) found.push(\"no-limit\");' '  if (tool.params.length > 4) found.push(\"too-many-params\");' '  return found;' '}' >> tools2.js"

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

ツールの点検を書く(3)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function errorText(e) {' '  if (e.code === \"not_found\") return \"エラー: \" + e.path + \" にファイルがありません。list_files を呼んでから、もう一度試してください。\";' '  if (e.code === \"too_big\") return \"エラー: \" + e.path + \" は \" + e.size + \" 行あり、上限は \" + e.limit + \" 行です。行の範囲を指定してください。\";' '  return \"エラー: \" + e.code + \"。再試行しないでください。\";' '}' >> tools2.js"

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

ツールの点検を書く(4)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' '  for (const t of tools) console.log(t.name + \": \" + (faults(t).join(\", \") || \"欠点なし\"));' '  console.log(errorText({ code: \"not_found\", path: \"src/app.pyy\" }));' '  console.log(errorText({ code: \"too_big\", path: \"data.csv\", size: 9000, limit: 500 }));' '  const list = tools.slice(0, 2).map(function (t) { return t.name + \": \" + t.description; }).join(\" | \");' '  const task = \"src/app.py の最初の数行を見せてください。ツールの名前だけで答えてください。\";' '  const reply = await ask([{ role: \"user\", content: \"ツール: \" + list + \" | \" + task }], \"read_file\", 10);' '  console.log(\"モデルが選んだもの: \" + reply.text);' '}' 'main();' >> tools2.js"

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

ツールの点検を実行する

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

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

呼び出しが示すこと

ラボのモデルは、ツール呼び出し機能のない、ふつうの文章で使います。そこで Run は、ツールの説明をプロンプトに貼り付けて、ツールの名前を尋ねます。言葉が説明書だと示すには、それで十分です。

点検と二つのエラーには、モデルは要りません。

出力の一例

行示すこと
read_file: 欠点なし制限のある、狭いツール
search_text: no-limitいつ使わないかを言っていない
do: vague-name, short-description, no-limit, too-many-params一つのツールに四つの欠点
エラー: src/app.pyy にファイルがありません。list_files を呼んでから、もう一度試してください。次の手順のあるエラー
エラー: data.csv は 9000 行あり、上限は 500 行です。行の範囲を指定してください。要求を減らす方法のあるエラー
モデルが選んだもの: ...たぶん read_file です。言葉は実行のたびに変わる

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

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

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