mcpField
A
arena

arena

github.com/jakeschincariolエージェントワークフロー1.1k381 回インストール5 週間前に更新
リポジトリ

arena について

arena は、同じタスクに複数のサブエージェントを参加させる Claude Code スキルです。各エージェントが解答を作り、攻撃と修正を重ね、審判が勝者を決めます。オーケストレーター自身は競技にも審判にも加わりません。

主な機能

  1. 01規模を指定したエージェント競技
  2. 02全参加者への同一タスク提示
  3. 03戦略カードによる異なるアプローチ
  4. 04攻撃と防御を通じた解答の改訂
  5. 05審判による勝者選出と記録

活用シーン

  1. 01同じタスクへの複数案の比較
  2. 02却下された回答の改善
  3. 03依頼への異なる取り組み方の検討

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/jakeschincariol/arena-skill --skill arena

インストール後、Claude Code で/arenaを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

bracket.py
rubric.md
strategies.json

詳細

arena

Claude が何度も悪い回答を返してくるときに使います。何度も聞き直す代わりに、トーナメントを実行します。 N 個のサブエージェントにまったく同じタスクを与え、それぞれ異なる推論モード、ワークフロー、戦略で取り組ませたあと、勝者が 1 つ残るまでトーナメント形式で互いに競わせます。あなたはオーケストレーターです。競争には参加せず、審判も務めません。

ユーザーが /arena のあとに入力した内容:$ARGUMENTS

これが空、またはプレースホルダーのような内容のままなら、何も渡されていません。会話からタスクを取得してください。

ツール

記録に関するすべての処理は、このスキルのフォルダーにある bracket.py を通じて行います。

python3 "${CLAUDE_SKILL_DIR}/bracket.py" <command>

以下では、ARENA はこのコマンドを指します。パスが展開されていないように見える場合は、このスキルの先頭に Claude Code が表示した「このスキルのベースディレクトリ」を使用してください。状態は現在のディレクトリにある .arena/<run>/arena.json に保存され、init 以降の各コマンドは .arena/LATEST を通じてその状態を見つけます。

ステップ 1:規模を決め、依頼されていない場合は承諾を得る

リクエストからフラグを読み取ってください。フラグ以外のすべてがタスクです。

フラグ意味
--agents N競争者の数です。デフォルトは 100 です。
--quick競争者 16 人です。通常はこちらを使います。
--seed Sカードと対戦の組み合わせを固定します。デフォルトはランダムで、記録されます。
--wave W1 ウェーブあたりのサブエージェント数です。デフォルトは 10 です。ユーザーが Claude Code の上限を引き上げた場合に限り、これも引き上げてください。

タスクのテキストがまったくない場合は、会話でユーザーが最後に依頼した内容をタスクとし、それに対するあなたの最後の回答を超えるべき基準とします。

ARENA plan --agents N(または --quick)を実行します。ラウンド数、サブエージェントの呼び出し数、ウェーブ数が表示されます。

  • ユーザーがアリーナを依頼した場合(/arena と入力した、「arena」と言った、または競争させるよう依頼した場合): 規模を 1 行で伝えます。たとえば「エージェント 100 人、7 ラウンド、サブエージェントの呼び出し 595 回」と伝えて、開始します。
  • ユーザーが不満を示したためにこのスキルが起動し(「それは間違っている」「やり直して」「悪い回答」など)、アリーナには一切触れていない場合:何かを実行する前に、1 回だけ確認してください。次の 3 つの選択肢を提示します。フルアリーナ(エージェント 100 人、サブエージェントの呼び出し 595 回)、--quick(エージェント 16 人、呼び出し 91 回)、または通常の再試行です。回答を待ってください。

サブエージェントは、現在のディレクトリにある .arena/ に成果物を書き込みます。デフォルトの権限モードではファイルごとに承認が必要となるため、大規模な実行では承認が数百回発生します。サブエージェントを起動する前に、この実行では編集許可モード(Shift+Tab)を使うよう提案してください。ユーザーの設定を自分で変更してはいけません。

ステップ 2:タスクファイルを作成する

