Claude Media
Claude Codeの--agentsが「Invalid --agents configuration」で止まる

Claude Codeの--agentsが「Invalid --agents configuration」で止まる

claude --agentsに渡したJSONが不正だとexit code 1で終了します。検査の順序、ファイル渡しの条件、resumeや--safe-modeで検査が働かない場面を解説します。

claude --agents に渡した値が不正だと、Claude Codeはセッションを始めず、Error: Invalid --agents configuration: を出して終了コード1で止まります。2行目以降に何が書かれるかは、値がどの段階で落ちたかで変わります。

この挙動はv2.1.242で入りました。それ以前は、不正な値でもセッションはそのまま起動していました。

出力の形と、検査が走る順番

エラーは次の形で出ます。1行目は固定で、<what failed> の部分が失敗の中身です。

Error: Invalid --agents configuration:
<what failed>

検査は決まった順で走り、最初に失敗した時点で止まります。2種類の問題が同居していると、先に当たった側を直すまで、後ろの問題は表示されません。

手順

--agentsの値が通る3つの関門

  1. 1

    JSONとして読めるか

    値が { で始まるのに構文エラーなら、JSONパーサーのメッセージを載せた invalid JSON: の1行が出ます。ファイルで渡した場合は、ファイルの中身が対象です。

  2. 2

    サブエージェントの定義として正しいか

    JSONとして読めても、各エージェントの定義がCLI定義サブエージェントのスキーマに合わなければ、問題ごとに1行ずつ出ます。

  3. 3

    名前が - で始まっていないか

    エージェント名が - で始まると、<name>: agent names must not start with '-' が出ます。

問題行が20行を超えるときは、先頭の20行だけが表示され、残りは …and N more にまとまります。大きな定義ファイルを一気に書くと、全部直したつもりでも次の起動で別の行が出ることがあります。

原因の切り分け

メッセージの2行目を見れば、どの関門で落ちたかが分かります。

2行目の手がかり落ちた関門見る場所
invalid JSON: で始まる落ちた関門1. JSON構文見る場所末尾のカンマ、引用符、シェルによる引用符の欠落
問題ごとに複数行落ちた関門2. スキーマ見る場所フィールド名と値の型
agent names must not start with '-'落ちた関門3. 名前見る場所トップレベルのキー

構文エラーの大半は引用符で起きる

JSONの文字列には二重引用符を使います。bashやzshでは全体を単一引用符で囲むのが基本で、公式のサンプルもそうなっています。

claude --agents '{
  "reviewer": {
    "description": "Reviews code changes",
    "prompt": "You are a careful code reviewer."
  }
}'

PowerShellでは、ヒアドキュメント形式の @' ... '@ で囲みます。公式のWindows向け例も、この形を使っています。

claude --agents @'
{
  "reviewer": {
    "description": "Reviews code changes",
    "prompt": "You are a careful code reviewer."
  }
}
'@

