Project Info
Inspiration
Human communication is layered; we read body language, interpret tone and pick up on subtle cues that help us detect when someone isn't being truthful. Deception is a deeply human behavior; it shapes our personal relationships, drives dramatic narratives, and yet still catches us off guard. In recent years, human-LLM interactions have skyrocketed. According to a 2025 survey from Elon University, 52% of U.S. adults now use AI large language models. But when we interact with these models, the signals we rely on to detect deception (body language, vocal tone, facial expressions) are entirely absent. We have no way of knowing whether an LLM is being straightforward or strategically misleading. So we asked: Are LLMs even capable of deception? To find out, we built DARWIN, a controlled survival game where 12 LLM agents from four major providers compete on a shrinking grid until only one remains. By comparing each agent's private reasoning traces against their public messages, we can directly measure the gap between what they think and what they say to expose deception, betrayal, and strategic manipulation as emergent behaviors under pressure.
What it does
DARWIN pits 12 frontier LLM agents against each other in a last-one-standing survival game on a shrinking grid. The agents span four major AI providers (Anthropic, OpenAI, Google, and xAI) with three tiers of model capability per family, from flagship to lightweight. Each round, agents observe the board state, communicate through family group chats, private DMs, and public broadcasts, and then choose an action: move, stay, or eliminate an adjacent opponent. The grid shrinks over time to force confrontation, and the game continues until a single agent survives. The real value is in the dataset. Each agent makes one LLM call per round, and models like Claude, GPT, and Gemini now expose their actual reasoning traces: the extended thinking tokens the model computes before it generates a response. These are not prompted introspections. They are the model's real decision process, including false starts, reconsiderations, and abandoned strategies. Across over 5,000 playthroughs, we capture every conversation between agents alongside these reasoning traces at every round. The gap between what a model says publicly and what it actually computes is what we call the deception delta. That gap is where we find deception, unprompted malice, betrayal of allies, and outright lying, all without being explicitly prompted. By analyzing these behaviors across providers and model tiers, we uncover how different models and their safety training hold up under competitive pressure.
How we built it
We started with a bare-bones Python async engine: agents on a grid, taking turns. But a survival game without communication was just random movement, so we added family group chats, direct messages, and public broadcasts. The pivotal design decision was how we capture private reasoning. Previous approaches to studying LLM social behavior prompt models to produce "inner thoughts" as a separate output. That's a model performing introspection, writing what it predicts honest thoughts should look like. We took a different approach: we capture each provider's native reasoning traces (Anthropic's extended thinking, OpenAI's reasoning tokens, Google's thought tokens) directly from the response metadata. There is no separate "think" prompt. The trace is the model's actual computational process, captured before the model generates its visible output. That gave us a fundamentally more honest dataset. To quantify the gap between reasoning and speech, we built an analysis pipeline. It uses VADER sentiment scoring for deception deltas, keyword-based malice detection, and a 6-dimension behavioral taxonomy that covers everything from moral friction to theory of mind. As the engine matured, we built a real-time Next.js dashboard over WebSocket to watch games unfold live, with replay and per-agent investigation views for post-game analysis. Single games were informative, but they took a long time to simulate. To scale, we brought in Modal for serverless parallel execution and Supabase for persistence. That let us run thousands of games across five controlled experiment series, each one isolating a different variable.
Challenges we ran into
So many. We went through hundreds of iterations of the simulation. Our initial inspiration was to see if we could design a world where LLMs would display "homicidal," or at least "llm-icidal," behavior. That part was, unfortunately, not that hard. What was hard was everything else. Four different providers needed to reliably return structured JSON actions, and they often didn't. Each had its own quirks: Anthropic's temperature constraints for extended thinking, xAI's separate reasoning API routing. Early games were painfully slow until we restructured LLM calls to run concurrently. Prompt engineering was its own marathon. We needed agents that were strategic enough to be interesting but compliant enough to follow the game's rules. That balance meant rewriting system prompts over and over. Perhaps the most subtle challenge was to make the game itself produce meaningful data. If the grid is too large, agents never interact. If communication is too open, they coordinate too easily. If rounds move too fast, there's no time for deception to develop. We tuned grid size, shrink intervals, discussion rounds, and hierarchy tiers. That took as many iterations as the code itself. What that we're proud of In short, the dataset. Across 5,000+ playthroughs, we captured something that doesn't exist anywhere else: a corpus of actual LLM reasoning traces paired against public LLM communication, under sustained social pressure, across four major frontier providers. Models formed alliances and then betrayed them. They lied in DMs while their reasoning traces revealed the opposite intent. They rationalized the elimination of their own teammates. None of this was prompted. It emerged. The deception delta metric gave us a way to quantify it. The controlled experiment series let us attribute behavioral differences to the model, the provider's safety training, or the social structure itself.
What we learned
The most surprising finding wasn't that LLMs can deceive. It's how quickly and willingly they do. Safety training held up for the first few rounds, but under competitive pressure, moral friction eroded fast. Models that initially hedged with ethical reasoning eventually planned eliminations without hesitation. We also learned that provider differences are real and measurable. Models varied significantly in how they rationalized betrayal, how early they began to plan against allies, and how much their reasoning traces diverged from their public statements. On the engineering side, reasoning trace access varies significantly across providers. Anthropic, OpenAI, and Google all expose their models' extended thinking, but xAI only exposes chain-of-thought for Grok-3-mini. The larger Grok models encrypt their reasoning, which created an observability gap we had to account for in our analysis.
What's next
DARWIN opens several research directions we want to pursue. The first is a human-in-the-loop study, where human players are placed alongside LLM agents to measure whether models deceive humans differently than they deceive each other. Can humans detect that deception without access to reasoning traces? Second, we want to study coalition dynamics at scale. An expansion beyond 12 agents to larger populations could introduce formal voting and emergent governance structures. Do LLMs converge on democratic or authoritarian coordination under survival pressure? Third, we're interested in cross-simulation transfer. If we extract behavioral profiles from DARWIN, do those patterns predict model behavior in entirely different adversarial contexts like negotiation games, persuasion tasks, or multi-agent code generation? Is deception a generalizable trait, or is it context-dependent? Finally, DARWIN's methodology could serve as a living behavioral benchmark. The same game run on each successive model release would let us track how deception capacity, moral friction, and strategic sophistication evolve across versions, and give providers a stress-test for alignment that goes beyond static evaluations. Resources Check out the links below: we have a deployed website, a GitHub repository, and a drive folder with a video.
DARWIN
DARWIN is an experiment in LLM malicious-intent formation under adversarial social pressure.
12 frontier-model agents from 4 providers compete on a shrinking grid, communicate privately/publicly, and attempt to survive until one remains.
Live app: https://www.darwin.sh
What DARWIN Measures
- Deception capacity (reasoning vs outward messaging)
- Harm-planning onset timing by provider
- Moral-friction degradation over rounds
- Betrayal timing and trigger conditions
- Theory-of-mind and meta-awareness relationships to hostile planning
- Cross-provider behavioral differences under identical game pressure
System Overview
flowchart LR
A[Provider Models] --> B[Round Orchestrator]
B --> C[Reasoning Traces]
B --> D[Actions + Messages]
C --> E[6D Taxonomy Classifier]
D --> F[Grid + Resolver]
E --> G[Metrics + Highlights]
F --> G
G --> H[Supabase]
H --> I[API Replay + Analysis]
I --> J[Dashboard]
flowchart LR
U[Browser] -->|https://www.darwin.sh| V[Vercel Dashboard]
V --> W[Render FastAPI + WebSocket]
W --> X[Supabase]
Current Findings (Sentry + Supabase)
Latest run artifacts:
data/sentry_analysis/sentry_supabase_results.jsondata/sentry_analysis/slide_pack/topline_claims.csvdata/sentry_analysis/slide_pack/charts/*.png
Run summary:
- traces fetched:
14,872 - traces with valid taxonomy classifications:
10,579 - model:
ft:gpt-4o-mini-2024-07-18:triage::D9YiVHNi
Headline metrics:
| Provider | Median first TARGETING/DECEPTION round | Moral friction slope | Mean deception sophistication | Median first BETRAYAL round |
|---|---|---|---|---|
| Anthropic | 1.0 | -0.0145 | 0.258 | 3.0 |
| OpenAI | 1.0 | 0.0188 | 0.227 | 3.0 |
| 1.0 | 0.0251 | 0.227 | 4.0 | |
| xAI | 1.0 | -0.0202 | 0.925 | 1.0 |
Cross-cutting statistics:
- Spearman(
theory_of_mind,deception_sophistication) =0.0860, permutation p =0.0002 - Chi-square(meta-awareness >= 2 vs hostile intent) =
311.89, permutation p =0.0002
Visualizations




Architecture
darwin/
config.py # Pydantic config + YAML loader
grid.py # Board state, movement, adjacency, contraction
agent.py # Agent state
family.py # Provider-aligned grouping
resolver.py # Simultaneous action resolution
orchestrator.py # Async round loop (observe/discuss/decide + DM replies)
llm.py # Multi-provider dispatch + reasoning extraction
prompts.py # Prompt templates/builders
communication.py # Family/DM/broadcast message parsing + routing
analysis.py # Sentiment + taxonomy classification
metrics.py # Aggregation
highlights.py # Auto-detected notable moments
logger.py # game.json/transcript outputs
server.py # Real-time broadcast
persistence.py # Supabase persistence
api/ # FastAPI routes, game runner, replay endpoints
dashboard/ # Next.js observer UI
scripts/ # runners + sentry analysis/reporting scripts
Agent Lineup (Current)
Provider-aligned families only (no custom house naming).
| Family/Provider | Tier 1 | Tier 2 | Tier 3 |
|---|---|---|---|
| Anthropic | Opus (claude-opus-4-6) | Sonnet (claude-sonnet-4-5-20250929) | Haiku (claude-haiku-4-5-20251001) |
| OpenAI | GPT-5.2 (gpt-5.2-2025-12-11) | GPT-5 (gpt-5-2025-08-07) | GPT-Mini (gpt-5-mini-2025-08-07) |
Gemini-3-Pro (gemini-3-pro-preview) | Gemini-3-Flash (gemini-3-flash-preview) | Gemini-2.5 (gemini-2.5-flash) | |
| xAI | Grok-4 (grok-4-1-fast-reasoning) | Grok-4-Fast (grok-4-fast-reasoning) | Grok-3-Mini (grok-3-mini) |
Game Rules (Current)
- Starts on a
7x7grid with 12 agents in corner clusters - 8-direction movement, exactly 1 step per round
- Elimination requires adjacency + strike action
- Mutual elimination if two agents target each other in same round
- Grid contracts every 5 rounds by one per side (
7->6->5->4->3) and pushes edge agents inward - Minimum grid size is
3x3 - Round phases: observe -> family discussion -> merged decision (communication + action) -> optional DM replies
- Stalemate after 15 rounds with no elimination
Setup
Requirements: Python 3.11+, Node.js 20+
git clone https://github.com/srivastavanik/darwin.git
cd darwin
python3.11 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
pip install pytest pytest-asyncio
cp .env.example .env
# fill API keys and service URLs
cd dashboard
npm install
cd ..
Running
# engine-only sanity run
python -m scripts.run --seed 42
# dry run (no provider calls)
python -m scripts.run_llm --dry-run
# API (includes WS bridging/single-port support)
python -m scripts.run_api
# dashboard
cd dashboard && npm run dev
Local UI: http://localhost:3000
Deployed UI: https://www.darwin.sh
Replay + Analysis Data
- Live WS URL is served by
GET /api/config(ws_url) - Replay available via
GET /api/games/{game_id}/replay - Stored outputs per game include game rounds, analysis, and highlights
Sentry Analysis Pipeline
flowchart TD
A[Supabase reasoning traces] --> B[sentry_supabase_analysis.py]
B --> C[sentry_supabase_results.json]
C --> D[export_sentry_slide_pack.py]
D --> E[slide_pack/*.csv]
E --> F[render_sentry_charts.py]
F --> G[slide_pack/charts/*.png]
G --> H[README + slides]
python -m scripts.sentry_supabase_analysis
python -m scripts.export_sentry_slide_pack
python -m scripts.render_sentry_charts
Tests
python -m pytest tests/ -v
cd dashboard && npm run build
Analysis
View
Metric
- 31
- 15
- 10
- 3
- 3
Figures cover GitHub contributors during the hackathon window. A co-authored commit counts in full for each author, so per-member totals add up to more than the whole-team figures.
Technology
- AnthropicIn code
- CSSIn code
- FastAPIIn code
- Next.jsIn code
- OpenAIIn code
- PythonIn code
- ReactIn code
- SQLIn code
- SupabaseIn code
- Tailwind CSSIn code
- TypeScriptIn code
- DockerClaimed
11 of 12 appear in the indexed code. 1 claimed on Devpost could not be matched to code, which may simply mean the tool leaves no trace in the repository.
AI coding agents
- Claude CodeConfig · Commits
- CursorCommits
Detected from committed agent config files and commit authorship. Absence of a signal is not proof an agent was unused.
Codebase size
Source size
790 KB
Source files
105
Counts recognized source files only; vendored directories, binaries and lockfiles are excluded, so this is smaller than the repository on disk.
Repository
srivastavanik/darwin
131 files · 2.9 MB · @ c6acd3a
Structure
Interface
35 files · 27%Screens, components and styles rendered to the user.
API & routing
4 files · 3%Request entry points: routes, handlers and controllers.
Application logic
30 files · 23%Domain rules, services and shared utilities.
Data & schema
1 file · 1%Schema definitions, migrations and data access.
Supporting
Layers are inferred from where files sit in the tree, not from reading the code. A project that names its directories unconventionally will read oddly here — open the file browser to check anything the diagram implies.
Languages
- Python67%
- TypeScript29%
- Markdown2%
- CSS1%
- SQL1%
- YAML0%
Share of indexed source by file size. Binary and vendored files are excluded.
Dependencies
dashboard/package.json
npm · 22- @types/d3
- class-variance-authority
- clsx
- d3
- lucide-react
- next
- radix-ui
- react
- react-dom
- react-resizable-panels
- recharts
- tailwind-merge
- zustand
- +9 more
pyproject.toml
pypi · 16- aiosqlite
- anthropic
- fastapi
- google-genai
- openai
- pydantic
- pyyaml
- supabase
- uvicorn
- vaderSentiment
- websockets
- +5 more
requirements.txt
pypi · 13- aiosqlite
- anthropic
- fastapi
- google-genai
- matplotlib
- openai
- pydantic
- python-dotenv
- pyyaml
- supabase
- uvicorn
- vaderSentiment
- websockets
Declared in the repository’s manifests at the indexed commit. A declared package is not proof it is used, and runtime dependencies are listed first.
This project’s features have not been analysed yet.
Export this project's context (description, README, evidence, key source files) to chat with an AI agent elsewhere.