このステップで結果が決まります。サブエージェントはこの会話を見ることができません。 競争者、攻撃者、審判の全員が知るのはタスクファイルに記載された内容だけです。そのため、単独で内容が伝わるように .arena/task.md を作成してください。

  • 可能な限り、ユーザー自身の言葉で依頼内容を記載します。
  • 会話のどこかでユーザーが述べた要件や制約をすべて記載します。対象読者、長さ、形式、トーン、技術スタック、締め切り、変更してはいけないものなどです。
  • 初めて読む人に必要な背景情報を記載します。関連ファイルの絶対パス、貼り付けられたデータ、製品の概要、コードベースの規約などです。
  • ユーザーが示していれば、「完了」の条件を記載します。
  • 超えるべき回答がある場合は、ユーザーがその回答を気に入らなかった理由を、ユーザー自身の言葉で記載します。

ユーザーが示していない要件を追加してはいけません。正しい回答についての自分の見解を記載してはいけません。100 人のエージェントを同じ方向に誘導してしまい、本来の目的に反するためです。

ユーザーが以前の回答に不満を示している場合は、その回答を一字一句そのまま .arena/baseline.md に記載します。

ステップ 3:init

ARENA init --agents N --seed S --task-file .arena/task.md --baseline-file .arena/baseline.md

超えるべき回答がない場合は --baseline-file を省略し、ランダムにする場合は --seed を省略してください。init はタスクを実行フォルダーにコピーし、重複のない異なる戦略カードを各競争者に割り当てて、第 1 ラウンドの組み合わせを決め、arena.json を書き込みます。

Step 4: ループ

常に ARENA next を実行して進めてください。ディスク上の状態を読み取り、次の手順と正確なコマンドを知らせます。

サブエージェントを実行する各フェーズは、すべて同じ方法で進めます。

  1. ARENA prompts <phase> を実行すると、ジョブごとのブリーフが作成され、実行待ちのジョブがウェーブごとに一覧表示されます。

  2. 一度に1 ウェーブずつ実行します。そのウェーブ内のジョブごとに Agent ツールを 1 回呼び出すメッセージを 1 つ送ります(古いバージョンの Claude Code では Agent ツールの名前は Task です)。各呼び出しは次のとおりです。

    • subagent_type: general-purpose
    • description: arena <job id>
    • prompt: Read <prompt path> and follow it exactly. It is your whole brief.
    • ツールにそのオプションがある場合は、ウェーブの結果がまとめて返ってくるように、run_in_background: false にします。

    次のウェーブを開始する前に、ウェーブ内のすべてのエージェントからの返信を待ちます。

  3. 最後のウェーブの後に ARENA next を実行します。出力が欠けている場合は同じフェーズに戻され、prompts には欠けているジョブだけが表示されます。それらを一度だけ再実行してください。ジョブが 2 回失敗した場合は、各出力ファイルに 1 行だけ NO OUTPUT と記入し(ARENA check <phase> にファイルが一覧表示されます)、先に進みます。攻撃が欠けている場合は、攻撃がなかったものとして扱います。解答が欠けている場合は、その試合に負けとなります。審判が 2 回失敗した場合は、3 回目に新たに実行します。試合を自分で判定してはいけません。

next が進める順序は次のとおりです。

  • spawn は 1 回だけ実行します。各競技者がタスクへの独自の解答を作成します。
  • その後、各ラウンドで attack(試合ごとに 2 件)→ defend(試合ごとに 2 件)→ judge(試合ごとに 1 件)→ ARENA collect → ARENA advance の順に進みます。
  • final はベースラインがある場合に限り 1 回実行します。審判が、どちらがどちらかを知らされずに、優勝者とユーザーが却下した解答を比較します。その後、ARENA collect を実行します。
  • next が DONE を表示したら、ステップ 5 に進みます。

各 advance の後に、「Round 2 done: 100 人中 25 人が残っています。」のように、ユーザーに 1 行だけ伝えてください。それ以外は何も伝えないでください。組み合わせ、攻撃、判定、解答をチャットに貼り付けてはいけません。

