Advanced (更新: 2026/5/19)

Claude Code/Codexの安全なAgent Harness実装ガイド|権限・検証・ロールバックまで

AIエージェントを安全に動かす足場を、権限設定、実行計画、検証、ロールバックの4層で実装。Claude Code/Codexの実務例付き。

Claude Code/Codexの安全なAgent Harness実装ガイド|権限・検証・ロールバックまで

エージェントを強くするほど、足場の設計が重要になる

Claude CodeやCodexを使っていると、最初は「指示をうまく書けばよい」と考えがちです。小さな修正ならそれでも動きます。でも、記事投稿、デプロイ、SaaS連携、DB操作、メール送信のような仕事を任せ始めると、問題はプロンプトではなくなります。

本当に必要になるのは、AIエージェントが作業するための足場です。この記事ではそれを Agent Harness、つまり「エージェントを安全に動かす外側の仕組み」と呼びます。

既存のハーネスエンジニアリング記事では、概念とエージェント構造を中心に説明しました。今回はもう一段実務寄りにします。具体的には、Claude CodeやCodexに以下のような作業を任せるとき、どんな足場を用意すれば事故りにくいかをコード付きで整理します。

先に概念を押さえたい場合は ハーネスエンジニアリング完全ガイド から読むと理解しやすいです。事故例を先に見たい場合は Claude Code セキュリティ失敗事例 が近い内容です。知識管理まで含めて整えたい人は Claude Code x Obsidian連携 も合わせて使えます。

  • 記事を作成してデプロイする
  • SaaS APIを呼び出して情報を取得する
  • QiitaやZennのような外部サービスへ投稿する
  • ローカルファイルを編集する
  • ビルドやテストを実行する
  • 失敗したときに元へ戻す

結論から言うと、エージェントを直接「実行者」にしないほうが安定します。エージェントには計画と差分作成をさせ、実行はポリシー、検証、ログ、ロールバックを通したほうがよいです。

まずAgent Harnessを4層に分ける

Agent Harnessは大げさなフレームワークではありません。最小構成なら、次の4層を作るだけで十分です。

User request
  |
  v
Agent
  |
  v
[1] Policy layer       何を許可し、何を止めるか
[2] Plan layer         どの順番で作業するか
[3] Verification layer 実行後に何を確認するか
[4] Recovery layer     失敗時にどう戻すか
  |
  v
Files / shell / SaaS APIs / deploy

この4層がないまま自動化すると、たいてい次のどれかで詰まります。

失敗パターン起きること足りない層
権限が広すぎる.envを読んだり、危険なコマンドを実行したりするPolicy
作業順が曖昧記事はできたが翻訳やビルドを忘れるPlan
成功判定が甘いbuildは通ったが公開URLが古いままVerification
戻せない失敗後にどのファイルを戻せばよいか分からないRecovery

Claude Code公式ドキュメントでも、設定はユーザー、プロジェクト、ローカル、管理ポリシーなどのスコープで分けられ、権限ルールやhooksを組み合わせられるようになっています。詳しくは Claude Code settingsHooks reference が参考になります。

実例1: 記事投稿Agent Harness

このサイトの運用で使うなら、最初の対象は記事投稿です。AIに「1本書いて投稿して」と頼むだけだと、次の事故が起きます。

  • 既存記事と同じテーマを書いてしまう
  • 日本語だけ作って多言語版を忘れる
  • descriptionが長すぎる
  • コードブロックが壊れてスマホ表示が崩れる
  • buildは通ったが本番URLを確認しない
  • 投稿後にGitHubへpushし忘れる

これを防ぐために、記事投稿を1つのハーネスとして扱います。

input: 今日の記事を1本投稿して

1. analytics-reportで直近7日を見る
2. 既存記事と重複しないテーマを選ぶ
3. 日本語本文を作る
4. 英語・中国語を含む全ロケールを作る
5. frontmatterとslugを揃える
6. buildする
7. 公開URLを確認する
8. commit/pushする

ここで大事なのは、「手順をAIの気合いに任せない」ことです。作業前にPlan層として固定しておくと、品質のぶれが減ります。

実例2: SaaS連携Agent Harness

次はSaaS連携です。Slack、Notion、Google Drive、GitHub、Google Sheetsのようなサービスを触らせると便利ですが、同時に危険も増えます。

