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

無料レッスン

エージェントのためのコンテキストファイル

このレッスンのあとで: リポジトリでの働き方をエージェントに伝える、短いコンテキストファイルを書くことができる。

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

エージェントのコンテキストファイルとは

コンテキストファイルは、リポジトリに置く短いファイルです。コーディングエージェントは、どのタスクの前にもこれを読みます。テストの動かし方、チームの決まりごと、触ってはいけないものが書いてあります。

これがないと、エージェントはタスクのたびにプロジェクトを学び直し、残りは推測します。このレッスンでは、チームがリポジトリに置いておくこのファイルを、自分で書きます。

このレッスンのゴール

メモ

リポジトリでの働き方をエージェントに伝える、短いコンテキストファイルを書くことができる。

キーワード

ことばいみれい
コンテキストファイルエージェントがどのタスクの前にも読む、いつものメモAGENTS.md
決まりごとチームがいつも守る規則
コマンド何かを動かすために打つ一行npm run test
守るパスエージェントが変えてはいけないファイルやフォルダー
行の上限ファイルが持ってよい行の最大の数

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

コードが言えないことを書く

コードは、プログラムが何をするかを示します。チームがどう働くかは示しません。コンテキストファイルには、四つの種類の行を書きます。テストと実行のコマンド、決まりごと、守るパス、物の置き場所です。

このラボのエージェント opencode は、プロジェクトの一番上にある AGENTS.md という名前のファイルを読みます。ほかのエージェントは、別の名前のファイルを読みます。

例: 残す行と削る行

行残すか削るか理由
テストは npm run test で動かします残すエージェントが毎回使うコマンド
値段は整数の円で書く残すコードが言わない決まりごと
触らない: data/prices.json残す守るパス
この売店は 2019 年に始まった削るエージェントに要らない歴史
total はかごの合計を出す削るコードがもう言っている
API_KEY=abc123削る秘密の情報はリポジトリに入れない

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

短く、正しく、安全に

エージェントは、タスクのたびに全部の行を読みます。だから、一行ごとに時間と場所を使います。40 行のような行の上限を決めて、それを守りましょう。

もう正しくない行は、行がないより悪いです。ないコマンドは、エージェントを違う方向に送ります。移ったパスは、何も守りません。

よくある間違い

注意

コンテキストファイルが長いほど、よい仕事になると考える人が多いです。300 行目の決まりは、エージェントにも人にも見落とされやすいです。ファイルは短く保ち、中のコマンドとパスが今もあるかを確かめましょう。

助っ人 model.js を書く(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"

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

助っ人 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 data = await res.json();' '    const text = data.choices[0].message.content;' '    return { text, inTokens: count(data, \"prompt_tokens\"), outTokens: count(data, \"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 fs = require(\"fs\");' 'const { ask } = require(\"./model\");' 'const NL = String.fromCharCode(10);' 'fs.mkdirSync(\"ctx-demo/data\", { recursive: true });' 'fs.mkdirSync(\"ctx-demo/src\", { recursive: true });' 'const pkg = { name: \"shop\", scripts: { test: \"node --test\", lint: \"node lint.js\" } };' 'fs.writeFileSync(\"ctx-demo/package.json\", JSON.stringify(pkg, null, 2));' 'fs.writeFileSync(\"ctx-demo/data/prices.json\", JSON.stringify({ onigiri: 150, juice: 120 }));' 'fs.writeFileSync(\"ctx-demo/src/shop.js\", \"module.exports = {};\" + NL);' > context.js"

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

見本と確認を書く(2)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const draft = [\"# コーディングエージェントへのメモ\", \"テストは npm run test で動かします\",' '  \"書き方の確認は npm run lint で行います\", \"サイトは npm run build で作ります\",' '  \"値段は整数の円で書き、小数は使いません。\", \"触らない: data/prices.json\",' '  \"触らない: secrets/keys.txt\", \"API_KEY=abc123 はテスト用サーバーのもの\"];' 'fs.writeFileSync(\"ctx-demo/AGENTS.md\", draft.join(NL) + NL);' >> context.js"

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

見本と確認を書く(3)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const LIMIT = 40;' 'const START = \"触らない: \";' 'const lines = fs.readFileSync(\"ctx-demo/AGENTS.md\", \"utf8\").trim().split(NL);' 'const scripts = JSON.parse(fs.readFileSync(\"ctx-demo/package.json\", \"utf8\")).scripts;' 'const found = [];' 'if (lines.length > LIMIT) found.push(\"長すぎる: \" + lines.length + \" 行\");' >> context.js"

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

見本と確認を書く(4)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'lines.forEach(function (line, at) {' '  const words = line.split(\" \");' '  const i = words.indexOf(\"run\");' '  const where = (at + 1) + \" 行目: \";' '  if (i > 0 && words[i - 1] === \"npm\" && scripts[words[i + 1]] === undefined) found.push(where + words[i + 1] + \" というスクリプトはない\");' '  const path = line.slice(START.length);' '  if (line.indexOf(START) === 0 && fs.existsSync(\"ctx-demo/\" + path) === false) found.push(where + path + \" というパスはない\");' '  const low = line.toLowerCase();' '  if (line.indexOf(\"KEY=\") >= 0 || low.indexOf(\"password\") >= 0 || line.indexOf(\"パスワード\") >= 0) found.push(where + \"秘密の情報に見える\");' '});' >> context.js"

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

見本と確認を書く(5)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' '  console.log(\"AGENTS.md: \" + lines.length + \" 行、上限 \" + LIMIT);' '  found.forEach(function (one) { console.log(one); });' '  const q = \"短く一文で答えてください。エージェントのコンテキストファイルを短く保つのは、なぜですか。\";' '  const sample = \"エージェントはタスクのたびに全部の行を読むので、長いと大事な決まりが埋もれるからです。\";' '  const reply = await ask([{ role: \"user\", content: q }], sample, 80);' '  console.log(\"モデル: \" + reply.text);' '}' 'main();' >> context.js"

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

コンテキストの確認を動かす

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

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

Run の出力

行意味
AGENTS.md: 8 行、上限 40下書きは十分に短い
4 行目: build というスクリプトはないpackage.json に build のスクリプトがない
7 行目: secrets/keys.txt というパスはない守るパスが存在しない
8 行目: 秘密の情報に見える作り話の鍵で、消さなければならない
モデル: ...ラボからの一文。モデルが答えなければ記録済みサンプル

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

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

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