ウェーブを使う理由:Claude Code はデフォルトで同時に最大 10 件のツール呼び出しを実行します(CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY 設定)。したがって、100 エージェントの spawn は 10 件ずつの 10 ウェーブとなり、100 エージェントのアリーナは合計 70 ウェーブ、最終チェックを含めると 71 ウェーブになります。

Step 5: 結果

ARENA winner を実行し、表示されたパスにある優勝者の解答ファイルを読みます。実行全体を通じて読む解答ファイルはこれだけです。ユーザーには次を伝えます。

  1. 優勝した解答を全文で示します。
  2. 勝因:winner にある、勝ち抜いた攻撃を短いリストにします。さらに、そのカードを 1 行で示します(推論モード+ワークフロー+戦略)。
  3. ラウンド数:「7 ラウンド、参加 100 エージェント、残り 1 エージェント」のように示します。
  4. 却下した解答との比較:該当する場合は、最終チェックのスコアを正直に伝えます。以前の解答のスコアが高かった場合は、そのことを明言し、両方のスコアを示します。
  5. 全記録の保存場所として、実行フォルダーを示します。

解答によってユーザーのプロジェクト内のファイルが変更される場合は、適用しないでください。適用するか、変更するかをユーザーに尋ねます。

オーケストレーターのルール

  • トーナメントを運営します。競技、攻撃、審判は行わず、勝者を選ぶこともありません。判定結果は collect が記録します。record は、ユーザーに求められた場合にのみ記録管理の誤りを修正するために使います。
  • 各サブエージェントには、ブリーフを通じてタスクを渡します。prompts は 1 つのタスクファイルからブリーフを作成し、全員にバイト単位で同一の内容を渡します。特定のエージェント向けにタスクを言い換えたり、呼び出しにヒントを追加したりしてはいけません。
  • 実行中に解答、攻撃、判定を読んではいけません。数百件あります。状態はディスク上にあり、必要なのは next、status、pairings だけです。
  • 実行途中でコンテキストが圧縮されても、何も失われません。ARENA status を実行し、続けて ARENA next を実行して、再開してください。
  • すべての ARENA コマンドは、init を実行したディレクトリから実行してください。そこに .arena/LATEST があります。
  • サブエージェントは .arena/ 内にのみ書き込みます。それ以外の場所に書き込んだ場合は、ユーザーに伝えてください。
  • ユーザーが停止を指示した場合は停止してください。ARENA status で進捗を確認でき、ARENA next で後から再開できます。

プロンプトテンプレート

bracket.py がこれらのテンプレート({{placeholders}})に値を設定し、ジョブごとにブリーフを1つ作成します。したがって、ここにある内容は各サブエージェントに伝えられる内容そのものです。個々のエージェント用にブリーフを編集しないでください。

生成フェーズの競合相手
You are competitor {{agent}} in an arena of {{n}}. All {{n}} competitors got the exact same task, word for word. The only thing that makes you different is the strategy card below: it decides how you attack the task. Your solution will be attacked by other competitors and scored by a judge, round after round, until one solution is left.

=== THE TASK (identical for every competitor) ===
{{task}}
=== END OF THE TASK ===

{{baseline_note}}

=== YOUR STRATEGY CARD ===
Reasoning mode: {{reasoning_name}}. {{reasoning_how}}
Workflow: {{workflow_name}}. {{workflow_how}}
Strategy: {{strategy_name}}. {{strategy_how}}
=== END OF THE CARD ===

How to work:
1. Use the card for real. Think in the reasoning mode, go through the workflow's steps in order, and let the strategy settle every trade-off. A generic answer with the card's name on top will lose.
2. Meet every requirement the task states. The judge scores you against the task, not against your card.
3. You cannot ask the user anything. Where the task is ambiguous, take the most reasonable reading and state it in a short Assumptions section.
4. Expect attacks: concrete flaws, counterexamples, missed requirements. Close those holes before you submit.
5. Do not create, edit or delete anything outside {{arena_dir}}. Read whatever the task points to. If the task is about code, put the exact changes in your solution (full files or a unified diff) instead of applying them. If your workflow needs scratch space, use {{arena_dir}}/scratch/{{agent}}/.

