ブログ • AI / Agent

Claude Code はなぜ本物の AI Agent に近づくのか?Tool Use、MCP、Session、Permission から JSON Workflow まで

Claude Code が Agent に見えるのは、1 つのセッションが三つの JSON を束ねるからだ。再開できる会話、毎回の Tool Use が通る権限、起動時に読む MCP。再開は --resume、権限は settings.json、ツールは .mcp.json から来る。どれか一つ欠けると、戻った作業は同じものではない。

ツールのループ自体は Coding Agent の動き に書いた。Harness の違いは Harness の競争 にある。この記事は Claude Code だけを分ける。セッションが何を戻すか、権限モードがいつ変わるか、MCP をいつ読み直すか、自分で残すワークフロー JSON はどれか。

この記事で扱うこと:

先に押さえる点:セッションの再開は起動引数の復元ではない。会話と一部の権限モードは戻る。--mcp-config は戻らない。以下ではセッション、権限、MCP、自分のワークフロー JSON の順に分ける。

セッションが戻すもの、戻さないもの

セッションはプロジェクトディレクトリに結び付いた会話だ。公式は セッションの管理。記録は作業中にローカルへ書かれるので、終了後に戻れる。

入口 戻るもの 権限モード
claude --continue このディレクトリの直近の対話セッション全体。ツール呼び出しと結果を含む -p なしの端末では公式の表に従う。bypassPermissions と plan はそのまま戻らない
claude --resume <name> 名前でそのセッションを直接再開する 名前が一意なら直接開く。重複するとピッカーが開き、保存されたモードは戻さない
claude -p --resume 非対話の再開。スクリプト向け 新しい claude -p と同じモードになる。plan で終わったセッションが公式の四条件を満たすときだけ plan に戻る

再開では当時のモデル、有効な目標、期限前の予定タスクも戻る。バックグラウンドの Bash は戻らない。

転写の既定は JSONL で、パスは ~/.claude/projects/ の下、作業ディレクトリから作ったフォルダにある。公式は形式が変わると書いている。安定した契約にしない。安定したフィールドは別の JSON に書く。

権限モードはセッションと一緒に動く

モードはプロンプトの一文ではない。セッション中は Shift+Tab で default、acceptEdits、plan を回す。起動時は --permission-mode。長く使う既定は 権限モード の文書にある permissions.defaultMode。チャットでモード変更を頼んでも、今回の門は変わらない。

1 セッションの既定モードとルール。deny が ask より先、ask が allow より先。
{
  "permissions": {
    "defaultMode": "default",
    "allow": ["Bash(npm test *)"],
    "ask": ["Bash(git push *)"],
    "deny": ["Read(./.env)", "Read(./.env.*)"]
  }
}

ルール順は Claude Code の権限。より具体的な allow でも、すでに当たった deny は覆せない。

再開の仕方 権限モード
端末の --continue、または一意な名前の --resume。-p なし 終了時のモードを戻す。例外は bypassPermissions と plan で、新しいセッションと同じモードになる。auto はアカウントが条件を満たすときだけ戻る。
起動時のピッカー、または複数セッションに当たる名前 保存されたモードは戻さない。今回の起動で新しいセッションが使うモードで始まる。
/resume 対象セッションに保存されたモードは戻さない。今開いているセッションのモードを続ける。

ルールを承認キューと拒否の書き戻しにする方法は 権限制御の接続。この記事ではモードをセッション状態として扱い、ルールファイルは再開時に読み直す。

MCP はセッション開始時に読む

プロジェクトのサーバーはリポジトリ直下の .mcp.json にあり、セッション開始時に読む。ファイルを変えたら終了して開き直す。説明は MCP へ接続。プロジェクトのサーバーを初めて見ると承認を求める。クローンしたリポジトリは、同意なしに自分のマシンでプロセスを起動できない。

プロジェクトの MCP。サーバー名がツール名の接頭辞になる。
{
  "mcpServers": {
    "docs": {
      "type": "http",
      "url": "https://code.claude.com/docs/mcp"
    }
  }
}

ツールの完全名は mcp__docs__ のような接頭辞を付ける。権限ルールはこの完全名に合わせる。サーバー内の短い名前だけを書かない。

自分で残すワークフロー JSON

転写の JSONL は安定した契約ではない。下の文書は自分のもので、次回の再開に何を渡すかを覚える。Claude Code のリクエスト本体ではなく、CLI も読まない。

再開できるワークフロー記録。resume 配列は次回補う引数。
{
  "name": "auth-refactor",
  "cwd": "/repo/app",
  "permission_mode": "default",
  "settings": ".claude/settings.json",
  "mcp_config": ".mcp.json",
  "resume": ["--resume", "auth-refactor"],
  "last_tool": {
    "name": "mcp__docs__search",
    "decision": "allow"
  }
}