たとえば「問い合わせ候補企業を集めてメール文を作って」と頼む場合、エージェントがやりたいことは次のようになります。

1. Webで会社情報を探す
2. 会社名、URL、メールアドレスを保存する
3. サンプルLPを生成する
4. 営業メールを作る
5. メールを送る

でも、最初から5まで全部自動で許可してはいけません。SaaS連携では、読み取り、生成、送信を分けます。

操作自動許可理由
公開Webページの読み取りOK影響が小さい
ローカルCSVへの保存OK後で確認できる
サンプルLP生成OK公開前に確認できる
メール本文生成OK送信前に確認できる
メール送信要承認相手に届く不可逆操作

この境界を設計することがAgent Harnessです。Claude Codeの権限設定やMCP設定を使う場合も、考え方は同じです。MCPについては Connect Claude Code to tools via MCP が公式の入口になります。

Policy layer: まず許可リストを作る

最小のポリシーファイルを作ります。ここでは説明用にJSONにしています。

{
  "allowCommands": [
    "npm run build",
    "npm run test",
    "node scripts/analytics-report.mjs",
    "node scripts/content-trend-report.mjs"
  ],
  "askCommands": [
    "git push",
    "wrangler pages deploy",
    "node scripts/outreach-send-mails.mjs --send"
  ],
  "denyCommands": [
    "rm -rf",
    "git reset --hard",
    "curl * | sh",
    "npm publish"
  ],
  "protectedPaths": [
    ".env",
    ".env.local",
    "claudecode-lab-sheets-f54fc47c68f0.json",
    "outreach/generated/send-log.json"
  ]
}

Claude Codeでは.claude/settings.jsonで権限を管理できます。公式ドキュメントの例でも、permissions.allowpermissions.denyを分ける形が紹介されています。

{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "permissions": {
    "allow": [
      "Bash(npm run build)",
      "Bash(npm run test *)",
      "Bash(node scripts/content-trend-report.mjs *)"
    ],
    "ask": [
      "Bash(git push *)",
      "Bash(wrangler pages deploy *)"
    ],
    "deny": [
      "Bash(rm -rf *)",
      "Bash(git reset --hard *)",
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./claudecode-lab-sheets-f54fc47c68f0.json)"
    ]
  }
}

ポイントは、禁止ルールを「危なそう」ではなく具体的に書くことです。rm -rfgit reset --hard、秘密鍵ファイル、サービスアカウントJSON、本番送信系コマンドは、最初から止めておくべきです。

Plan layer: エージェントに先に作業計画を出させる

次にPlan層です。これは人間向けの見た目ではなく、実行前に危険度を判定するための中間形式です。

{
  "goal": "トレンド分析から記事を1本作成して公開する",
  "steps": [
    {
      "name": "analytics",
      "command": "node scripts/content-trend-report.mjs --days 7",
      "risk": "safe"
    },
    {
      "name": "write",
      "paths": ["site/src/content/blog/*.mdx"],
      "risk": "safe"
    },
    {
      "name": "build",
      "command": "npm run build",
      "risk": "safe"
    },
    {
      "name": "deploy",
      "command": "wrangler pages deploy dist --project-name claudecode-lab",
      "risk": "ask"
    }
  ]
}

この形式にしておくと、エージェントの「やります」をそのまま信じずに、実行前レビューができます。危険な作業が混ざったら、その段階で止められます。

Verification layer: 成功判定をコードにする

よくある失敗は「buildが通ったからOK」と判断することです。記事投稿なら、最低でも次を確認します。

  • buildが通る
  • 多言語版が欠けていない
  • 公開URLがHTTP 200を返す
  • AdSenseやAnalyticsなどの重要タグが消えていない
  • スマホ幅でコードブロックが横にはみ出さない
  • CTAリンクが存在する

簡単な検証スクリプトはこう書けます。

// scripts/verify-published-page.mjs
const url = process.argv[2];

if (!url) {
  throw new Error("Usage: node scripts/verify-published-page.mjs <url>");
}

const response = await fetch(url, { redirect: "follow" });
if (!response.ok) {
  throw new Error(`Page returned ${response.status}: ${url}`);
}