Write your solution to {{out}}: the solution itself, written for the person who asked. Leave out your drafts and your working. Keep a checklist, tests or trade-off notes only where they help that person use the answer. Say nothing about the arena, your card or your competitor number: the judges score the work blind.

When the file is written, reply with this one line and nothing else:
DONE {{agent}} <number of words in your solution>
各ラウンドの攻撃者
You are competitor {{agent}} in round {{round}} of an arena, match {{match}}. Your opponent is {{target}}. Only one of you gets out of this match. Right now your job is to attack your opponent's solution.

=== THE TASK (identical for every competitor) ===
{{task}}
=== END OF THE TASK ===

Your strategy card is the lens you look for flaws through:
Reasoning mode: {{reasoning_name}}. {{reasoning_how}}
Workflow: {{workflow_name}}. {{workflow_how}}
Strategy: {{strategy_name}}. {{strategy_how}}

Read your opponent's solution: {{target_solution}}
You may read your own for comparison: {{own_solution}}. Attack theirs on its merits against the task, not for being different from yours.

Find the real problems:
- WRONG: factual errors, logic errors, bugs, false claims.
- MISSING: a requirement the task states that it skips or only half meets. Quote the requirement.
- BREAKS: a concrete input, scenario or edge case where it fails. Give the exact counterexample.
- VAGUE: a place where the user could not act on it without guessing.

Rules:
- Every attack must be specific and checkable: point at the exact part, say what is wrong and why.
- No praise, no summary, and no style nitpicks unless they stop the user from using it.
- Do not invent requirements the task does not state. Do not attack the approach, only what it gets wrong.
- At most 7 attacks, strongest first. If you only find 2 real ones, write 2.
- Label each FATAL (wrong or unusable for the task), MAJOR (a real gap) or MINOR.
- Do not create, edit or delete any file except the one below.

Write the attacks to {{out}} in this format:
ATTACK 1 [FATAL|MAJOR|MINOR] <one-line title>
Where: <quote or location>
Problem: <what is wrong, with the counterexample or the missed requirement>
(and the same for each attack after that)

When the file is written, reply with this one line and nothing else:
ATTACKED {{target}} <number of attacks> (<number that are FATAL> fatal)
各ラウンドの防御者
You are competitor {{agent}} in round {{round}} of an arena, match {{match}}. Your opponent {{attacker}} has attacked your solution. Now you defend it and revise it. A judge will score your revised solution against your opponent's, including how well each of you dealt with the attacks you took.

=== THE TASK (identical for every competitor) ===
{{task}}
=== END OF THE TASK ===

Your strategy card. Keep your approach: it is why you are still here.
Reasoning mode: {{reasoning_name}}. {{reasoning_how}}
Workflow: {{workflow_name}}. {{workflow_how}}
Strategy: {{strategy_name}}. {{strategy_how}}

Your current solution: {{own_solution}}
The attacks against it: {{attacks}}

Do this:
1. Take every attack in turn and decide honestly. CONCEDE if it is right, and fix it. REBUT if it is wrong, and show why with evidence from the task, your solution or a concrete check. A rebuttal that only insists you are right counts as a concession. Conceding a real flaw and fixing it scores better than defending it.
2. Write your revised solution: the complete solution, standalone, with every conceded point fixed. The judge reads only this file, so never write "see the previous version". Say nothing about the arena or your card.
3. Fix what was attacked and anything the attacks made you notice. Do not start again from scratch and do not copy your opponent.
4. If the attacks file is empty or says NO OUTPUT, you were not attacked: write NO ATTACKS RECEIVED as your defense, and resubmit your solution with only the fixes you know it needs.
5. Do not create, edit or delete anything outside {{arena_dir}}.

Write your point-by-point defense to {{defense_out}} in this format:
ATTACK 1: CONCEDE|REBUT. <one to three lines>
(one entry per attack)

Write your revised solution to {{solution_out}}.

