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

無料レッスン

CI のパイプラインの中のエージェント

このレッスンのあとで: マージの前に人の承認を置いた、エージェントの段階を設計することができる。

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

CI のエージェントの段階とは

継続的インテグレーション(CI)は、リポジトリに送られた変更のたびに確認を動かします。チームは、エージェントを一つの段階として足せます。たとえば、文書の誤字を直す段階です。

パイプラインの段階は誰も見ていないので、その限度を先に書いておきます。一回の実行を限るだけでは足りません。このレッスンでは、そのまわりのパイプライン全体を設計します。

このレッスンのゴール

メモ

マージの前に人の承認を置いた、エージェントの段階を設計することができる。

キーワード

ことばいみれい
パイプライン変更のたびに順に動く段階の並び
権限段階に許されていることwrite-branch
最小の権限段階に必要な権限だけ
承認の関門人が「よい」と言わなければならない所
記録段階がしたことの書き残し

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

エージェントの段階には最小の権限

段階には、コードを読む、ブランチに書く、main ブランチに書く、チームの秘密の情報を読む、といった権限を与えられます。エージェントの段階に要るのは、読むこととブランチに書くことです。main や秘密の情報は、決して要りません。

さらに、変えてよいフォルダーと時間の上限も書きます。星印は「何でも」という意味で、限度がまったくありません。

例: エージェントの段階の権限

権限エージェントの段階理由
readありコードを読まなければならない
write-branchあり変更は自分のブランチに置く
write-mainなしmain に書くのは、人が承認したマージだけ
secretsなしプロンプトの中の秘密の情報は漏れうる
変えてよいものdocs/ だけタスクに要るフォルダー
時間の上限30 分以下行き詰まったエージェントは止まる

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

テスト、人、そしてマージ

エージェントの段階のあと、そのブランチでテストがもう一度動きます。次に人が変更を読んで承認し、そこで初めてマージが動きます。

段階は記録を残します。与えられたタスク、動かしたコマンド、変えたファイルです。一か月後に何かがおかしくなったとき、記録が何が起きたかを教えてくれます。

よくある間違い

注意

CI のエージェントは、ブランチを作るだけなので安全だと考える人が多いです。秘密の情報を読めたり、main に書けたりする段階は、害を与えることがあります。権限は最小にし、どのマージの前にもテストと人を置きましょう。

助っ人 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 { ask } = require(\"./model\");' 'const pipelines = {' '  \"文書ボット\": [' '    { name: \"checkout\", kind: \"setup\", permissions: [\"read\"] },' '    { name: \"agent\", kind: \"agent\", permissions: [\"read\", \"write-branch\"], may_change: [\"docs/\"],' '      keeps_log: true, max_minutes: 20 },' '    { name: \"tests\", kind: \"test\", permissions: [\"read\"] },' '    { name: \"merge\", kind: \"merge\", permissions: [\"write-main\"], needs_approval: true },' '  ],' '  \"自動修正\": [' '    { name: \"agent\", kind: \"agent\", permissions: [\"read\", \"write-main\", \"secrets\"], may_change: [\"*\"],' '      keeps_log: false, max_minutes: 90 },' '    { name: \"merge\", kind: \"merge\", permissions: [\"write-main\"], needs_approval: false },' '  ],' '};' > ci.js"

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

パイプラインの確認を書く(2)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function stepProblems(s) {' '  const out = [];' '  if (s.permissions.indexOf(\"write-main\") >= 0) out.push(\"main に直接書ける\");' '  if (s.permissions.indexOf(\"secrets\") >= 0) out.push(\"秘密の情報を読める\");' '  if (s.may_change.length === 0 || s.may_change.indexOf(\"*\") >= 0) out.push(\"何でも変えられる\");' '  if (s.keeps_log === false) out.push(\"記録を残さない\");' '  if (s.max_minutes > 30) out.push(\"長く動きすぎる\");' '  return out.map(function (p) { return s.name + \": \" + p; });' '}' >> ci.js"

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

パイプラインの確認を書く(3)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function problems(steps) {' '  let out = [];' '  let agent = false;' '  let tested = false;' '  steps.forEach(function (s) {' '    if (s.kind === \"agent\") { out = out.concat(stepProblems(s)); agent = true; tested = false; }' '    if (s.kind === \"test\") tested = true;' '    if (s.kind === \"merge\" && agent && tested === false) out.push(s.name + \": エージェントのあとにテストがない\");' '    if (s.kind === \"merge\" && agent && s.needs_approval === false) out.push(s.name + \": 承認がない\");' '  });' '  return out;' '}' >> ci.js"

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

パイプラインの確認を書く(4)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' '  Object.keys(pipelines).forEach(function (name) {' '    const found = problems(pipelines[name]);' '    console.log(name + \": \" + (found.length === 0 ? \"安全\" : \"危険\"));' '    found.forEach(function (p) { console.log(\"  \" + p); });' '  });' '  const q = \"短く一文で答えてください。エージェントの変更をマージする前に、人が承認するのは、なぜですか。\";' '  const sample = \"変更が何を意味するかは、テストにもエージェントにも判断できず、人なら見られるからです。\";' '  const reply = await ask([{ role: \"user\", content: q }], sample, 80);' '  console.log(\"モデル: \" + reply.text);' '}' 'main();' >> ci.js"

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

パイプラインの確認を動かす

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

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

Run の出力

行意味
文書ボット: 安全最小の権限、テスト、そして承認
自動修正: 危険その下に七つの問題が並ぶ
agent: main に直接書ける人の承認の前に main が変わる
agent: 秘密の情報を読めるプロンプトから秘密の情報が漏れうる
agent: 何でも変えられる変えてよい場所に限りがない
agent: 記録を残さないあとで何が起きたか調べられない
agent: 長く動きすぎる時間の上限 30 分を超える(90 分)
merge: エージェントのあとにテストがない変更を何も確かめない
merge: 承認がないマージの前に誰も「よい」と言わない
モデル: ...ラボからの一文。モデルが答えなければ記録済みサンプル

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

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

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