concord-engine について
concord-engineは、契約と決定ログで並行するコーディングエージェントを調整し、同じ論点に対する作業者間の矛盾を防ぐツールです。モデル呼び出しではなく比較によって矛盾を検出し、スキル、MCPサーバー、CLIとして利用できます。
主な機能
- 01タスク契約の作成と検証
- 02契約の決定を追記専用ログに登録
- 03契約に基づく作業者向けブリーフの生成
- 04決定を比較し矛盾を拒否
- 05受け入れチェック、文書、コストレポートの生成
- 06CLIによる矛盾チェック
活用シーン
- 01API、クライアント、スキーマの作業を複数エージェントに分割
- 02矛盾する決定の記録時に不整合な実装を阻止
- 03CIで決定ログの矛盾を確認
- 04複数の作業者へのブリーフ作成と受け入れチェック
MCP 対応
MCPサーバーは、契約の作成と登録、作業者へのブリーフ、フリート計画、受け入れチェック、文書生成、コスト報告、決定の記録、競合の確認、状態確認のツールを提供します。決定の比較はルールに基づき、モデルを呼び出しません。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
npx -y concord-engineCONCORD_ENGINE_DIRWhere the decision log lives. Defaults to .concord-engine in the working directory. Commit it — the log is the shared contract between your agents.ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
Concord Engine
並列処理を拡張し、整合性を保ちます。
タスクを説明すると、エージェントの一群がそれを構築します。完成し、テストとドキュメントが整い、互いに矛盾しない成果物を持ち帰ります。すでに決まったことに反するのを、誰にも許していないからです。
並列エージェントの規模は、途中に人間がいる限り拡張できません。速く進めようと5つ走らせ、そのうち4つが正しくても、製品は壊れます。それを見つけられるのは、すべてを読み、全体像を把握し、すでに決着した選択を改めて説明するあなた一人だけです。
それはプロンプトの問題ではありません。エージェントには記憶があり、検証もあります。しかし、並列実行を実際に破綻させる問いには、どちらも答えられません。
この2つのエージェントは、同じ問いに対して異なる答えを出したのではないでしょうか?
Concord Engineはモデルを一切使わず、比較によってこの問題に答え、2つ目の答えが書き込まれる瞬間にそれを拒否します。
録画したものであり、描画したものではありません。brag/record.mjsは実際のCLIを実行し、その出力をそのまま記録します。brag/video.htmlは記録された内容を表示するだけです。このループでは拒否に至る流れを示しています。完全な実行では、最初に契約を作成してバインドし、4人のワーカーに概要を伝えてから進めます。
決定とは何か
ここは、過小評価されている部分です。「決定」とは変数名のことではありません。2つのエージェントがそれぞれ異なる答えを出しても、どちらも妥当であり得る問いのすべてです。そして、問題なのは問いそのものではありません。何も赤くならないことです。
| 種類 | 実例 |
|---|---|
convention | 金額は整数の最小通貨単位で扱い、浮動小数点数は使いません · タイムスタンプはUTCのISO-8601文字列です · ページネーションはカーソルベースです · 2xx以外のレスポンス本文はすべて{"error":"<message>"}です · リトライは冪等で、最大3回です · マイグレーションは、元に戻せる2段階でリリースします |
api-contract | POST /api/ordersの戻り値は200ではなく201です · テナントのスコープはヘッダーではなくパスに含めます |
enum | 注文ステータスはpending|paid|shippedです · ロールはowner|admin|memberです · Webhookイベントは固定の集合です |
schema | idはuuidで、NULL不可です · amount_centsは整数です · 論理削除にはブール値ではなくdeleted_atを使います |
naming | 識別子はuser_idです · 宛先フィールドはtargetではなくurlです |
4人のエージェントが、「エラー本文の形式はどうあるべきか」という問いに対して、それぞれ妥当な答えを実装すると、4つのテストスイートがすべて成功しても、製品は壊れます。これが問題の全体像であり、対象はルートパスよりもはるかに広範です。
防止する障害
バックエンドのワーカーとクライアントのワーカーに分かれて進める、返金機能の開発です。バックエンド側がエラー形式を決めます。一方、クライアント側はバックエンドのファイルを確認できないまま、並行して作業し、別の答えにたどり着きます。
$ concord-engine decide --unit client --kind convention \
--subject "error response body shape" \
--value 'every non-2xx body is {"code":"<slug>","detail":"<message>"}' --as client
refused this contradicts a decision already in force.
d-003 api (lead): error response body shape = every non-2xx body is {"error":"<message>"}
because: the client shows it to a person
yours: every non-2xx body is {"code":"<slug>","detail":"<message>"}
Adopt the existing value, or supersede it deliberately:
--supersedes d-003 --layer pm (an override, recorded as one)
--force (record the disagreement for `check` to surface)
上記の録画からの引用です。
エージェントは異議を唱えようとした瞬間に止められ、現在有効な決定、その決定者、理由、そして認められる2つの対処方法が伝えられます。統合時ではありません。あなたが止めるのでもありません。
実行方法は3つ
**スキルとして使う方法が、ほとんどの人にとっての使い方です。**タスクを説明すると、エージェントが一連の流れを実行します。契約を作成してバインドし、各ワーカーに概要を伝え、作業を並行して割り振り、すべての決定にゲートを設け、受け入れチェックを実行し、設計ドキュメントを作成します。
/concord-engine:concord-engine add refunds across the API, the client and the schema
/concord-engine:concord-engine migrate us off the legacy auth tables, five workers
/concord-engine:concord-engine rename the tenant concept to workspace everywhere
タスクの規模を小さくする必要はなく、ルートである必要もありません。
MCP サーバーとして使う方法なら、すでにタスクに取り組んでいるエージェントが、ワークフローを渡されなくてもゲートにアクセスできます。12個のツールを備えています。write_contract、bind_contract、brief_unit、fleet_plan、run_acceptance、generate_docs、cost_reportに加え、record_decision、binding_decisions、open_conflicts、record_attempt、statusがあります。
CLIとして使う方法は、人間とCI向けです。concord-engine checkは矛盾があればゼロ以外の終了コードを返すため、パイプラインに1行追加するだけで済みます。
これが単なるメモリーツールではない理由
| ツール | 答えられること | 答えられないこと |
|---|---|---|
| 引き継ぎ/メモリーツール | 「前のエージェントは何を知っていましたか?」 | 「この2つの意見は一致していますか?」 |
| オーケストレーターによる検証 | 「このワーカーはタスクを完了しましたか?」 | 「この2つの意見は一致していますか?」 |
| 編集競合の検出 | 「2つのエージェントが1つのファイルを編集しましたか?」 | 「この2つの意見は一致していますか?」 |
そして、これに答える明白な方法、つまり決定を文章で保存し、2つが矛盾しているかモデルに尋ねる方法は、遅く、確認のたびに呼び出しコストがかかり、間違いも多いため、人々は信頼しなくなります。誰にも信頼されない調整レイヤーは、ないより悪いものです。遅延と誤警告を、本来それらのなかったワークフローに持ち込むからです。
Concord Engine は、モデルではなく比較によって意見の一致を判定します。 決定は型付きで対象を絞っているため、矛盾は比較で判定できます。同じ対象で値が異なる場合です。決定の経路には API 呼び出しが一切なく、その経路上のいずれかのファイルがプロセスの外部にアクセスできる場合に失敗するテストと、パッケージ内のどこかのファイルがモデルを呼び出す場合に失敗する別のテストがあります。
ループ
上記のゲートは1つの器官です。v0.2 はその周りにある本体です。タスクを記述すると、それを構築するフリートは、最初のコードを書く前から1組の決定に従います。
describe a task
|
[1] CONTRACT the agent authors JSON to a published schema;
| the package validates it and stores it
v
[2] BIND the contract's decisions enter the log at PM layer,
| binding before any code exists
v
[3] BRIEF one brief per unit: its slice, the decisions it must
| honour, what it may not decide, how it will be judged
v
[4] FAN OUT the host spawns one worker per unit, each getting a
| brief and nothing else
v
[5] GATE a worker that tries to decide something contradictory
| is refused, told what is in force and who may override
v
[6] ACCEPT every acceptance criterion carries a command; the run
| is not done until all of them exit 0
v
[7] DOCS the design doc is generated from the decision log —
| what was decided, by whom, and why
v
[8] COST what the fan-out sent, in bytes
concord-engine spec --schema # the contract shape, as JSON Schema
concord-engine spec --from contract.json # validate and store it
concord-engine bind --contract add-refunds
concord-engine fleet --contract add-refunds # every brief, as JSON
concord-engine brief --contract add-refunds api # one worker's brief
concord-engine accept --contract add-refunds # run every check
concord-engine docs --contract add-refunds
concord-engine cost --contract add-refunds
すべてのループコマンドは --contract を受け取ります。MCP サーバーは同じコマンド群を write_contract、bind_contract、brief_unit、fleet_plan、run_acceptance、generate_docs、cost_report として公開します。
コントラクト
1つの JSON ドキュメントです。エージェントが作成し、パッケージがその有効性を判定します。
openSubjects は、見落とされがちですが、見落としてはいけない部分です。誰かが決定する前に対象に名前を付けることで、2人のワーカーがそれぞれ異なる名前を考え出すのを防ぎます。その問題が起きた実行については、誠実な限界を参照してください。
{
"id": "add-refunds",
"goal": "one sentence a reviewer can judge the result against",
"scope": { "in": ["..."], "out": ["..."] },
"decisions": [ // binding from t=0, at PM layer
{ "kind": "api-contract", "subject": "refund endpoint",
"value": { "method": "POST", "path": "/api/refunds", "status": 201 },
"rationale": "why this and not the alternative" }
],
"openSubjects": [ // known to need deciding, not yet decided
{ "kind": "convention", "subject": "error response body shape",
"note": "the server and the client both serialise this" }
],
"units": [ // one worker each
{ "id": "api", "goal": "...", "files": ["src/api/**"],
"mayDecide": ["convention"], // everything else must be requested
"dependsOn": [] }
],
"acceptance": [
{ "id": "a1", "statement": "refunds endpoint returns 201",
"check": "npm test -- refunds", "unit": "api" }
]
}
検証は形式的なものではありません。契約内の2つの決定が互いに矛盾する場合、存在しないユニットに依存している場合、依存関係グラフに循環がある場合、ユニットに受け入れ基準がない場合、または基準にコマンドがない場合、契約は拒否されます。これらすべてを1回の処理で検証します。往復ごとにエラーを1つずつ修正するのは、4つのエラーを見つける方法としては高くつくからです。
$ concord-engine spec --from contract.json
concord-engine: contract is not valid:
- unit "api" depends on "ui", which is not a unit in this contract
- acceptance[a1] has no check — a criterion without a command is a wish
次に bind は、契約の決定を PM レイヤーのログに記録します。そのうち1つでも、すでに有効な決定と矛盾する場合、バインドは拒否されます。新しい契約が有効な決定をひそかに上書きすることこそ、このツールが防ごうとしている問題です。
1人のワーカーに渡されるもの
ブリーフであり、会話ではありません。これは、このファイルを書いたユニットに実際に渡されたブリーフです。明記されている箇所のみ短縮し、それ以外は逐語的に引用しています。
$ concord-engine brief --contract concord-engine-v2 readme
You are one worker on "concord-engine-v2". Your unit is "readme".
GOAL
Rewrite README.md around the loop without losing the v0.1 pitch that the gate is the product.
FILES YOU OWN
README.md
Do not edit files outside this list. Another worker owns them.
DECISIONS ALREADY IN FORCE — these are not suggestions
- [convention] model calls inside the package = no file in the package may call a model or open a network connection; enforced by a test (the one defensible sentence is that agreement is decided by comparison, never by a model — if authoring moves inside the package that stops being true)
- [naming] cli flag for selecting a contract = --contract (every loop command takes it, so it has to be the same word everywhere)
... 3 more decisions in force
WHAT YOU MAY DECIDE
nothing — you write code and decide nothing
WHAT YOU MUST NOT DECIDE ALONE
naming, convention, api-contract, enum, schema
RECORD A DECISION LIKE THIS — the flags are what enforce the two lists above
concord-engine decide --contract concord-engine-v2 --unit readme \
--kind <kind> --subject "<what>" --value '<value>' --as readme --rationale "<why>"
Omitting --unit skips the check on what you may decide. Use the MCP tool
record_decision if you have it; it gates the same way.
A refusal means a decision already covers this: adopt the existing value.
Do not work around it, and do not --force it.
DONE MEANS
[a-readme] the README covers the loop and keeps the gate pitch
$ test -f README.md && grep -q 'spec --schema' README.md && grep -q 'refus' README.md && grep -q -i 'estimate' README.md
fleet はすべてのブリーフを一度に出力し、dependsOn に基づいてウェーブごとにまとめます。これにより、ホストは並列実行できるものを把握できます。
パッケージが判定すること、判定しないこと
パッケージはモデルを呼び出しません。 エージェントが作成し、ホストが起動し、パッケージは比較で判定できるすべてのことを判定します。
| モデルが作成 | パッケージが判定 | |
|---|---|---|
| コントラクトの内容 | ✅ | |
| コントラクトが正しい形式かどうか | ✅ | |
| 各ワーカーに伝える内容 | ✅ | |
| 各ワーカーが書くコード | ✅ | |
| ある決定が有効な決定と矛盾するかどうか | ✅ | |
| 受け入れ基準に合格したかどうか | ✅ | |
| 設計ドキュメントの内容 | ✅(ログから生成) |
右側の各項目は、比較、スキーマ検査、またはサブプロセスの終了コードによって判定されます。2つのテストがこの分担を保証します。決定の経路からは、いかなる手段によってもプロセスの外に出てはならず、どのファイルも、サブプロセスの起動を目的とする accept を含め、モデルにアクセスしてはなりません。
これこそが差別化要因であり、欠落ではありません。ファンアウトはループとプロンプトであり、どのオーケストレーターにもあります。フリートの決定を互いに拘束させるものはほかになく、それを信頼できる状態に保つには、モデルを経路に含めないことが必要です。
インストール
claude plugin marketplace add harsh-chandak/shadowjoin
claude plugin install concord-engine@harsh-chandak
harsh-chandak マーケットプレイスは shadowjoin リポジトリでホストされており、
2 つのツールをどちらも提供しています。最初の行は誤記ではありません。
次に作業内容を説明し、ループを実行させます。
/concord-engine:concord-engine add refunds across the API, the client and the schema
Claude Code を使わない場合:
npx concord-engine --help
使い方
リードと PM が決定します。ワーカーはコードを書きますが、何も決定しません。
# a decision, gated: --unit enforces what this unit is allowed to settle,
# and the subject must be one the contract declares
concord-engine decide --contract add-refunds --unit api \
--kind convention --subject "error response body shape" \
--value 'every non-2xx body is {"error":"<message>"}' \
--as api --rationale "the client shows it to a person"
concord-engine check # exits 1 if anything contradicts
concord-engine verify # are the decided routes actually served?
concord-engine report # how often did a conflict reach you?
契約の範囲外でも、decide は有効な決定に矛盾する決定を拒否します。ただし、--unit がないと対象ユニットの決定権限を示すものがないため、そのユニットに何を決定する権限があったかは確認できません。
verify の意味は v0.1 と同じく、ルートの検証です。受け入れ基準は accept で実行します。
比較ルールがそれぞれ異なる 5 種類があります。
| 種類 | 値 | 比較方法 |
|---|---|---|
naming | "user_id" | 完全一致 |
convention | "snake_case in payloads" | 完全一致 |
api-contract | {"method":"POST","path":"/orders","status":201} | 末尾のスラッシュとパラメーター名を無視して、構造的に比較 |
enum | ["pending","paid","shipped"] | 集合の一致 |
schema | {"field":"id","type":"uuid","nullable":false} | 構造的に比較 |
ログの保存場所
作業ディレクトリ内の .concord-engine/decisions.jsonl です。追記専用の JSON Lines 形式で、1 行に 1 つの決定を記録するため、読み取りにパーサーは必要ありません。契約はその隣の .concord-engine/contracts/ に保存されます。
コミットしてください。 このログはエージェント間の契約なので、マイグレーションと同じようにコードと一緒に持ち運ぶ必要があります。別の場所に保存するには CONCORD_ENGINE_DIR を設定するか、--dir を指定してください。CLI と MCP サーバーは同じ方法で場所を解決するため、check は常にサーバーが書き込むファイルを監査します。
誰が何を解決するか
worker vs worker -> team lead
lead vs lead -> PM
PM can't resolve -> you
裁定は階層に基づいて行われ、判断によるものではありません。PM の決定はリードの決定に優先します。これは上書きであり、対立ではありません。2 人のリードの意見が食い違った場合は PM に委ねます。2 人の PM の意見が食い違った場合は、彼らを上回る者はいないため、あなたに委ねます。
各階層での試行は 2 回までで、その後はエスカレーションされます。あなたに届くのは、両方の立場、それぞれの立場を取る人、その理由、そしてすでに試したことがまとめられたパケットです。
CONFLICT c-01fc0217 naming: user identifier in API payloads
backend-lead (lead) user_id "matches the users table column"
frontend-lead (lead) userId "matches the TypeScript style guide"
tried: proposed user_id; frontend-lead rejected, 3 call sites already public
tried: proposed an alias field; rejected as duplication
owner: you
「問題が起きました。ログを読んでください」ではありません。
誰も書かない設計ドキュメント
docs は決定ログから実行内容をレンダリングします。目標、スコープ内外の内容、適用中の各決定とその作成者・タイムスタンプ・根拠、そして作業の証明となったコマンドの一覧が含まれます。自動生成されるため、実際に決定された内容との食い違いが生じません。また、誰も書かないため、最新の状態に保つコストがかからない初めての設計ドキュメントです。
重要な数値
$ concord-engine report
47 conflicts recorded
settled without you 44
reached the PM 11
reached you 3 6.4%
他のオーケストレーターが報告するのは、起動したエージェント数、消費したトークン数、完了したタスク数です。システムが自己処理できたかどうかを報告するものはありません。10 個のエージェントを実行するほうが 1 個のエージェントを実行するより実際にコストを抑えられたかを示すのは、この数値だけです。
ファンアウトにかかったコスト
節約できるのは仕組みによるもので、トリックではありません。ワーカーが受け取るのはブリーフであり、会話ではありません。 ブリーフは、1 つのユニットの担当範囲と、それを拘束する決定だけで構成されます。小さく、一定で、実行中ずっと同じです。トランスクリプトはそのどれにも当てはまりません。
このパッケージが計測するのはバイト数です。計測できるのがバイト数だからです。このリポジトリ自身の契約(5 つのユニット、5 つの拘束力のある決定)で実行してください。リポジトリをクローンし、同じコマンドを実行すれば再現できます。
$ concord-engine cost --contract concord-engine-v2
mcp 2333 B brief vs 4132 B whole contract
skill 2470 B brief vs 4132 B whole contract
tests 2286 B brief vs 4132 B whole contract
readme 2297 B brief vs 4132 B whole contract
e2e 2214 B brief vs 4132 B whole contract
11600 B sent instead of 20660 B — 44% less
~2900 vs ~5165 tokens, ESTIMATED at 4 chars/token.
No tokenizer ships with this package; these are divisions, not counts.
出力されるトークン数はすべて推定値と明記され、前提とする文字数/トークン数も示されます。基準値は各ワーカーに渡す契約全体であり、実際のセッションではありません。実際の節約量はこれより大きくなりますが、このツールはその差を推測しません。
実例
examples/linkfold.contract.json は、この README で繰り返し引用している実行の契約です。4 人のワーカーが互いのコードを見ることなく URL 短縮サービスを構築し、正常に動作するものができました。55 件のテストに加え、3 つのユニット間で、事前に話し合うことなく合意したワイヤーフォーマットを使った実際の HTTP 往復通信も確認できました。
この契約には、元の実行で不足していた openSubjects が含まれています。そのため元の実行では、同じエラーフォーマットを別々の名前で 2 回決定してしまいました。CI はプッシュのたびに再検証します。
concord-engine spec --from examples/linkfold.contract.json
concord-engine fleet --contract linkfold
concord-engine brief --contract linkfold api
正直な制約
-
記録された内容だけがチェックされます。 リードが文章で何かを決めても、それを記録しなければ、このツールからは見えません。
-
対象は意味ではなく、表現で照合されます。 大文字と小文字、句読点、アクセント記号は正規化されるため、「User Identifier」と「user identifier」は衝突します。同じものを本当に異なる表現で記述した2人のエージェントは照合されません。これはこのツールの最も注意すべき点であり、机上の話ではありません。このループを別のプロジェクトで初めて実行した際、2人のワーカーが「error response body shape」と「api error response body」という表現でエラー形式を決め、互換性のないペイロードを選びましたが、
checkは両者を比較しなかったため、矛盾を報告しませんでした。対策は
openSubjectsです。誰かが決定する前に、契約で対象の名称を定義しておきます。するとdecide --contract <id> --unit <id>は、契約で宣言されていない対象を拒否し、代わりに宣言済みの表記を提示します。これにより、対象の同一性は推測ではなく検索で判断できます。類似性に基づいて対象を照合すればこの抜けも解消できますが、判断を意思決定の過程に持ち込むことになります。このパッケージが行わないのは、まさにそれです。残るリスクは現実にあります。
--contractを付けずに記録した決定や、--new-subjectを付けた決定は、再び表現に基づいて照合されます。 -
verifyが認識するのは、Express 形式の登録だけです。app/router/server/apiの後にメソッド呼び出しが続く形式に加え、FastAPI と Flask のデコレーターを探します。req.urlに応じて処理を切り替える素のnode:httpサーバーは、見えないルートを提供します。任意の識別子にまでパターンを広げると、cache.get("key")がルートのように見えてしまうため、範囲を絞り、検出漏れを許容しています。 -
verifyが読み取るのはリテラルのパスだけです。 プレフィックスの下にマウントされたルーターや、実行時に組み立てられるパスは、静的抽出では見えません。誤って指摘するよりも検出漏れを許容し、読み取ったファイル数を出力することで、その数が完全性を意味すると誤解されないようにしています。 -
ワーカーは起動しません。
fleetは指示書を出力し、ワーカーを起動するのはホスト側です。別のエージェント CLI をシェル経由で実行するパッケージは、そのツールの認証、レート制限、障害モードを引き継ぎ、ライブラリではなくなります。 -
契約は作成しません。 作成にはモデル呼び出しが必要であり、モデル呼び出しはパッケージの外部で行われます。
-
トークン数は数えません。 トークナイザーは同梱されていません。測定するのはバイト数であり、トークン数は換算してラベル付けします。
-
作業が完了したかどうかは検証しません。
acceptは契約に記載されたコマンドを実行します。契約に弱いコマンドが記載されていれば、そのまま通ります。 -
どの決定がより優れているかは判断しません。 2つの決定が同時には成立しないことと、誰が裁定するのかを報告します。
-
ワーカーがゲートを回避することは可能です。
--unitを付けずにdecideを実行すると、そのユニットが決定できる内容のチェックをスキップします。また、--forceを使うと、意図的に矛盾を記録できます。どちらもログに表示され、reportで件数が集計されます。ゲートは安全策であり、サンドボックスではありません。 -
種類は意図的に5つです。
dependencyは、semver 範囲の共通部分を適切に実装するまで保留されています。^1.0.0と^1.2.0を互換性がないと判定する比較器を用意するくらいなら、機能がないほうがましです。
ライセンス
MIT © Harsh N. Chandak
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。