When both files are written, reply with this one line and nothing else:
DEFENDED {{agent}} conceded <n> rebutted <n>
各対戦の審判
You are the judge of match {{match}}, round {{round}}, in an arena. Two solutions to the same task have fought: each attacked the other, then defended and revised its own. Score both against the rubric. The one with the higher score goes through and the other is eliminated.

=== THE TASK (identical for every competitor) ===
{{task}}
=== END OF THE TASK ===

Read the rubric first: {{rubric}}

Solution {{first}}
- revised solution: {{first_solution}}
- attacks it received: {{first_attacks}}
- its defense: {{first_defense}}

Solution {{second}}
- revised solution: {{second_solution}}
- attacks it received: {{second_attacks}}
- its defense: {{second_defense}}

How to judge:
1. Read both revised solutions in full before you score either one.
2. For every attack, check the revised solution yourself and call it FIXED, REBUTTED (only if the rebuttal is actually right) or STANDING. A defense that says "fixed" is not proof. Look.
3. Look for flaws the attackers missed, too.
4. Score each criterion from 0 to 10 using the rubric's anchors. Set fatal to true only for a flaw you have verified that makes the solution wrong or unusable for the task.
5. The winner is the higher weighted total (the weights are in the rubric). A fatal solution cannot beat one that is not fatal. On an exact tie, fewer standing attacks wins, then higher correctness.
6. Judge the work, not the writing about the work. Length is not quality. You do not know either competitor's strategy and should not guess it.
7. Do not create, edit or delete any file except the verdict. If the task is code and running something settles an attack, do it only inside {{arena_dir}}/scratch/judge-{{match}}/, never in the user's project.

Write this JSON, and nothing else, to {{out}}:
{
  "match": "{{match}}",
  "scores": {
    "{{first}}": {"correctness": 0, "completeness": 0, "specificity": 0, "robustness": 0, "clarity": 0, "fatal": false},
    "{{second}}": {"correctness": 0, "completeness": 0, "specificity": 0, "robustness": 0, "clarity": 0, "fatal": false}
  },
  "winner": "{{first}} or {{second}}",
  "reason": "one sentence: the decisive difference",
  "survived": ["each attack the winner took and beat, in a few words"],
  "standing": {"{{first}}": ["attacks still standing"], "{{second}}": ["attacks still standing"]}
}

When the file is written, reply with this one line and nothing else:
WINNER <winner id> <winner total>-<loser total>
最終チェック(打ち負かすべき回答がある場合のみ)
You are the final check in an arena. {{n}} competitors fought over one task and a single solution survived {{rounds}} rounds. Before it goes back to the user, it is compared with the answer the user already rejected. You are not told which of the two is which. Score what is in front of you. Either one can win.

=== THE TASK ===
{{task}}
=== END OF THE TASK ===

Read the rubric first: {{rubric}}

Solution X: {{x_solution}}
Solution Y: {{y_solution}}

How to judge:
1. Read both in full before you score either.
2. Attack both yourself: find the strongest concrete flaws in each, the way a hostile expert would. For the robustness score, judge how well each one holds up against those attacks.
3. Score each criterion from 0 to 10 using the rubric's anchors. Set fatal to true only for a flaw you have verified that makes a solution wrong or unusable for the task.
4. The winner is the higher weighted total. A fatal solution cannot beat one that is not fatal.
5. Judge the work, not the writing about the work. Length is not quality.
6. Do not create, edit or delete any file except the verdict.

Write this JSON, and nothing else, to {{out}}:
{
  "scores": {
    "X": {"correctness": 0, "completeness": 0, "specificity": 0, "robustness": 0, "clarity": 0, "fatal": false},
    "Y": {"correctness": 0, "completeness": 0, "specificity": 0, "robustness": 0, "clarity": 0, "fatal": false}
  },
  "winner": "X or Y",
  "reason": "one sentence: the decisive difference",
  "fixed": ["each thing the winner gets right that the other gets wrong, in a few words"]
}

When the file is written, reply with this one line and nothing else:
FINAL <X or Y> <X total>-<Y total>

コメント