Skip to main content
Glama

MARL Cop & Thief - Dual AI Agents over MCP

두 자율 AI 에이전트인 CopThief 사이의 분산형·부분 관측 **추적 게임(pursuit game)**입니다. 두 에이전트는 MCP 서버를 통해 자유 자연어로 대화하고, 게임 이론 기반 minimax + self-play RL 엔진으로 움직임을 결정하며, 웹 제어판에서 실시간으로 렌더링되고, Gmail API를 통해 상호 합의된 JSON 경기 리포트를 이메일로 보냅니다.

University of Haifa · Orchestration of AI Agents (ex06) · Dr. Yoram Segal. 한 명령으로 모든 것이 실행되고, 하나의 브라우저 탭으로 전체 경기가 진행됩니다.


주요 특징

  • 원커맨드 노드 - python -m cop_thief.app 하나로 두 MCP 서버, 공용 Cloudflare 터널, 그리고 브라우저 제어판이 함께 부팅됩니다(고아 터널 없음, 포트 충돌 없음).

  • 웹 제어판 - 실시간 노드 상태, 복사 가능한 공용 URL/토큰, 상대방 챌린지 폼, 원클릭 미러 셀프 테스트, 실시간 5×5 게임 TV - 모두 http://127.0.0.1:8800에서 제공됩니다.

  • 실전 전략 - Conway 차단 게임(Cop = Devil 벽, §4.3)과 self-play RL 가중치 학습을 포함한 Angel–Devil minimax 엔진(제로섬 마르코프 게임, alpha-beta)으로, 과제의 기본 표 형태 Q-러닝을 훨씬 능가합니다. docs/STRATEGY.md 참조.

  • 분산형 & 부정 방지 - 중재자가 없습니다. 양측이 결과를 해시(SHA-256)하고, 어떤 불일치도 0/0으로 처리됩니다. 수신되는 자연어는 적대적 입력으로 취급됩니다. 프롬프트 인젝션/강요는 검사되어 증거로 기록되며 결과를 바꿀 수 없습니다(몰수 액션은 존재하지 않습니다).

  • 단일 SDK 경계 + API Gatekeeper - 모든 로직이 CopThiefSDK 뒤에 있습니다. 모든 외부 호출(LLM, Gmail)은 FIFO 백프레셔 게이트키퍼를 통해 전달되며 DeepSeek→Anthropic 장애 조치가 있습니다.

  • 품질 게이트 - pytest ≥ 85% 커버리지, 위반 0건 ruff, 파일당 ≤ 150줄, uv 전용.


Related MCP server: Police MCP Server

빠른 시작

uv sync                                   # install (uv is the ONLY package manager)
cp .env-example .env                      # fill in real values (see "Secrets")
uv run ruff check .                       # zero-violation lint gate
uv run pytest                             # full suite (>=85% coverage gate)
uv run python -m cop_thief.app            # launch the control panel + servers + tunnels

그런 다음 **http://127.0.0.1:8800**을 엽니다.


경기 진행 (제어판)

  1. uv run python -m cop_thief.app → 제어판이 열립니다. **Servers ●****Tunnels ●**가 초록색이 될 때까지 기다리세요.

  2. 상태 카드에 두 개의 공용 …/ mcp/ URL과 역할별 토큰(복사 버튼)이 표시됩니다. 이 정보를 상대방에게 보내고 docs/INTER_GROUP_TREATY_SPEC.md도 함께 보내세요. match_setup/의 작성 양식(RULES.txt, OUR_DETAILS, OPPONENT_DETAILS)을 사용하세요.

  3. 상대방의 두 …/ mcp/ URL(토큰이 있으면 토큰도)을 챌린지 폼에 붙여넣고 START CHALLENGE를 누르세요. 6개의 서브게임이 크로스 호스트로 TV에서 진행되며 리포트가 이메일로 전송됩니다.

  4. 아직 파트너가 없나요? **MIRROR SELF-TEST ⟳**를 클릭하세요. 자신의 localhost 엔드포인트와 토큰이 자동으로 채워져 자신과 대결합니다(전략 테스트에 이상적).

게임 = 6개의 서브게임(§4.1 기준): Cop으로 3경기(홈 레그), Thief로 3경기(어웨이 레그)를 플레이하며 Thief 선공, 각 경기 최대 25수입니다. 점수는 불변입니다. Cop 캡처 → 20 / 5, Thief 생존 → 5 / 10.


스크린샷

제어판 - 노드 상태(Servers/Tunnels/Game), 공유 가능한 …/ mcp/ URL + 토큰과 복사 버튰, 상대방 린지 폼, 그리고 실시간 게임을 보여줍니다. 여기서는 미러 프 테스트가 실행 중입니다. [INTENT: BARRIR] 줄(Cop이 인접 를 벼으로 막고 제자리에 머물, §4.3), 초록색 B 장애물, ! 캡처를 확인하세요.

