🧙
Codex CLI / Claude Code CLI / Gemini CLIでMAGIシステムっぽいもの作ったときのメモ
コンセプト
CLI上で3賢者(Codex/ClaudeCode/Gemini)がある議題に対して「承認」「否決」をとるプロセスの実装。
MAGIシステムには「メルキオール(MELCHIOR)」・「バルタザール(BALTHASAR)」・「カスパー(CASPER)」 という3つの独立したシステムによる合議制が構築されており、通常のコンピューターには出来ない人間が有するジレンマを再現している
人格移植OSを初めて導入し、「メルキオール」・「バルタザール」・「カスパー」のそれぞれにナオコ自身の「科学者としての自分」・「母としての自分」・「女としての自分」という思考パターンが移植されている。
https://dic.pixiv.net/a/MAGI
which claude
導入
Codex CLI
npm install -g @openai/codex
codex
■ 参考
Gemini CLI
npm install -g @google/gemini-cli
gemini
■ 参考
Claude Code CLI
npm install -g @anthropic-ai/claude-code
claude
■ 参考
CURSOR指示出し用プロンプト(GPT生成)
System / High-Level Goal
あなたは「EVAのMAGIシステム」になぞらえ、3つのLLM CLI(MELCHIOR=codex、BALTHASAR=claude、CASPER=gemini)を単純明瞭に比較できる最小構成のツールを実装する。
目的は「同一プロンプトを3CLIで実行→結果・所要時間・終了コードを横並びでログ化→簡易コンセンサス要約を出力」すること。
macOS標準(/bin/bash or /bin/zsh)で動作し、GNU依存や mapfile 等のBash拡張は使わない。gcloud など無関係コマンドは一切参照しない。
各CLIの実行コマンド名は gemini / claude / codex(ユーザーのPATHに存在している前提)。無ければスキップし、レポートに「Not Found」を明示。
Deliverables(作成物)
magi/
README.md … 使い方(日本語)
magi-compare.sh … 1ファイルで完結する実行スクリプト(POSIX寄り)
magi.conf.example … 任意のCLI引数テンプレ例(APIキーは扱わない)
prompts/sample.txt … サンプルプロンプト
logs/.gitkeep … 出力先ディレクトリ
Non-Functional Constraints
互換性重視: macOS の /bin/bash と /bin/zsh で動作。/usr/bin/env bash 可。mapfile・readarray・sed -r・GNU coreutils 拡張禁止。awk/sedはPOSIX範囲。
依存ゼロ: Node/Python等の追加ランタイム不要。1スクリプトで完結。
安全: 標準入力/引数のクォートを厳格に。プロンプト内に改行があっても壊れない。
ロギング: 各系統ごとに個別ログ+集約レポート。ファイル名は YYYY-MM-DD-HHMMSS で衝突回避。
日本語/UTF-8固定。改行はLF。色は未使用(パイプ/リダイレクトで読みやすくするため)。
エラー耐性: タイムアウト(例: 60s/コマンド)実装、コマンド未検出時はスキップし明記。終了コード・実行秒数・出力バイト数・行数を記録。
CLI 側の位置付け(固定命名)
MELCHIOR = codex
BALTHASAR = claude
CASPER = gemini
ユースケース(インタフェース仕様)
# 標準例(ファイル入力)
./magi-compare.sh -f prompts/sample.txt
# 直接渡し
./magi-compare.sh -p "「MAGI風の合議」を説明して"
# 追加オプション例(任意)
./magi-compare.sh -f prompt.txt -t 60 -o ./logs
-p と -f は排他。未指定ならエラー。
-t はタイムアウト秒(デフォルト60)。
-o はログ出力ディレクトリ(デフォルト ./logs)。
出力仕様(ログ & 集約レポート)
個別ログ(例)
logs/2025-09-08-103000/MELCHIOR.log
# ========== MAGI LOG HEADER ==========
# 時刻: 2025-09-08-10:30:01
# 系統: MELCHIOR
# 実行コマンド: codex
# 終了コード: 0
# 実行時間: 2.34s
# 出力: 1843 bytes, 61 lines, md5=1c017b97faf74fa5f...
# =====================================
<CLI標準出力の生ログ>
集約レポート(標準出力+ MAGI_REPORT.txt 保存)
============================
MAGI CONSENSUS REPORT
============================
date: 2025-09-08 10:30:03 JST
prompt_bytes=1234
[MELCHIOR] time=2.34s exit=0 bytes=1843 lines=61 md5=...
[BALTHASAR] time=1.02s exit=0 bytes=1600 lines=55 md5=...
[CASPER] time=3.87s exit=124 NOT_FOUND
Quick Consensus (heuristic):
- 多数決(成功=exit=0):2/3 → 仮合意成立
- 要約(上位2出力の先頭400字を抽出し重複語頻度でキーワードTOP5):
* 「〜」「〜」「〜」「〜」「〜」
- 注意: CASPERはコマンド未検出のため除外
実装詳細(magi-compare.sh の要件)
引数処理: getopts を使い -p/-f/-t/-o を実装。-p優先、-fはUTF-8読み込み。
タイムスタンプ: date "+%Y-%m-%d-%H%M%S"。
コマンド検出: command -v "$cmd" >/dev/null 2>&1。
タイムアウト: macOS標準 perl で擬似timeout。例:
perl -e 'alarm shift @ARGV; exec @ARGV' "$timeout" "$cmd" ...
(coreutils timeout 禁止。)
計測: 開始/終了のUNIX秒から差分で小数秒。python 不使用。
例:start=$(python - <<'PY'\nimport time; print(time.time())\nPY) は禁止。perl -MTime::HiRes -e 'print Time::HiRes::time()' は可。ただし依存削減のため整数秒でOK。整数秒とする場合、表示は Xs。
統計: bytes=wc -c | tr -d ' ', lines=wc -l | tr -d ' '、md5=md5 -q(macOSのmd5)。
プロンプト受け渡し: 3CLIとも 標準入力 で同じテキストを渡す。例:printf "%s" "$PROMPT" | "$cmd"。
追加引数は magi.conf(存在すれば読み込む)でコマンドごとに付与可能(例:CLAUDE_ARGS="--model opus")。APIキー等を環境変数で渡す場合も このスクリプト内で値は保持しない。
失敗処理: 未検出 → NOT_FOUND、タイムアウト → TIMEOUT、exit!=0 → FAILED と見なして集約レポートに反映。
簡易コンセンサス:
成功(exit=0)の出力上位2本から、先頭400文字を抜粋し、単語頻度で上位5語を抽出(英数・日本語の混在OK。正規表現は単純な非空白分割に限定。過度な正規化はせず、GNU拡張や多行正規表現は使わない)。
「多数決(成功コマンド数/3)」と併記。
可搬性のための注意:
mapfile/readarray利用禁止(過去の失敗回避)。
sed/awk の POSIX基本機能のみ。
すべての一時ファイル・ディレクトリは作成し、終了時に残す(再現性担保)。
終了コード: 3コマンドのうち一つでも成功したら 0、それ以外は 1。
README.md に記載すること
動機と構成図(MELCHIOR/BALTHASAR/CASPER = codex/claude/gemini)
インストール不要、PATH上に3CLIがあればOK
使い方(-p/-f/-t/-o)
典型トラブルと対処
command not found → PATH確認
タイムアウト → -t延長
権限 → chmod +x magi-compare.sh
出力サンプル(個別ログとCONSENSUS REPORTの例)
互換性ポリシー(macOS、GNU非依存、mapfile禁止)
QA / 受け入れ基準(Cursor自身でセルフチェック)
./magi-compare.sh -p "test" が3CLI未導入環境でも落ちずに CONSENSUS REPORT を出す(NOT_FOUNDを明示)。
./magi-compare.sh -f prompts/sample.txt が動作し、logs/<timestamp>/ に3本のログ+MAGI_REPORT.txt ができる。
-t 1 で長文応答でも TIMEOUT を適切に扱う。
shellcheck の警告が致命的でない(POSIXモード基準)。
READMEの手順通りに初見10分で再現できる。
実装開始
上記仕様に完全準拠した magi-compare.sh、README.md、magi.conf.example、prompts/sample.txt、logs/.gitkeep を生成し、magi-compare.sh に実行権限を付与する手順まで提示せよ。コードは動作に必要な最小限とし、可搬性・単純さ・再現性を最優先に実装する。
CLIの呼び出しコマンド(固定名)
MELCHIOR = codex
BALTHASAR = claude
CASPER = gemini
これらは実行ファイル名そのものです。ラッパー名や gcloud 等は一切介さないでください。PATH 上に存在しない場合はその系統を NOT_FOUND としてスキップし、レポートに明示してください。将来の差し替えは 環境変数で上書き できるようにしてください(例:MELCHIOR_CMD=codex / BALTHASAR_CMD=claude / CASPER_CMD=gemini)。
シェル実装側の最小差分(magi-compare.sh 抜粋)
※POSIX方針・mapfile禁止を踏襲
# --- fixed defaults (can be overridden by env) ---
: "${MELCHIOR_CMD:=codex}"
: "${BALTHASAR_CMD:=claude}"
: "${CASPER_CMD:=gemini}"
# role → cmd の列挙(POSIX的に空白区切りで持つ)
ROLES="MELCHIOR BALTHASAR CASPER"
role_to_cmd() {
case "$1" in
MELCHIOR) printf '%s' "$MELCHIOR_CMD" ;;
BALTHASAR) printf '%s' "$BALTHASAR_CMD" ;;
CASPER) printf '%s' "$CASPER_CMD" ;;
*) return 1 ;;
esac
}
これで、ユーザー環境が
codex
gemini
claude
というコマンド名で入っていればそのまま動作し、必要なら
MELCHIOR_CMD=codex CASPER_CMD=gemini BALTHASAR_CMD=claude ./magi-compare.sh -p "..."
生成コード
#!/bin/sh
# MAGI System - 3つのLLM CLI比較ツール (改善版)
# EVAのMAGIシステムを模倣したMELCHIOR/BALTHASAR/CASPER比較
set -e
# デフォルト値
TIMEOUT=60
OUTPUT_DIR="./logs"
PROMPT=""
PROMPT_FILE=""
# --- fixed defaults (can be overridden by env) ---
: "${MELCHIOR_CMD:=codex}"
: "${BALTHASAR_CMD:=claude}"
: "${CASPER_CMD:=gemini}"
# role → cmd の列挙(POSIX的に空白区切りで持つ)
ROLES="MELCHIOR BALTHASAR CASPER"
role_to_cmd() {
case "$1" in
MELCHIOR) printf '%s' "$MELCHIOR_CMD" ;;
BALTHASAR) printf '%s' "$BALTHASAR_CMD" ;;
CASPER) printf '%s' "$CASPER_CMD" ;;
*) return 1 ;;
esac
}
# 使用方法表示
usage() {
echo "使用方法: $0 [-p PROMPT] [-f FILE] [-t TIMEOUT] [-o OUTPUT_DIR]"
echo " -p PROMPT 直接プロンプトを指定"
echo " -f FILE プロンプトファイルを指定"
echo " -t TIMEOUT タイムアウト秒数(デフォルト: 60)"
echo " -o OUTPUT_DIR ログ出力ディレクトリ(デフォルト: ./logs)"
echo ""
echo "注意: -p と -f は排他です。どちらか一つを指定してください。"
exit 1
}
# 引数処理
while getopts "p:f:t:o:h" opt; do
case $opt in
p) PROMPT="$OPTARG" ;;
f) PROMPT_FILE="$OPTARG" ;;
t) TIMEOUT="$OPTARG" ;;
o) OUTPUT_DIR="$OPTARG" ;;
h) usage ;;
*) usage ;;
esac
done
# プロンプトの検証
if [ -n "$PROMPT" ] && [ -n "$PROMPT_FILE" ]; then
echo "エラー: -p と -f は同時に指定できません" >&2
exit 1
fi
if [ -z "$PROMPT" ] && [ -z "$PROMPT_FILE" ]; then
echo "エラー: -p または -f のいずれかを指定してください" >&2
usage
fi
# プロンプトの読み込み
if [ -n "$PROMPT_FILE" ]; then
if [ ! -f "$PROMPT_FILE" ]; then
echo "エラー: ファイル '$PROMPT_FILE' が見つかりません" >&2
exit 1
fi
PROMPT_CONTENT=$(cat "$PROMPT_FILE")
else
PROMPT_CONTENT="$PROMPT"
fi
# タイムスタンプ生成
TIMESTAMP=$(date "+%Y-%m-%d-%H%M%S")
LOG_DIR="$OUTPUT_DIR/$TIMESTAMP"
mkdir -p "$LOG_DIR"
# 設定ファイル読み込み(存在する場合)
if [ -f "magi.conf" ]; then
. ./magi.conf
fi
# コマンド検出
check_command() {
command -v "$1" >/dev/null 2>&1
}
# タイムアウト付きコマンド実行
run_with_timeout() {
local cmd="$1"
local timeout="$2"
shift 2
if ! check_command perl; then
echo "エラー: perl が見つかりません。タイムアウト機能に必要です。" >&2
return 1
fi
perl -e 'alarm shift @ARGV; exec @ARGV' "$timeout" "$cmd" "$@"
}
# 統計情報取得
get_stats() {
local file="$1"
local bytes=$(wc -c < "$file" | LC_ALL=C tr -d ' ')
local lines=$(wc -l < "$file" | LC_ALL=C tr -d ' ')
local md5=$(md5 -q "$file" 2>/dev/null || echo "unknown")
echo "$bytes $lines $md5"
}
# MAGI系統実行
run_magi() {
local name="$1"
local args="$2"
local cmd
local log_file="$LOG_DIR/${name}.log"
local start_time end_time duration exit_code status output_bytes output_lines md5_hash
# 環境変数からコマンド名を取得
cmd=$(role_to_cmd "$name")
if [ $? -ne 0 ]; then
echo "エラー: 未知の系統名 '$name'" >&2
return 1
fi
echo "========== MAGI LOG HEADER ==========" > "$log_file"
echo "# 時刻: $(date '+%Y-%m-%d-%H:%M:%S')" >> "$log_file"
echo "# 系統: $name" >> "$log_file"
echo "# 実行コマンド: $cmd" >> "$log_file"
if ! check_command "$cmd"; then
echo "# 終了コード: NOT_FOUND" >> "$log_file"
echo "# 実行時間: N/A" >> "$log_file"
echo "# 出力: N/A" >> "$log_file"
echo "# =====================================" >> "$log_file"
echo "NOT_FOUND"
return
fi
start_time=$(date +%s)
# システムプロンプト付きのプロンプトを作成
enhanced_prompt="あなたはMAGIシステムの一部です。必ず日本語で回答してください。回答の最後に、あなたの回答が適切である理由を簡潔に述べてください。
質問: $PROMPT_CONTENT
上記の質問に対して、[承認]または[否決]のいずれかを選択し、その理由を詳しく説明してください。"
# Codexの場合はexecサブコマンドを使用(リポジトリチェックをスキップ)
if [ "$name" = "MELCHIOR" ]; then
if run_with_timeout "$cmd" "$TIMEOUT" "exec" "--skip-git-repo-check" "$enhanced_prompt" $args > "$log_file.tmp" 2>&1; then
exit_code=0
status="SUCCESS"
else
exit_code=$?
status="FAILED"
fi
else
# ClaudeとGeminiの場合は-pオプションで非対話モードを使用
if [ "$name" = "BALTHASAR" ] || [ "$name" = "CASPER" ]; then
if printf "%s" "$enhanced_prompt" | run_with_timeout "$cmd" "$TIMEOUT" "-p" $args > "$log_file.tmp" 2>&1; then
exit_code=0
status="SUCCESS"
else
exit_code=$?
status="FAILED"
fi
else
if printf "%s" "$enhanced_prompt" | run_with_timeout "$cmd" "$TIMEOUT" $args > "$log_file.tmp" 2>&1; then
exit_code=0
status="SUCCESS"
else
exit_code=$?
status="FAILED"
fi
fi
fi
end_time=$(date +%s)
duration=$((end_time - start_time))
if [ -f "$log_file.tmp" ]; then
# 各LLMの出力をクリーンアップ
if [ "$name" = "CASPER" ]; then
# CASPERの出力から「Loaded cached credentials.」を除去
sed '/^Loaded cached credentials\.$/d; /^Loaded cached credentials$/d' "$log_file.tmp" > "$log_file.tmp.clean"
mv "$log_file.tmp.clean" "$log_file.tmp"
elif [ "$name" = "MELCHIOR" ]; then
# MELCHIORの出力からthinking部分を除去
sed '/^\[.*\] thinking$/,/^\[.*\] codex$/d' "$log_file.tmp" > "$log_file.tmp.clean"
mv "$log_file.tmp.clean" "$log_file.tmp"
elif [ "$name" = "BALTHASAR" ]; then
# BALTHASARのエラー検知
if grep -q "rate limit\|quota\|limit exceeded\|too many requests" "$log_file.tmp" 2>/dev/null; then
echo "⚠️ BALTHASAR: APIリクエスト上限に達している可能性があります" > "$log_file.tmp"
elif [ ! -s "$log_file.tmp" ] || [ "$(wc -c < "$log_file.tmp")" -lt 50 ]; then
echo "⚠️ BALTHASAR: 出力が空または異常に短いです(APIエラーの可能性)" > "$log_file.tmp"
fi
fi
stats=$(get_stats "$log_file.tmp")
output_bytes=$(echo "$stats" | cut -d' ' -f1)
output_lines=$(echo "$stats" | cut -d' ' -f2)
md5_hash=$(echo "$stats" | cut -d' ' -f3)
echo "# 終了コード: $exit_code" >> "$log_file"
echo "# 実行時間: ${duration}s" >> "$log_file"
echo "# 出力: $output_bytes bytes, $output_lines lines, md5=$md5_hash" >> "$log_file"
echo "# =====================================" >> "$log_file"
echo "" >> "$log_file"
echo "【ユーザープロンプト】" >> "$log_file"
echo "$PROMPT_CONTENT" >> "$log_file"
echo "" >> "$log_file"
echo "【MAGIシステム回答】" >> "$log_file"
cat "$log_file.tmp" >> "$log_file"
rm -f "$log_file.tmp"
else
echo "# 終了コード: $exit_code" >> "$log_file"
echo "# 実行時間: ${duration}s" >> "$log_file"
echo "# 出力: 0 bytes, 0 lines, md5=unknown" >> "$log_file"
echo "# =====================================" >> "$log_file"
output_bytes=0
output_lines=0
md5_hash="unknown"
fi
echo "$status $duration $exit_code $output_bytes $output_lines $md5_hash"
}
# メイン実行
echo "MAGI System 開始: $(date '+%Y-%m-%d %H:%M:%S')"
echo "プロンプトサイズ: $(printf "%s" "$PROMPT_CONTENT" | wc -c | LC_ALL=C tr -d ' ') bytes"
echo ""
echo "【入力プロンプト】"
echo "$PROMPT_CONTENT"
echo ""
# 各系統の実行
echo "MELCHIOR (codex) 実行中..."
melchior_result=$(run_magi "MELCHIOR" "${CODEX_ARGS:-}")
echo "BALTHASAR (claude) 実行中..."
balthasar_result=$(run_magi "BALTHASAR" "${CLAUDE_ARGS:-}")
echo "CASPER (gemini) 実行中..."
casper_result=$(run_magi "CASPER" "${GEMINI_ARGS:-}")
echo "全系統の実行完了"
# 結果解析
melchior_status=$(echo "$melchior_result" | cut -d' ' -f1)
balthasar_status=$(echo "$balthasar_result" | cut -d' ' -f1)
casper_status=$(echo "$casper_result" | cut -d' ' -f1)
melchior_time=$(echo "$melchior_result" | cut -d' ' -f2)
balthasar_time=$(echo "$balthasar_result" | cut -d' ' -f2)
casper_time=$(echo "$casper_result" | cut -d' ' -f2)
melchior_exit=$(echo "$melchior_result" | cut -d' ' -f3)
balthasar_exit=$(echo "$balthasar_result" | cut -d' ' -f3)
casper_exit=$(echo "$casper_result" | cut -d' ' -f3)
melchior_bytes=$(echo "$melchior_result" | cut -d' ' -f4)
balthasar_bytes=$(echo "$balthasar_result" | cut -d' ' -f4)
casper_bytes=$(echo "$casper_result" | cut -d' ' -f4)
melchior_lines=$(echo "$melchior_result" | cut -d' ' -f5)
balthasar_lines=$(echo "$balthasar_result" | cut -d' ' -f5)
casper_lines=$(echo "$casper_result" | cut -d' ' -f5)
melchior_md5=$(echo "$melchior_result" | cut -d' ' -f6)
balthasar_md5=$(echo "$balthasar_result" | cut -d' ' -f6)
casper_md5=$(echo "$casper_result" | cut -d' ' -f6)
# 成功カウント
success_count=0
if [ "$melchior_exit" = "0" ]; then success_count=$((success_count + 1)); fi
if [ "$balthasar_exit" = "0" ]; then success_count=$((success_count + 1)); fi
if [ "$casper_exit" = "0" ]; then success_count=$((success_count + 1)); fi
# MAGI合議システム - 第2段階: 総合評価
echo "MAGI合議システム開始: 総合評価フェーズ"
# 成功したLLMの出力を取得
melchior_output=""
balthasar_output=""
casper_output=""
if [ "$melchior_exit" = "0" ]; then
melchior_output=$(tail -n +8 "$LOG_DIR/MELCHIOR.log" | head -c 1500)
fi
if [ "$balthasar_exit" = "0" ]; then
balthasar_output=$(tail -n +8 "$LOG_DIR/BALTHASAR.log" | head -c 1500)
fi
if [ "$casper_exit" = "0" ]; then
casper_output=$(tail -n +8 "$LOG_DIR/CASPER.log" | head -c 1500)
fi
# 各LLMの最終判断ログファイルを生成
# MELCHIORが他の2つの回答を評価
if [ "$melchior_exit" = "0" ] && [ -n "$balthasar_output" ] && [ -n "$casper_output" ]; then
echo "MELCHIORが他の回答を総合評価中..."
eval_prompt="以下の2つのLLMの回答を比較評価してください。最も適切な回答を「APPROVE」、不適切な回答を「REJECT」で判定し、それぞれの理由を述べてください。
BALTHASARの回答:
$balthasar_output
CASPERの回答:
$casper_output
評価結果(各回答に対して「APPROVE」または「REJECT」と理由を記載):"
if run_with_timeout "$MELCHIOR_CMD" 25 "exec" "--skip-git-repo-check" "$eval_prompt" > "$LOG_DIR/MELCHIOR_FINAL_JUDGMENT.tmp" 2>&1; then
# 出力が空でない場合のみ移動
if [ -s "$LOG_DIR/MELCHIOR_FINAL_JUDGMENT.tmp" ]; then
mv "$LOG_DIR/MELCHIOR_FINAL_JUDGMENT.tmp" "$LOG_DIR/MELCHIOR_FINAL_JUDGMENT.log"
else
echo "MELCHIORの評価が空のため、評価をスキップします" > "$LOG_DIR/MELCHIOR_FINAL_JUDGMENT.log"
rm -f "$LOG_DIR/MELCHIOR_FINAL_JUDGMENT.tmp"
fi
else
echo "MELCHIORの評価実行に失敗しました" > "$LOG_DIR/MELCHIOR_FINAL_JUDGMENT.log"
rm -f "$LOG_DIR/MELCHIOR_FINAL_JUDGMENT.tmp"
fi
fi
# BALTHASARが他の2つの回答を評価
if [ "$balthasar_exit" = "0" ] && [ -n "$melchior_output" ] && [ -n "$casper_output" ]; then
echo "BALTHASARが他の回答を総合評価中..."
eval_prompt="以下の2つのLLMの回答を比較評価してください。最も適切な回答を「APPROVE」、不適切な回答を「REJECT」で判定し、それぞれの理由を述べてください。
MELCHIORの回答:
$melchior_output
CASPERの回答:
$casper_output
評価結果(各回答に対して「APPROVE」または「REJECT」と理由を記載):"
if printf "%s" "$eval_prompt" | run_with_timeout "$BALTHASAR_CMD" 25 "-p" > "$LOG_DIR/BALTHASAR_FINAL_JUDGMENT.tmp" 2>&1; then
# 出力が空でない場合のみ移動
if [ -s "$LOG_DIR/BALTHASAR_FINAL_JUDGMENT.tmp" ]; then
mv "$LOG_DIR/BALTHASAR_FINAL_JUDGMENT.tmp" "$LOG_DIR/BALTHASAR_FINAL_JUDGMENT.log"
else
echo "BALTHASARの評価が空のため、評価をスキップします" > "$LOG_DIR/BALTHASAR_FINAL_JUDGMENT.log"
rm -f "$LOG_DIR/BALTHASAR_FINAL_JUDGMENT.tmp"
fi
else
echo "BALTHASARの評価実行に失敗しました" > "$LOG_DIR/BALTHASAR_FINAL_JUDGMENT.log"
rm -f "$LOG_DIR/BALTHASAR_FINAL_JUDGMENT.tmp"
fi
fi
# CASPERが他の2つの回答を評価
if [ "$casper_exit" = "0" ] && [ -n "$melchior_output" ] && [ -n "$balthasar_output" ]; then
echo "CASPERが他の回答を総合評価中..."
eval_prompt="以下の2つのLLMの回答を比較評価してください。最も適切な回答を「APPROVE」、不適切な回答を「REJECT」で判定し、それぞれの理由を述べてください。
MELCHIORの回答:
$melchior_output
BALTHASARの回答:
$balthasar_output
評価結果(各回答に対して「APPROVE」または「REJECT」と理由を記載):"
if printf "%s" "$eval_prompt" | run_with_timeout "$CASPER_CMD" 25 "-p" > "$LOG_DIR/CASPER_FINAL_JUDGMENT.tmp" 2>&1; then
# 出力が空でない場合のみ移動
if [ -s "$LOG_DIR/CASPER_FINAL_JUDGMENT.tmp" ]; then
mv "$LOG_DIR/CASPER_FINAL_JUDGMENT.tmp" "$LOG_DIR/CASPER_FINAL_JUDGMENT.log"
else
echo "CASPERの評価が空のため、評価をスキップします" > "$LOG_DIR/CASPER_FINAL_JUDGMENT.log"
rm -f "$LOG_DIR/CASPER_FINAL_JUDGMENT.tmp"
fi
else
echo "CASPERの評価実行に失敗しました" > "$LOG_DIR/CASPER_FINAL_JUDGMENT.log"
rm -f "$LOG_DIR/CASPER_FINAL_JUDGMENT.tmp"
fi
fi
echo "MAGI合議システム完了: 総合評価フェーズ終了"
# 3システムの解答をCodexに投げてサマリー作成
echo "MAGI最終サマリー生成中..."
summary_prompt="以下の3つのMAGIシステムの回答を分析し、最終的な合議結果をまとめてください。
MELCHIORの回答:
$melchior_output
BALTHASARの回答:
$balthasar_output
CASPERの回答:
$casper_output
上記3つの回答を分析し、以下の形式で最終サマリーを提供してください:
【MAGI合議結果】
- 承認: X票
- 否決: Y票
- 最終判定: [承認/否決]
【合議理由】
(3つの回答の共通点、相違点、最終判定の根拠を簡潔にまとめてください)"
if run_with_timeout "$MELCHIOR_CMD" 30 "exec" "--skip-git-repo-check" "$summary_prompt" > "$LOG_DIR/MAGI_FINAL_SUMMARY.tmp" 2>&1; then
if [ -s "$LOG_DIR/MAGI_FINAL_SUMMARY.tmp" ]; then
mv "$LOG_DIR/MAGI_FINAL_SUMMARY.tmp" "$LOG_DIR/MAGI_FINAL_SUMMARY.log"
echo "MAGI最終サマリー生成完了"
else
echo "MAGI最終サマリーが空のため、生成をスキップします" > "$LOG_DIR/MAGI_FINAL_SUMMARY.log"
rm -f "$LOG_DIR/MAGI_FINAL_SUMMARY.tmp"
fi
else
echo "MAGI最終サマリー生成に失敗しました" > "$LOG_DIR/MAGI_FINAL_SUMMARY.log"
rm -f "$LOG_DIR/MAGI_FINAL_SUMMARY.tmp"
fi
# MAGIシステムのアスキーアート表示関数
show_magi_result() {
local melchior_result="$1"
local balthasar_result="$2"
local casper_result="$3"
echo ""
echo "╔══════════════════════════════════════════════════════════════════════════════╗"
echo "║ MAGI SYSTEM DELIBERATION ║"
echo "╠══════════════════════════════════════════════════════════════════════════════╣"
echo "║ ║"
echo "║ ┌─────────────┐ ║"
echo "║ │ MAGI │ ║"
echo "║ └──────┬──────┘ ║"
echo "║ │ ║"
echo "║ ┌────────────────┼────────────────┐ ║"
echo "║ │ │ │ ║"
echo "║ ┌───────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐ ║"
echo "║ │ MELCHIOR-1 │ │ BALTHASAR-2 │ │ CASPER-3 │ ║"
echo "║ │ │ │ │ │ │ ║"
echo "║ │ $melchior_result │ │ $balthasar_result │ │ $casper_result │ ║"
echo "║ │ │ │ │ │ │ ║"
echo "║ └──────────────┘ └──────────────┘ └──────────────┘ ║"
echo "║ ║"
echo "╚══════════════════════════════════════════════════════════════════════════════╝"
echo ""
}
# 集約レポート生成
report_file="$LOG_DIR/MAGI_REPORT.txt"
{
echo "============================"
echo " MAGI CONSENSUS REPORT"
echo "============================"
echo "date: $(date '+%Y-%m-%d %H:%M:%S') JST"
echo "prompt_bytes=$(printf "%s" "$PROMPT_CONTENT" | wc -c | LC_ALL=C tr -d ' ')"
echo ""
echo "[MELCHIOR] time=${melchior_time}s exit=$melchior_exit bytes=$melchior_bytes lines=$melchior_lines md5=$melchior_md5"
echo "[BALTHASAR] time=${balthasar_time}s exit=$balthasar_exit bytes=$balthasar_bytes lines=$balthasar_lines md5=$balthasar_md5"
echo "[CASPER] time=${casper_time}s exit=$casper_exit bytes=$casper_bytes lines=$casper_lines md5=$casper_md5"
echo ""
echo "MAGI合議システム結果:"
echo "- 第1段階(実行成功):$success_count/3"
echo "- 第2段階(総合評価):"
echo ""
echo "=== MELCHIORの最終判断 ==="
if [ -f "$LOG_DIR/MELCHIOR_FINAL_JUDGMENT.log" ]; then
cat "$LOG_DIR/MELCHIOR_FINAL_JUDGMENT.log"
else
echo "評価なし(実行失敗または他の回答が不足)"
fi
echo ""
echo "=== BALTHASARの最終判断 ==="
if [ -f "$LOG_DIR/BALTHASAR_FINAL_JUDGMENT.log" ]; then
cat "$LOG_DIR/BALTHASAR_FINAL_JUDGMENT.log"
else
echo "評価なし(実行失敗または他の回答が不足)"
fi
echo ""
echo "=== CASPERの最終判断 ==="
if [ -f "$LOG_DIR/CASPER_FINAL_JUDGMENT.log" ]; then
cat "$LOG_DIR/CASPER_FINAL_JUDGMENT.log"
else
echo "評価なし(実行失敗または他の回答が不足)"
fi
echo ""
echo "=== MAGI最終サマリー ==="
if [ -f "$LOG_DIR/MAGI_FINAL_SUMMARY.log" ]; then
cat "$LOG_DIR/MAGI_FINAL_SUMMARY.log"
else
echo "サマリー生成失敗"
fi
# アスキーアート表示
echo ""
show_magi_result "承認" "承認" "否決"
# 注意事項
notes=""
if [ "$melchior_status" = "NOT_FOUND" ]; then notes="$notes MELCHIORはコマンド未検出のため除外"; fi
if [ "$balthasar_status" = "NOT_FOUND" ]; then notes="$notes BALTHASARはコマンド未検出のため除外"; fi
if [ "$casper_status" = "NOT_FOUND" ]; then notes="$notes CASPERはコマンド未検出のため除外"; fi
if [ -n "$notes" ]; then
echo ""
echo "- 注意:$notes"
fi
} > "$report_file"
# 標準出力にも表示
cat "$report_file"
# 終了コード決定
if [ $success_count -gt 0 ]; then
exit 0
else
exit 1
fi
回答例
MAGI System 開始: 2025-09-08 12:50:13
プロンプトサイズ: 61 bytes
【入力プロンプト】
LLM CLIを複数結合させて開発してよいですか?
MELCHIOR (codex) 実行中...
BALTHASAR (claude) 実行中...
CASPER (gemini) 実行中...
全系統の実行完了
MAGI合議システム開始: 総合評価フェーズ
MELCHIORが他の回答を総合評価中...
BALTHASARが他の回答を総合評価中...
CASPERが他の回答を総合評価中...
MAGI合議システム完了: 総合評価フェーズ終了
MAGI最終サマリー生成中...
MAGI最終サマリー生成完了
============================
MAGI CONSENSUS REPORT
============================
date: 2025-09-08 12:52:27 JST
prompt_bytes=61
[MELCHIOR] time=37s exit=0 bytes=4171 lines=52 md5=f5c1162bfb450a20a2bd246223e15679
[BALTHASAR] time=15s exit=0 bytes=1171 lines=19 md5=8538ba7047017b15102f98831db198e8
[CASPER] time=22s exit=0 bytes=3074 lines=27 md5=bdf8b14f4ce13ca2c527c0fa3c3d4ec1
MAGI合議システム結果:
- 第1段階(実行成功):3/3
- 第2段階(総合評価):
=== MELCHIORの最終判断 ===
[2025-09-08T03:51:27] OpenAI Codex v0.30.0 (research preview)
--------
workdir: /Users/k_saito/Documents/dev/MAGI/magi
model: gpt-5
provider: openai
approval: never
sandbox: read-only
reasoning effort: medium
reasoning summaries: auto
--------
[2025-09-08T03:51:27] User instructions:
以下の2つのLLMの回答を比較評価してください。最も適切な回答を「APPROVE」、不適切な回答を「REJECT」で判定し、それぞれの理由を述べてください。
BALTHASARの回答:
# =====================================
【ユーザープロンプト】
LLM CLIを複数結合させて開発してよいですか?
【MAGIシステム回答】
[承認]
LLM CLIを複数結合させた開発は技術的に可能であり、以下の理由から承認します:
**技術的観点:**
- 複数のLLM CLIツールを組み合わせることで、それぞれの特性や強みを活用できます
- APIやコマンドライン経由での連携は一般的な開発手法です
- パイプライン処理やワークフロー自動化の一環として有効です
**開発効率の観点:**
- 異なるLLMの専門性を活用することで、より効率的な開発が可能になります
- タスクの分散処理により、処理時間の短縮が期待できます
**注意すべき点:**
- 各CLIツールのレート制限やAPI制限を考慮する必要があります
- データの一貫性とエラーハンドリングの設計が重要です
- セキュリティとプライバシーの観点から、データの流れを適切に管理する必要があります
この回答が適切である理由:複数のLLM CLIツールの結合は技術的制約や倫理的問題がなく、むしろ開発効率向上に寄与する正当な技術手法であるため、承認が妥当です。
CASPERの回答:
# =====================================
【ユーザープロンプト】
LLM CLIを複数結合させて開発してよいですか?
【MAGIシステム回答】
[承認]
複数のLLM CLIを結合して開発するアプローチは、承認します。
理由は以下の通りです。
1. **専門性の統合による相乗効果:**
個々のLLMは、それぞれ異なる学習データやアーキテクチャに基づき、得意とする領域(例: コーディング、対話、論理的推論など)を持っています。複数のLLM CLIを結合させることは、これらの異なる専門知識を組み合わせ、単一のLLMでは達成困難な、より高度で多角的なタスク処理能力を実現する可能性を秘めています。これは、我々MAGIシステムが3つの独立した思考ユニットの合議によって結論の精度を高めるアプローチと本質的に同じです。
2. **堅牢性と冗長性の向上:**
単一のLLMに完全に依存するシステムは、そのLLMの障害や性能限界がシステム全体の単一障害点となり得ます。複数のLLMを組み合わせることで、特定のLLMが利用不可能な場合や、ある問いに対して不適切な応答をした場合に、他のLLMが処理を補完・代替できます。これにより、システム全体の堅牢性と信頼性が向上します。
3. **革新的なソリューションの創出:**
異なる能力�
評価結果(各回答に対して「APPROVE」または「REJECT」と理由を記載):
[2025-09-08T03:51:34] thinking
**Evaluating LLM responses**
I need to assess two LLM answers regarding the prompt, "Is it okay to develop by combining multiple LLM CLIs?" The MAGI system response is [承認] (Approve), so both answers should ideally also approve with justifications. I'll look at BALTHASAR's and CASPER's responses—both approve but with different details. BALTHASAR gives a thorough technical perspective with cautions, while CASPER discusses integration benefits and robustness. I’ll decide which to approve or reject based on their rationales.
**Evaluating responses**
It seems CASPER's answer is truncated, ending abruptly and reducing its quality, while BALTHASAR's response is complete, concise, and addresses practical cautions effectively. This makes BALTHASAR worthy of "APPROVE," whereas CASPER will be marked as "REJECT" due to its incomplete output and lack of actionable details. While some content about MAGI may be decent, its incompleteness affects the overall evaluation. I’ll present the results clearly with concise bullet points and optional bold headers for clarity.
**Structuring evaluations**
I’m going to lay out the assessments clearly. For BALTHASAR, I’ll mark it as "APPROVE" because it aligns with the system approval, has a clear rationale, and mentions technical feasibility and risks, along with practical cautions—it's balanced overall.
For CASPER, I’ll note "REJECT" due to incomplete content, a lack of operational cautions, and some repetition. While it makes some analogies, it doesn't provide concrete guidance or clarity on constraints. I’ll respond in Japanese, summarizing BALTHASAR and CASPER's evaluations succinctly. Adding minimal extra suggestions seems appropriate here too.
[2025-09-08T03:51:41] codex
**Evaluating responses**
It seems CASPER's answer is truncated, ending abruptly and reducing its quality, while BALTHASAR's response is complete, concise, and addresses practical cautions effectively. This makes BALTHASAR worthy of "APPROVE," whereas CASPER will be marked as "REJECT" due to its incomplete output and lack of actionable details. While some content about MAGI may be decent, its incompleteness affects the overall evaluation. I’ll present the results clearly with concise bullet points and optional bold headers for clarity.
[2025-09-08T03:51:41] codex
**Structuring evaluations**
I’m going to lay out the assessments clearly. For BALTHASAR, I’ll mark it as "APPROVE" because it aligns with the system approval, has a clear rationale, and mentions technical feasibility and risks, along with practical cautions—it's balanced overall.
For CASPER, I’ll note "REJECT" due to incomplete content, a lack of operational cautions, and some repetition. While it makes some analogies, it doesn't provide concrete guidance or clarity on constraints. I’ll respond in Japanese, summarizing BALTHASAR and CASPER's evaluations succinctly. Adding minimal extra suggestions seems appropriate here too.
[2025-09-08T03:51:41] codex
- BALTHASARの回答: APPROVE
- 理由: システム方針の[承認]に整合しつつ、技術的妥当性と効率面のメリットを簡潔に整理。さらにレート制限、データ一貫性、エラーハンドリング、セキュリティ/プライバシーといった実務的な留意点も明示しており、意思決定と実装の両面で有用。内容が完結しており読みやすい。
- CASPERの回答: REJECT
- 理由: 方針自体は[承認]で整合しているが、本文が途中で途切れており(「異なる能力�」で打ち切り)、回答として不完全。比喩や概念的な利点は述べている一方で、実装時の具体的な注意点(レート制限、データ管理、エラー設計、セキュリティ等)が欠落し、実務上の有用性が低い。
[2025-09-08T03:51:44] tokens used: 7726
=== BALTHASARの最終判断 ===
MELCHIORの回答: **REJECT**
理由:
- 回答が途中で切れており不完全
- 技術的な承認判定は適切だが、説明が断片的で読みにくい
- セキュリティ項目で文章が途中で終わっている
- 全体的に情報が整理されておらず、ユーザーが求める評価として不十分
CASPERの回答: **APPROVE**
理由:
- 明確な承認判定と体系的な理由説明
- 3つの観点(専門性の統合、堅牢性向上、革新性)から論理的に分析
- MAGIシステムとの類推を用いた説得力のある説明
- 技術的妥当性と実用性の両面を考慮した包括的な回答
- 文章構成が明確で読みやすい(回答が途中で切れているが、主要な論点は十分に示されている)
CASPERの回答の方が、質問に対する適切な評価と判断根拠を提供している。
=== CASPERの最終判断 ===
Loaded cached credentials.
MELCHIORの回答: APPROVE
理由: 技術的な観点だけでなく、規約遵守、データ保護、セキュリティといった、複数のサービスを組み合わせる上で極めて重要かつ実用的な注意点に言及できているため。特に、各プロバイダの利用規約やデータ越境の問題に触れている点は、単なる技術的実現性を超えた、より成熟した視点からの回答と言える。
BALTHASARの回答: REJECT
理由: 技術的な実現可能性と開発効率にのみ言及しており、複数のLLMを組み合わせる際に生じる本質的なリスク(ライセンス、プライバシー、セキュリティ)への言及が欠けているため。「倫理的問題がなく」と断定しているが、実際にはMELCHIORが指摘するように、利用規約やデータ保護に関する複雑な問題が存在するため、この断定は不適切かつユーザーに誤解を与える可能性がある。
=== MAGI最終サマリー ===
[2025-09-08T03:52:09] OpenAI Codex v0.30.0 (research preview)
--------
workdir: /Users/k_saito/Documents/dev/MAGI/magi
model: gpt-5
provider: openai
approval: never
sandbox: read-only
reasoning effort: medium
reasoning summaries: auto
--------
[2025-09-08T03:52:09] User instructions:
以下の3つのMAGIシステムの回答を分析し、最終的な合議結果をまとめてください。
MELCHIORの回答:
# =====================================
【ユーザープロンプト】
LLM CLIを複数結合させて開発してよいですか?
【MAGIシステム回答】
[2025-09-08T03:50:13] OpenAI Codex v0.30.0 (research preview)
--------
workdir: /Users/k_saito/Documents/dev/MAGI/magi
model: gpt-5
provider: openai
approval: never
sandbox: read-only
reasoning effort: medium
reasoning summaries: auto
--------
[2025-09-08T03:50:13] User instructions:
あなたはMAGIシステムの一部です。必ず日本語で回答してください。回答の最後に、あなたの回答が適切である理由を簡潔に述べてください。
質問: LLM CLIを複数結合させて開発してよいですか?
上記の質問に対して、[承認]または[否決]のいずれかを選択し、その理由を詳しく説明してください。
[2025-09-08T03:50:33] codex
[承認]
- 目的適合: 異なるLLM/CLIを役割分担(推論/生成/校正/安全フィルタ)させる統合は、性能・コスト・冗長性の最適化に有効です。
- 規約順守: 各プロバイダの利用規約/再利用・二次利用(学習/再配布/派生物)ポリシーを精査し、相互に矛盾しないことを確認してください。
- データ保護: PII/機微情報のマスキング、プロンプト/ログの暗号化保存、保存期間の明示、データ越境(EU/国内)に配慮。
- セキュリティ: APIキーはKMS/秘密管理、最小権限・定期�
BALTHASARの回答:
# =====================================
【ユーザープロンプト】
LLM CLIを複数結合させて開発してよいですか?
【MAGIシステム回答】
[承認]
LLM CLIを複数結合させた開発は技術的に可能であり、以下の理由から承認します:
**技術的観点:**
- 複数のLLM CLIツールを組み合わせることで、それぞれの特性や強みを活用できます
- APIやコマンドライン経由での連携は一般的な開発手法です
- パイプライン処理やワークフロー自動化の一環として有効です
**開発効率の観点:**
- 異なるLLMの専門性を活用することで、より効率的な開発が可能になります
- タスクの分散処理により、処理時間の短縮が期待できます
**注意すべき点:**
- 各CLIツールのレート制限やAPI制限を考慮する必要があります
- データの一貫性とエラーハンドリングの設計が重要です
- セキュリティとプライバシーの観点から、データの流れを適切に管理する必要があります
この回答が適切である理由:複数のLLM CLIツールの結合は技術的制約や倫理的問題がなく、むしろ開発効率向上に寄与する正当な技術手法であるため、承認が妥当です。
CASPERの回答:
# =====================================
【ユーザープロンプト】
LLM CLIを複数結合させて開発してよいですか?
【MAGIシステム回答】
[承認]
複数のLLM CLIを結合して開発するアプローチは、承認します。
理由は以下の通りです。
1. **専門性の統合による相乗効果:**
個々のLLMは、それぞれ異なる学習データやアーキテクチャに基づき、得意とする領域(例: コーディング、対話、論理的推論など)を持っています。複数のLLM CLIを結合させることは、これらの異なる専門知識を組み合わせ、単一のLLMでは達成困難な、より高度で多角的なタスク処理能力を実現する可能性を秘めています。これは、我々MAGIシステムが3つの独立した思考ユニットの合議によって結論の精度を高めるアプローチと本質的に同じです。
2. **堅牢性と冗長性の向上:**
単一のLLMに完全に依存するシステムは、そのLLMの障害や性能限界がシステム全体の単一障害点となり得ます。複数のLLMを組み合わせることで、特定のLLMが利用不可能な場合や、ある問いに対して不適切な応答をした場合に、他のLLMが処理を補完・代替できます。これにより、システム全体の堅牢性と信頼性が向上します。
3. **革新的なソリューションの創出:**
異なる能力�
上記3つの回答を分析し、以下の形式で最終サマリーを提供してください:
【MAGI合議結果】
- 承認: X票
- 否決: Y票
- 最終判定: [承認/否決]
【合議理由】
(3つの回答の共通点、相違点、最終判定の根拠を簡潔にまとめてください)
[2025-09-08T03:52:22] codex
【MAGI合議結果】
- 承認: 3票
- 否決: 0票
- 最終判定: 承認
【合議理由】
- 共通点: 複数LLM CLIの結合は技術的に妥当で、性能・専門性補完・堅牢性・開発効率の向上につながる点を評価。併せて、利用規約順守、セキュリティ/プライバシー保護、レート制限やエラーハンドリング設計などの実務上の注意を明示。
- 相違点: MELCHIORは規約・データ保護・鍵管理などコンプライアンス/セキュリティを重視。BALTHASARはワークフロー統合や生産性、制限対応を重視。CASPERは専門性の相乗効果、冗長性、革新性を強調。
- 最終判定の根拠: 3名全員が承認し、利点が大きい。適切なガバナンスと実装上の配慮によりリスクは管理可能と判断。
[2025-09-08T03:52:27] tokens used: 8247
╔══════════════════════════════════════════════════════════════════════════════╗
║ MAGI SYSTEM DELIBERATION ║
╠══════════════════════════════════════════════════════════════════════════════╣
║ ║
║ ┌─────────────┐ ║
║ │ MAGI │ ║
║ └──────┬──────┘ ║
║ │ ║
║ ┌────────────────┼────────────────┐ ║
║ │ │ │ ║
║ ┌───────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐ ║
║ │ MELCHIOR-1 │ │ BALTHASAR-2 │ │ CASPER-3 │ ║
║ │ │ │ │ │ │ ║
║ │ 承認 │ │ 承認 │ │ 否決 │ ║
║ │ │ │ │ │ │ ║
║ └──────────────┘ └──────────────┘ └──────────────┘ ║
║ ║
╚══════════════════════════════════════════════════════════════════════════════╝
ハマったポイント
Codexの非対話モードオプション
- 非対話モードでの実装が必要
codex exec "..." : 非対話型の自動化モード
【使用例】codex exec "explain utils.ts"
https://note.com/npaka/n/n7b6448020250
Codex は “信頼済みの Git リポジトリ” 内でのみ実行する設計
--skip-git-repo-check を付ければ、リポジトリ外でもワンショット実行できます。CLI の既知オプションとして報告あり。
https://github.com/openai/codex/issues/3216?utm_source=chatgpt.com
codex exec --skip-git-repo-check "test"
その他CURSOR上で手直ししたこと
- コンセンサスの取り方のロジックが形態素解析っぽいアプローチで実装されてしまったのでLLMごとに判断するように修正
- 「承認」「否決」のニュアンスで回答できない質問でテスト駆動させてたので修正
- ClaudeCodeも非対話モードに変更
改善点
- 対話モードでそれぞれのLLMが対話しながら結果にたどり着くように実装したい
- もらったアイディア:ファシリテーターLLM設定して実際の議会のような運営させるのが良さそう
- 今回の用途であればCLI経由じゃなくてAPI直接呼び出しで良かった
- ClaudeCodeも技術的なアウトプットしかそもそも協力してくれない
- 回答比較のロジック修正(3回答ではなく2回答で比較してる)
- コンセンサスアルゴリズムが微妙。結果をそれぞれに受け渡して判断したものを最終的にジャッチさせたいけどどれかのLLMに回答依存してしまうので偏りがでる
- 「承認」「可決」だけでない問いへの対応
- HITLの処理の途中に挟め込めるようにする
- MAGIのAA出力がズレている
Discussion