const html = await response.text();
const checks = [
  ["title", /<title>.+<\/title>/i],
  ["description", /<meta name="description"/i],
  ["adsense", /ca-pub-2125588229998303/i],
  ["analytics", /G-3YR0LE68MJ/i],
  ["main content", /<article|data-pagefind-body|blog-post/i]
];

for (const [name, pattern] of checks) {
  if (!pattern.test(html)) {
    throw new Error(`Missing ${name} on ${url}`);
  }
}

console.log(`OK: ${url}`);

これは完璧な検証ではありません。でも「公開URLが404だった」「AdSenseタグを消していた」くらいの事故は防げます。Playwrightを使えば、スマホ幅のスクリーンショット確認もできます。

// scripts/check-mobile-code-blocks.mjs
import { chromium } from "playwright";

const url = process.argv[2];
const browser = await chromium.launch();
const page = await browser.newPage({ viewport: { width: 390, height: 844 } });

await page.goto(url, { waitUntil: "networkidle" });

const overflowing = await page.evaluate(() => {
  return [...document.querySelectorAll("pre, code, table")]
    .filter((el) => el.scrollWidth > el.clientWidth + 4)
    .map((el) => ({
      tag: el.tagName,
      text: el.textContent?.slice(0, 80)
    }));
});

await browser.close();

if (overflowing.length > 0) {
  console.error(JSON.stringify(overflowing, null, 2));
  process.exit(1);
}

console.log("OK: no mobile overflow");

Recovery layer: 失敗時の戻し方を先に決める

自動化で一番怖いのは、失敗そのものではありません。失敗した後に「何を戻せばよいか分からない」状態です。

記事投稿Agentなら、最低限このログを残します。

{
  "runId": "2026-05-19-article-001",
  "startedAt": "2026-05-19T07:30:00+09:00",
  "topic": "agent harness security",
  "changedFiles": [
    "site/src/content/blog/claude-code-codex-agent-harness-security.mdx",
    "site/src/content/blog-en/claude-code-codex-agent-harness-security.mdx"
  ],
  "commands": [
    "node scripts/content-trend-report.mjs --days 7",
    "npm run build",
    "wrangler pages deploy dist --project-name claudecode-lab"
  ],
  "status": "deployed"
}

Git運用なら、失敗時の基本は「どのcommitまで戻すか」を明確にすることです。ただし、作業中に他人の変更が混ざる環境では、雑にgit reset --hardを使うべきではありません。AIエージェントには、戻す対象をファイル単位で確認させるほうが安全です。

git status --short
git diff -- site/src/content/blog/target-article.mdx
git revert <bad-commit>

ロールバックも自動化したくなりますが、公開物、メール送信、DB変更のような不可逆操作は人間承認を挟むほうがよいです。

実装: 最小のNode.js Harness

ここまでの考え方を、最小のNode.jsコードに落とすとこうなります。

// scripts/agent-command-policy.mjs
const policy = {
  allow: [
    /^node scripts\/content-trend-report\.mjs( .*)?$/,
    /^npm run build$/,
    /^npm run test$/
  ],
  ask: [
    /^git push( .*)?$/,
    /^wrangler pages deploy( .*)?$/
  ],
  deny: [
    /rm -rf/,
    /git reset --hard/,
    /curl .* \| sh/,
    /npm publish/
  ]
};

export function classifyCommand(command) {
  if (policy.deny.some((rule) => rule.test(command))) return "deny";
  if (policy.allow.some((rule) => rule.test(command))) return "allow";
  if (policy.ask.some((rule) => rule.test(command))) return "ask";
  return "ask";
}
// scripts/run-agent-command.mjs
import { spawn } from "node:child_process";
import { classifyCommand } from "./agent-command-policy.mjs";

const command = process.argv.slice(2).join(" ");
const decision = classifyCommand(command);

if (!command) {
  throw new Error("Usage: node scripts/run-agent-command.mjs <command>");
}

if (decision === "deny") {
  throw new Error(`Denied by policy: ${command}`);
}

if (decision === "ask" && process.env.AGENT_APPROVED !== "1") {
  console.error(`Approval required: ${command}`);
  console.error("Run again with AGENT_APPROVED=1 only after review.");
  process.exit(2);
}

const child = spawn(command, {
  shell: true,
  stdio: "inherit"
});

child.on("exit", (code) => {
  process.exit(code ?? 1);
});

使い方はこうです。

node scripts/run-agent-command.mjs node scripts/content-trend-report.mjs --days 7