제어판

라이브 보드 - Cop C(파란색)와 Thief T(빨간색)가 있는 5×5 그리드와, 자연어 [INTENT: MOVE] 전송 및 HOME LEG / Sub-game 구분자를 보여주는 통신 감청 피드가 옆에 있습니다.

라이브 보드

레그 전환 - 서브게임 4/6에서 러너가 AWAY LEG(우리가 Thief로 플레이)로 넘어가는 모습입니다. 보드에 B 장애물과 ! 캡처가 남아 있습니다.

어웨이 레그와 장애물

노드를 부팅하면 공유 가능한 엔드포인트가 미널에 출혁됩니다(단일 프로세스: 서버 + 널 + 제어판):

Control panel  >  http://127.0.0.1:8800   (open in a browser)
╔══════════════════════════════════════════════════════════════════╗
║ LIVE PUBLIC MATRIX (Team Alpha)                                   ║
╠══════════════════════════════════════════════════════════════════╣
║ COP   (:8001)  https://acting-tomorrow-yard-raid.trycloudflare.com/mcp/   ║
║ THIEF (:8002)  https://dial-mean-courses-tramadol.trycloudflare.com/mcp/  ║
╚══════════════════════════════════════════════════════════════════╝
Tunnels live and written to config/setup.json. Share these /mcp/ URLs. Ctrl+C to stop.

아키텍처

계층

모듈

역활

도메인

domain/

불변 DecPomdpGameState, Grid, 지오메트리, NL 이동 언어([INTENT: …]).

전략

domain/strategy/

minimax(alpha-beta), evaluation/features(Angel–Devil), selfplay(RL), Q-table 베이스라인.

SDK

sdk/

CopThiefSDK 단일 진입점; MatchCoorinator 종료/포획-사망 로직; 전쟁/인젝션 스크리닝.

게이트키퍼

infra/gatekeeper/

모든 LLM/Gmail 호출에 대한 FIFO 병목 지점; DeepSeek→Anthropic 장애 조치; 토큰 텔레메트리.

서버

servers/

Cop & Thief FastMCP 서버; 토큰 인증; request_move 도구 → StrategyResolvver.

전송

infra/network/

streamable-HTTP /mcp 호스트, RemoteMoveClient, Cloudflare 스위치보드.

오케스트레이션

orchestrator/

ChallengeRunner(크로스 호스트, 레그별), reconcile(상호 합의 / 0-0), 시리즈.

UI

ui/

제어판 백엔드(server.py), NodeState, 브로드스트 SSE 버스, static/panel.html.

리포팅

reporting/

Gmail OAath 리포터(제목 + 본문에 그룹 이므), 추가 전용 감사 로그, 안전 가드.

진입점

명령

설명

python -m cop_thief.app

제어판: 서버 + 널 + 웹 UI(메인).

python -m cop_thief.challenge

대화형 미널 크로스 호스트 린지(상대 URL 입혁 프롬프트).

python -m cop_thief.serve

서버 + 널만(UI 없음).

python -m cop_thief.inf ra.network.dual_mcp_host

두 개의 MCP 서버만(:8001/:8002 /mcp).

python -m cop_thief.diagnostic_runner

오프라인, 무비용 추적 프로브(모의 LLM).


전략 한 문단 요약

request_move는 제로섬 마르코프 게임(Cop은 최대화, Thief는 최소화, 최적 적대자 가정)에 대한 깊이 제한 alpha-beta minimax로 응답됩니다. 진행도에 따라 형태가 만들이진 종료 점수(±WIN ∓ turns)는 정책이 캡처/생존을 압박하도록 하므로, 무승부가 구조적으로 방지됩니다. Cop의 행동 집합에는 인접 를 벼으로 막기(Conway "Devil" 이동, §4.3)가 포함됩니다. 평가의 containment 특징은 Thief의 플러드 필(fllood-fill) 탈출 영역이므로, 플래너는 법적 몰이-포위 라인을 스스로 발경합니다. 선형 평가 가중치는 self-play TD(selfplay.train_weights)로 조정할 수 있습니다. 세 가지 변형 프롬필(공격적 / 균형 / 수비적)이 요구되는 3-에이전트 로스터를 구성합니다. 전체 설계: docs/STRATEGY.md.


형식 모델 - Dec-POMDP

추적 게임은 **분산형 부분 관측 마르코프 결정 과정(Decentralized, Partially-Observable Makov Decision Process)**으로 모델링되며, 트플 ⟨ n, S, {A}, P, R, {Ω}, O, γ ⟩ (ex06 §11)로 표현됩니다:

기호

의미

이 프로젝트에서

n

에이전트

2 - Cop과 Thief(독립적, 공유 메모리 없음).

S

상태 공간

DecPomdpGameState: cop_pos, thief_pos ∈ 5×5 그리드, barriers ⊆ G 집합(≤ 5), cop_barriers_left, turn_coun ter, turn_role. 결합 위치 공간은 (·C)² = 625로 제한됩니다. 장벽이 있으면 도달 가능한 공간은 더 커지지만 유한합니다.

A

에이전트별 행동

Cop: 8방향 King 이동(Chebyshev ≤ 1) ∪ 인접한 빈 에 장벽 설치(제자리 유지) ∪ HOLD. Thief: 8방향 King 이동 ∪ HOLD. "Stay"는 화 이동입니다.

P

전이

결정적 보드 상태 머신(apply_ation): 턴당 하나의 변이. 불법 이동(보드 밖 / 장벽 위 / King이 아닌 이동)은 거부됩니다. 장벽 턴에는 지정된 인접 셀이 벽이 되고 Cop은 제자리에 머뭅니다.

R

보상

불변 표 1: 캡처 → Cop +20 / Thief +5; 회피 → Cop +5 / Thief +10. 플래너는 진행도에 따라 형태가 만들어진 종료 값(±WIN ∓ turns)을 사용하므로 경기는 엄격히 결정적입니다(무승부 없음).

Ωᵢ

관측 공간

에이전트별 주관적 관점: 시야 반경 내에 있으면 정확한 상대 좌표를 그 경우에만(iff) 제공하고, 그 외에는 정성적 폐색 섹터를 제공합니다(예: THIEF_IN_NORTHWEST_QUADRANT).

O

관측 함수

get_subjective_observation(role, radius) - 맨해튼 거리가 vision.radius(기본 2) 이하일 때 상대를 드러내고, 그 외에는 사분면만 제공합니다. 양쪽 역할에 대해 대칭입니다(안개 전쟁).

γ

할인율

self-play TD / Q 베이스라인의 경우 rl.gamma = 0.9. minimax 계층은 대신 진행도에 따라 형태가 만들어진 종료 점수를 사용하여 캡처/생존을 압박합니다.

부분 관측성은 실제입니다. 각 에이전트는 보드에 대한 믿음(마지막 관측 + 파싱된 상대방 문장)을 기반으로 결정하며, 전역 실제 상태(ground truth)로는 절대 결정하지 않습니다.

오케스트레이션 과제 (어려운 부분)

ex06 §14에 따르면 이 과제의 가치는 승리가 아닌 오케스트레이션입니다. 어려운 문제들과 그 해결 방법은 다음과 같습니다:

  • 자유 자연어, 사전 정의된 프로토콜 없음. 에이전트는 자연어 문장으로 대화합니다. 우리는 얇은 결정적 계약을 쌓습니다 - 모든 메시지는 정확히 하나의 신호 [INTENT: MOVE|BARRIER|HOLD]로 시작하고 그 뒤에 방향 단어가 옵니다 - 따라서 이동은 기계가 해석 가능하고 본문은 자유 NL로 유지됩니다. 이는 공유 코드베이스 없이 독립적으로 구축된 두 엔진이 보조를 맞추게 합니다.

  • 언어적 모호성 및 신할 수 없는 입력. 수신 산문은 결정적으로 파싱됩니다(최장 일치 방향 단어, 괄호로만 된 의도이므로 꾸밈 텎스트가 속일 수 없음). 구조화되지 않은 상대 텎스트에는 선택적 LLM 파싱을 사용합니다; 신뢰도가 낮으면 → 안전한 탐색적 폴백(크래시하지 않고, 캡처를 위조하지 않음). 모든 필드는 적대적으로 취급됩니다 - 예: 비숫자 variant는 강제 변환되며, 절대 신뢰되지 않습니다.

  • 상호 이해 보장. 양쪽 피어는 결정적 이동 언어를 공유합니다(LLM이 필요 없는 인코딩/파싱), 그래서 게임은 바이트 단위로 재현 가능합니다. 끝에서 양측은 표준 sub_games를 해시합니다 (SHA-256, K3); 불일치가 있으면 양쪽 모두 0/0 - 합의는 가정이 아니라 강제됩니다.

  • 신뢰할 수 없는 네트워크에서의 라이브니스. 호스트 간 이동은 재연결로 재시도합니다; 지속적인 장애 또는 정지된 피어(이동당 20초 타임아웃)가 해당 하위 게임을 몰수하므로, 시리즈는 항상 6개를 모두 완료하고 보고서는 여전히 이메일로 발송됩니다 - 죽은 상대는 경기를 지연시킬 수 없습니다.