{ で始まらず、JSONとしても読めない値は、ファイルパスとして扱われます。シェルが引用符を食ってしまった結果、先頭が { でなくなると、構文エラーではなく別のエラーになります。これは次の節で扱います。

スキーマ違反は、フィールド名と値を表と突き合わせる

各エージェントの定義で使えるのは、prompt と、サブエージェントのfrontmatterと同じフィールドです。フィールド名はcamelCaseで書きます。型や許容値を間違えやすいものは次のとおりです。

フィールド書ける値
model書ける値sonnet、opus、haiku、fable、claude-opus-5-5 のような完全なモデルID、または inherit
permissionMode書ける値default、acceptEdits、auto、dontAsk、bypassPermissions、plan。manual は default の別名
effort書ける値low、medium、high、xhigh、max。使える段階はモデルで変わる
memory書ける値user、project、local
isolation書ける値worktree
background / omitClaudeMd書ける値true
tools / disallowedTools書ける値ツール名のカンマ区切り文字列、またはYAMLのリスト

残りのフィールドは description、mcpServers、hooks、maxTurns、skills、initialPrompt です。

permissionMode のように許容値が決まっているフィールドに表にない値を書くと、2つ目の関門で弾かれます。直した例は次のとおりです。

{
  "reviewer": {
    "description": "Reviews code changes",
    "prompt": "You are a careful code reviewer.",
    "permissionMode": "acceptEdits"
  }
}

一方、フィールド名のほうは事情が違います。color と experimental は受け付けられず、エラーにはならずに無視されます。

複数の語からなるフィールド名(maxTurns や disallowedTools)はcamelCaseで、表の綴りと完全に一致させます。認識できないフィールドはエラーを出さずに無視されるので、max_turns や maxturns と書いた定義も Invalid は出ずに通り、上限だけが効きません。エラーが出ないのに効かないフィールドがあるときは、まずキーの綴りを表と1文字ずつ見比べます。そのうえで、綴りが合っていても効かない場合は、この記事の「検査を通ったのに設定が効かないとき」の条件に当てはまっていないかを確かめます。直前まで動いていた定義がある場合は、その差分から追うと原因を絞りやすくなります。

ファイルで渡すときの条件

定義が長くなったら、JSONファイルに切り出せます。ただし条件が2つあります。

  • --print(-p)と一緒に使うこと。対話セッションでファイルパスを渡すと拒否されます
  • Claude Code v2.1.281以降であること。それ以前は、ファイルパスもインラインJSONの一部として読まれ、JSONエラーになりました
claude -p --agents ./agents.json "Review my changes"

ファイル渡しには、上のメッセージとは別の拒否文言があります。

メッセージ意味対処
Error: --agents takes a JSON object, or a file path only with --print (-p)意味対話セッションでパスを渡した対処インラインJSONにするか、-p を足す
Error: --agents file not found: <path>意味そのパスにファイルがない対処パスか引用符を確認する

2つ目は、引用符の取り違えでも出ます。先頭が { でない値、かつJSONとして読めない値は、パスと見なされるからです。

エラーの文面だけで原因を決めずに、シェルが実際に何を渡したかを先に確かめるのが近道です。

# 渡す前にJSONとして読めるか確かめる
jq . agents.json

jq がエラーを返すなら、問題は1つ目の関門にあります。jq を通るのにClaude Codeが拒否するなら、2つ目か3つ目の関門です。

検査が働かない場面

Invalid が出ないから正しい、とは限りません。次の場面では検査自体が行われないか、行われ方が違います。

例外

検査が働かない・変わる場面

  • --safe-mode / CLAUDE_CODE_SAFE_MODE

    --agents そのものが無視されます。値が不正でも、正しくても、定義は読み込まれません。safe modeはカスタムエージェントを含むカスタマイズを全部止める起動方法なので、切り分けの途中で使うと、--agents が効いていないことに気づきにくくなります。

  • --resume / --continue のインラインJSON

    インラインのJSONは検査されず、セッションは始まります。壊れた値を渡しても、エラーなしで再開できます。

  • --resume / --continue のファイル渡し

    ファイルから読んだ値は、起動のたびに検査されます。同じ--agentsでも、インラインとファイルで再開時の挙動が分かれます。

再開時にインラインJSONが素通りする点は、スクリプトに組み込むときの落とし穴になります。新規起動では必ず落ちる値でも、--resume を付けた起動ではエラーが出ないので、テストが再開側だけで走っていると壊れた定義に気づけません。定義を検証したいときは、新規起動で確かめます。

検査を通ったのに設定が効かないとき

Invalid が出ずにセッションが始まっても、書いた値がそのまま効くとは限りません。公式のフィールド説明には、効き方を狭める条件がいくつかあります。

  • effort は、セッションの努力レベルを上書きしますが、環境変数 CLAUDE_CODE_EFFORT_LEVEL には勝てません
  • permissionMode、mcpServers、hooks、initialPrompt は、プラグインのサブエージェントでは無視されます
  • omitClaudeMd は、そのエージェントがメインセッションとして動くときは無視されます
  • prompt を空にして memory も書かないエージェントを --agent で選ぶと、システムプロンプトは変わりません

どれも検査の対象外なので、エラーの有無だけでは見分けられません。

バージョンで変わる挙動

--agents まわりは、リリースごとに受け付ける範囲が広がってきました。古いClaude Codeでは、同じ値が別の結果になります。

バージョン変わったこと
v2.1.242変わったこと不正な値で終了コード1になる検査が入った。それ以前は不正でも起動した
v2.1.271変わったこと定義に omitClaudeMd を書けるようになった
v2.1.281変わったこと-p と組み合わせたファイル渡しに対応。prompt を空にすることもできるようになった

チームで古いバージョンと新しいバージョンが混在していると、同じagents.jsonが片方では通り、もう片方ではInvalidになる、という状況が起きえます。

同名の定義との優先順位

--agents で渡した定義は現在のセッションだけに効き、ディスクには保存されません。同じ名前のサブエージェントが複数の場所にあるときは、managed settings、--agents、プロジェクトの.claude/agents/、ユーザーの~/.claude/agents/、プラグインの順で、前にあるものが使われます。

試しに既存と同名のエージェントを--agentsで渡して挙動を変えるときは、managed settingsで同名の定義が配られていないかを先に確かめる必要があります。managed settingsは組織が配布する設定で、同名の定義があるとそちらが優先され、--agents の定義は使われません。配布の有無は、組織の管理者に聞くのが確実です。

スクリプトに組み込むときの事前チェック

CIや自作ラッパーで --agents を使うなら、起動前にJSONの構文だけでも確かめておくと、失敗の原因をClaude Codeの終了コードから推測せずに済みます。

#!/usr/bin/env bash
set -euo pipefail
jq -e . agents.json > /dev/null   # 構文エラーならここで止まる
claude -p --agents ./agents.json "Review my changes"

jq が確かめるのは構文だけです。スキーマの検査は、Claude Code側の2つ目の関門が行います。

直す手順

  1. 2行目を見て、どの関門で落ちたかを判断する
  2. JSONなら jq . で構文を確かめる
  3. スキーマなら、フィールド名と値を上の表と突き合わせる
  4. 1つ直したら、もう一度起動する。後ろの関門の問題は、この時点で初めて表示される
  5. 20行を超える表示は先頭だけなので、全部直してからも再確認する

CLAUDE.mdを渡さないサブエージェントを --agents で定義するときの omitClaudeMd については、omitClaudeMdの解説にまとめています。ファイルベースの定義との使い分けは、サブエージェントの総合ガイドが扱っています。

よくある質問

toolsに存在しない名前を書くとどうなりますか

tools のどの項目もツールとして解決できないと、サブエージェントは多くの場合、起動に失敗します。その場合のエラーには、解決できなかった項目の名前が載ります。これは Invalid --agents configuration とは別のエラーで、定義が検査を通ったあとの実行時に出ます。

ビルトインのExploreとPlanを止めたいだけなら

--agents ではなく、環境変数で止める方法があります。手順はCLAUDE_CODE_DISABLE_EXPLORE_PLAN_AGENTSの記事にあります。

この記事を共有:XはてブLinkedIn