name は claude -n または /rename で付けた名前で、--resume が名前で探す。cwd は当時のプロジェクトディレクトリでなければならない。セッションはディレクトリごとに保存される。

  1. 1
    先にセッションを合わせる

    name を --resume に渡す。cwd は、どのプロジェクトディレクトリに転写があるかを決める。ディレクトリが違うと同名でも見つからない。

  2. 2
    次に権限モードを合わせる

    permission_mode を再開コマンドの --permission-mode に写す。ピッカーと /resume は古いモードを戻してくれない。

  3. 3
    最後に MCP を足す

    mcp_config がリポジトリ内のファイルを指すなら、起動時に読み直す。当時コマンドラインのファイルに頼っていたなら、そのパスを --mcp-config に入れる。

1 回の Tool Use が三つの文書をどう更新するか

1 ターンはプロンプトをもう一段書くことではない。順は固定だ。

  1. 1
    読み込む

    セッションは既存の会話を載せ、settings.json と .mcp.json を読み直す。コマンドラインの MCP は、今回渡したときだけある。

  2. 2
    呼び出しを出す

    モデルは tool_use を出す。ツールの完全名と input。MCP ツールにはサーバー接頭辞が付く。

  3. 3
    権限を通す

    deny、ask、allow の順で判定する。deny は実行しない。ask は人を待つ。allow になって初めてツールを呼ぶ。

  4. 4
    書き戻す

    結果はセッション転写へ追記する。自分のワークフロー JSON が更新するのは last_tool だけだ。転写全体はコピーしない。

次回の再開では、どのツールで止まったか、当時のモード、MCP をどのファイルから読んだかが分かる。転写そのものは Claude Code が保存する。

他の二本との分担

Coding Agent の動き Harness の競争 この記事
答える問い ツールのループが一般にどう回るか 各社の外殻がどこで違うか Claude Code のセッション再開で、三つの JSON がそれぞれ何を担うか
ここで探さないもの ツール呼び出しの総説をもう一篇 製品比較表をもう一枚 JSONL 転写を安定した API として解析すること

JSONNote でワークフロー JSON を確認する

  1. 1
    整形する

    JSON 整形 で settings.json とワークフロー記録を開く。コメントや末尾カンマは、次の起動で Settings Error になる。

  2. 2
    ワークフロー記録を検証する

    下の Schema を JSON Schema に貼る。name や cwd が無い、permission_mode が列挙外なら、再開の前に直す。

  3. 3
    権限ルールを比べる

    deny / allow を変える前後を JSON Diff で見て、deny が allow に移っていないか確認する。この変化はセッション名より見る価値がある。

ワークフロー記録の JSON Schema。permission_mode は公式のモード名を使う。
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "additionalProperties": false,
  "required": ["name", "cwd", "permission_mode", "settings", "mcp_config"],
  "properties": {
    "name": { "type": "string", "minLength": 1 },
    "cwd": { "type": "string", "minLength": 1 },
    "permission_mode": {
      "enum": ["default", "acceptEdits", "plan", "auto", "dontAsk", "bypassPermissions"]
    },
    "settings": { "type": "string", "minLength": 1 },
    "mcp_config": { "type": "string", "minLength": 1 },
    "resume": { "type": "array", "items": { "type": "string" } },
    "last_tool": {
      "type": "object",
      "required": ["name", "decision"],
      "properties": {
        "name": { "type": "string" },
        "decision": { "enum": ["allow", "deny", "ask"] }
      }
    }
  }
}

よくある質問

resume のあと MCP サーバーは残っていますか?

.mcp.json か ~/.claude.json に書いたサーバーは起動時に読み直される。--mcp-config だけで渡したものは自動では戻らない。再開時に再指定する。

権限モードは会話と一緒に戻りますか?

必ずではない。-p なしの端末 --continue、または一意な名前の --resume は公式の表に従う。bypassPermissions と plan はそのまま戻らない。ピッカーと /resume は今回の起動モードを使う。

~/.claude/projects の JSONL をワークフローとして解析してよいですか?

しない。公式は転写形式を変わる内部ファイルとしている。安定したフィールドは、この記事のワークフロー JSON に名前、ディレクトリ、モード、設定パス、直前のツール判定だけを書く。

会話の中でモデルに権限モードの切り替えを頼むと効きますか?

効かない。モードは Shift+Tab、--permission-mode、または settings の defaultMode が決める。プロンプトでは変わらない。

これは承認キューと同じものですか?

違う。ここでの permission_mode は今回のセッションの門だ。キュー、拒否の書き戻し、tool_use_id は権限制御の記事にある。両方が要る。モードは尋ねるかどうかを決め、キューは答えたあとの保存を決める。

まとめ

Claude Code が Agent に見えるのは、セッションが会話、権限モード、MCP ツールを一つの再開できる作業に束ねるからだ。会話を戻すことは起動引数を戻すことではない。JSONL 転写は CLI に任せ、自分のワークフロー JSON を残す。

結論:セッションは名前とディレクトリで特定する。ピッカーと /resume では権限モードを明示して再指定する。--mcp-config は再開のたびに付け直す。

次にすること:ワークフロー記録を検証してから、中の resume 引数でセッションを開く。

ブログへ戻る