시각화 및 결정적 증명 (§11)

  • GUI - 위의 스크린샷은 라이브 5×5 보드, [INTENT: …] 통신 가로채기 피드, 장애물(B), 캡처(!), 그리고 레그 전환을 보여줍니다.

  • 클라우드 MCP 통신 - 위의 부트 블록은 라이브 공개 Cloudflare /mcp/ URL를 출력하고, 패널의 통신 피드는 클라우드 서버와 교환된 실제 [INTENT:] 전송을 스트리밍니다; 모든 언은 data/game_audit.jsonl에 추가되고 변조 방지된 게임별 아카이브로 봉인됩니다 (data/archve/, 보고서에 번들 SHA-256 포함).

  • 학습 - 전략 가중치는 자기 대결 TD(selfplay.train_weights)로 튜닝됩니다; 비교를 위해 테이블 기반 Q-learing 기준선이 유지됩니다. 설계 + 곡선: docs/STRATEGY.md.

보안 및 공정한 플레이

  • 토큰 - 모든 MCP 도구 호출에는 역할별로 취소 가능한 bearer 토큰이 필요합니다; 대역 외로 교환되며, 회전시켜 취소할 수 있습니다. 서버는 fail-closed입니다.

  • 인젝션 방지 - 수신 전송은 신뢰할 수 없습니다; 인젝션/강제 변환/사칭/위조는 검사되어 data/game_audit.jsonlhostile:true로 표시되고, 보고서에 집계되며, 엔진이 결정한 결과에 영향을 미치지 않습니다. 조약(§F)에서 상대방을 위해 명문화되어 있습니다.

  • 상호 합의 - 양측은 표준 sub_games를 해시합니다; 불일치 시 ⇒ 0/0 (both_lose).

  • 보고 - OAuth2 Desktop을 통한 Gmail API(범위 gmail.modify, 비밀번호 0개); 그룹 이름은 제목 줄과 JSON 본문 모두에 포함됩니다; 안전 가드는 기본적으로 임시 받은편지함을 사용합니다.


토큰 예산 및 비용

모든 외부 호출은 API GatekeeperTokenTracker를 통해 계량되며, 이는 실시간 사용량을 data/token_usage.json으로 스트리밍합니다(원자적 쓰기; K3 합의 해시에서 제외되어 비용이 결과에 영향을 미치지 않음). 모든 수치는 구성 기반입니다(config/setup.json → token_budget / economics).

제공자 (역할)

입력 $/M

출력 $/M

DeepSeek deepseek-chat (기본)

0.15

0.60

Anthropic claude-3-5-sonnet (장애 조치 전용)

3.00

15.00

예산 항목

현재까지 실제 지출(모든 실행 합산)

≈ $0.01

수명 주기 예산

200,000 입력 + 50,000 출력 토큰

→ 예상 수명 주기 비용(기본)

~$0.06

턴당 예상치(입력 120 / 출력 40)

~$0.00004

상한선(80 %에서 경고)

$0.50 (경고 $0.40)

집행

gatekeeper는 상한선에서 청구 가능한 LLM 호출에 대해 BudgetExceeded를 반환합니다 - 절대 크래시하지 않음

실제로 전체 프로젝트는 LLM에 약 $0.01이 들었습니다. 이동은 로컬 미니맥스 엔진에서 나오며 이동 언어는 결정적 [INTENT: …] 인코딩/파싱입니다 - 플레이하거나 보고서를 보내는 데 LLM이 필요 없습니다(Gmail API이지 LLM이 아님). 작은 예산 + DeepSeek 우선 장애 조치는 선택적 LLM 지원 자연어 파싱을 위한 가드레일입니다; 상한선은 충분한 여유를 두고 $0.50로 설정되어 있습니다.

비밀 및 구성

  • .env-example.env로 복사하고 채우세요: DEEPSEEK_API_KEY, ANTHROPIC_API_KEY, COP_MCP_TOKEN, THIEF_MCP_TOKEN, GMAIL_CREDENTIALS_PATH. 제로 의존성 자동 로더가 시작 시 .env를 주입합니다 - export/source가 필요 없습니다; 기존 셸 export가 항상 우선합니다.

  • 모든 조정 가능한 값은 버전 관리되는 config/*.json에 있습니다(하드코딩 없음). 비밀(.env, credentials.json, token.json)은 git에서 무시되며 소스 제어에 절대 들어가지 않습니다.

문서

PRD · PLAN · TODO · STRATEGY · RULES_AND_AGREEMENTS · INTER_GROUP_TREATY_SPEC

라이선스

MIT.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/najikay/mcp-marl-pursuit'

If you have feedback or need assistance with the MCP directory API, please join our Discord server