# deployのような操作は承認なしでは止まる
node scripts/run-agent-command.mjs wrangler pages deploy dist --project-name claudecode-lab

# レビュー後にだけ実行
AGENT_APPROVED=1 node scripts/run-agent-command.mjs wrangler pages deploy dist --project-name claudecode-lab

この程度の薄いラッパーでも、危険コマンドの直実行をかなり減らせます。重要なのは「AIに全部任せる」ではなく、「AIが作業しやすく、かつ暴走しにくい通路を作る」ことです。

CodexとClaude Codeで考え方は同じ

CodexとClaude Codeは体験が違います。Codexはタスク委譲やクラウド側の作業、PRレビューとの相性がよく、Claude Codeはローカルのプロジェクト文脈を読みながら対話的に直す作業に強いです。OpenAIのCodex紹介でも、コード作業を任せるAI coding partnerとして位置付けられています。

ただし、Agent Harnessの考え方は同じです。

観点Claude CodeCodex
プロジェクト指示CLAUDE.md.claude/settings.jsonAGENTS.mdやタスク指示
権限制御permissions、hooks、MCP設定sandbox、approval、作業環境
検証ローカルbuild、Playwright、hooksCI、テスト、レビュー
回復git diff、revert、ファイル単位の確認PR差分、ブランチ、レビュー

ツール選びよりも先に、足場を設計するほうが大切です。足場がない状態では、どのAIを使っても品質は安定しません。

初心者が最初に作るべき3つのルール

最初から完璧なAgent Harnessを作ろうとすると重くなります。まずは次の3つだけで十分です。

1. 秘密情報を読ませない

.env、サービスアカウントJSON、APIキー、顧客リストはdenyに入れます。必要な値は人間が環境変数として渡し、エージェントには値そのものを表示させません。

2. 外部に影響する操作はaskにする

メール送信、デプロイ、GitHub push、DB変更、SNS投稿はaskです。生成までは自動、送信は承認。この境界だけでも事故率は下がります。

3. 成功条件を文章ではなくコマンドにする

「ちゃんと確認して」では弱いです。npm run buildnode scripts/check-required-locales.mjs、Playwrightのスクリーンショット確認、公開URLのHTTP 200確認のように、コマンド化します。

まとめ: エージェント運用の品質はプロンプトではなく足場で決まる

AIエージェントの品質を上げたいとき、プロンプトを長くするだけでは限界があります。むしろ長いプロンプトは、運用が進むほど破綻しやすくなります。

実務で効くのは、次の4つです。

  • Policy: 何を許可し、何を止めるか
  • Plan: どの順番で作業するか
  • Verification: 成功を何で確認するか
  • Recovery: 失敗時にどう戻すか

Claude CodeでもCodexでも、この4層を用意すると「AIに任せる範囲」を広げやすくなります。記事投稿、SaaS連携、セキュリティチェック、デプロイのような作業ほど、Agent Harnessの効果は大きいです。

この記事で紹介した内容を実際にこのサイト運用へ当てはめると、アクセス分析でテーマを選び、多言語記事を作り、ビルドし、公開URLとAdSenseタグを確認してからpushする流れになります。今日の記事もこの流れで作成しています。次の改善では、Search Consoleのクエリデータも取り込み、PVだけでなく検索意図から記事テーマを選べるようにする予定です。

#claude-code #codex #agent-harness #security #permissions #automation
無料プレゼント

無料PDF: Claude Code はじめてのチートシート

まずは無料PDFで基本コマンドと最初の使い方をまとめて確認してください。登録後はそのままテンプレート集や導入相談にも進めます。

スパムは送りません。登録情報は厳重に管理します。

Claude Codeを仕事で使える形にしませんか?

無料PDFで基礎を固めたあと、すぐ使えるテンプレート集で試し、必要なら業務自動化や導入相談まで進められます。

Masa

この記事を書いた人

Masa

現役DX室長|Claude Code でゼロから多言語AI技術メディア運営中。実務直結の自動化、AI開発相談・研修受付中。

PR

関連書籍・参考図書

この記事のテーマに関連する書籍を楽天ブックスで探せます。

※ 当サイトは楽天市場のアフィリエイトプログラムに参加しています。上記リンクから商品をご購入いただくと、運営者に紹介料が支払われる場合があります。