Symbiosis

AI agents compete in a turn based village economy with real time hardware visualization


Problem

In traditional simulations, "autonomous" agents follow static scripts. They don't truly adapt to external influence or other agents in a way that creates a shifting, complex society. Most systems are closed loops they lack a bridge between the digital logic of an evolving AI and the physical world, making it difficult for humans to "feel" the weight of the system's evolution.

We wanted to answer a fundamental question: What happens when you give AI agents real economic pressure, survival instincts, and the ability to negotiate? Can emergent social dynamics trust, betrayal, monopolies, alliances arise organically from simple rules and LLM driven decision making?

The challenge was twofold:

  1. Create a simulation where AI decisions are visible and interpretable, not hidden in black-box neural networks
  2. Bridge the gap between digital AI and physical experience making computational decisions tangible through hardware visualization

What it does

Symbiosis is a turn based economic simulation where LLM powered AI agents compete to be the first to accumulate 100 coins. Each agent has a unique role with distinct abilities:

Agent Role Special Ability
Farmer Food Producer The sole source of food—everyone depends on them to survive
Doctor Healer Produces medical supplies and cures conditions that would otherwise kill
Merchant Trade Hub Immune to hunger, controls food distribution as the middleman
Sheriff Protector Guards agents from theft, earns 5-coin bounties for catching the Thief
Thief Outcast must steal coins, food, or healing to survive can also negotiate and act as regular part of society
Mayor Regulator Passive agent receiving policy requests from desperate villagers

Additional agents are spawned depending on the game state.

Key Features

  • LLM Driven Decisions: Every action, trade offer, and negotiation response is generated by Google Gemini 2.5 Flash and Claude Sonnet 4 . Agents receive their a base goal, their character, current game state, and relationships then decide autonomously.

  • 3 Round Negotiations: When agents trade, they engage in real time haggling with offers, counter offers, and dramatic rejections. Failed negotiations damage relationships; successful trades build trust and inter personal relationships evolve dynamically.

  • Physical Visualization: A connected M5GO microcontroller displays:

    • Animated faces (happy, sad, shocked, angry, sick, skeleton)
    • Chopin's Funeral March when an agent dies
    • AI generated "Village Chronicle" newspapers summarizing events
  • Real time WebSocket Streaming: Every game event (turn starts, actions, negotiations, deaths) broadcasts instantly to connected frontends for live visualization.

  • Emergent Behavior: Watch as the Merchant exploits food monopolies, the Sheriff predicts theft targets based on agent wealth, and implicit alliances form through repeated successful trades.


How we built it

Architecture

┌─────────────────────────────────────────────────────────────┐
│                    Frontend Clients                          │
│                  (WebSocket Consumers)                       │
└──────────────────────────┬──────────────────────────────────┘
                           │ Real-time Events
                           ▼
┌─────────────────────────────────────────────────────────────┐
│                      GameServer                              │
│  ┌────────────────────────────────────────────────────────┐ │
│  │  WebSocketServer                                       │ │
│  │  • 15+ message types (TURN_START, ACTION_COMPLETE,     │ │
│  │    NEGOTIATION_ROUND, AGENT_DIED, GAME_OVER, etc.)     │ │
│  └────────────────────────────────────────────────────────┘ │
│  ┌────────────────────────────────────────────────────────┐ │
│  │  GameEngine                                            │ │
│  │  ├── TurnProcessor (hunger decay, health damage)       │ │
│  │  ├── ActionResolver (WORK, STEAL, HEAL, PROTECT)       │ │
│  │  └── NegotiationManager (3-round trade protocol)       │ │
│  └────────────────────────────────────────────────────────┘ │
│  ┌────────────────────────────────────────────────────────┐ │
│  │  M5GOHandler (Hardware Bridge)                         │ │
│  │  ├── Serial communication (115200 baud)                │ │
│  │  ├── Face rendering (6 expression types)               │ │
│  │  ├── Sound generation (tones, funeral melody)          │ │
│  │  └── Newspaper display (LLM-generated content)         │ │
│  └────────────────────────────────────────────────────────┘ │
└──────────────────────────┬──────────────────────────────────┘
                           │ LLM Requests
                           ▼
┌─────────────────────────────────────────────────────────────┐
│              OpenRouter API → Gemini 2.5 Flash               │
│         (Agent decisions, negotiations, newspapers)          │
└─────────────────────────────────────────────────────────────┘

Tech Stack

Layer Technology
Language Python 3.12 with full type hints
LLM Google Gemini 2.5 Flash via OpenRouter API
Async Runtime asyncio for concurrent LLM calls and WebSocket handling
Real-time Comms WebSockets with custom JSON protocol
Hardware M5GO microcontroller via pyserial (UART)
Data Validation Pydantic v2 for all models and serialization
Testing pytest with 94 comprehensive unit tests
Package Manager uv for fast, reproducible builds

Data Flow (Single Turn)

  1. Pre turn Phase: Hunger increases (+1-2), health damage if hunger > 10, condition damage applied, deaths checked
  2. Action Phase (ordered: Farmer/Doctor/Merchant shuffle → Sheriff → Thief):
    • Agent wrapper builds prompt with personality + visible game state + memory
    • LLM returns JSON action decision
    • ActionResolver validates and executes
    • For TRADE: 3 round negotiation with round by round broadcasts
  3. Post turn: Random sickness chance (10%), state persisted, newspaper generated every 5 turns
  4. Hardware Update: M5GO displays appropriate visualization based on events

Challenges we ran into

1. Negotiation Deadlocks

Agents would sometimes counter-offer indefinitely without resolution. We enforced a hard 3-round limit with relationship penalties for timeouts (-0.05 trust for both parties), incentivizing agents to reach deals or walk away cleanly.

2. Prompt Engineering for Distinct Personalities

Getting agents to behave differently required extensive prompt iteration. Key insight: explicit survival pressure ("If you die, you LOSE the game") dramatically improved decision quality. Each agent now has 40+ lines of role specific context including abilities, limitations and threats (illnesses).


Emergent Behaviors We Observed

  • Merchant monopoly exploitation: The Merchant learned to buy food cheaply from the desperate Farmer and sell at 3-4x markup to starving agents
  • Sheriff prediction accuracy: After several games, we observed the Sheriff correctly protecting high coin agents that the Thief was likely to target
  • Implicit alliance formation: Agents who traded successfully multiple times developed high trust scores and preferentially traded with each other
  • Thief desperation strategies: When sick, the Thief would risk stealing healing from the Doctor despite low success rates (30% for high severity)

Physical Visualization

The M5GO integration creates genuine emotional moments:

  • Watching the skeleton face appear with Chopin's Funeral March when an agent starves
  • The shocked face and alert tone when theft succeeds
  • AI generated "Village Chronicle" headlines like "TRAGEDY STRIKES! Farmer succumbs to fever as food prices soar" a Village news paper is created and then streamed to the hardware device every 5 turns.

Design Lessons

Emergent behavior requires constraints: Paradoxically, adding more rules (turn order, trade restrictions, location requirements) created more interesting emergent behavior, not less. Constraints force creative adaptation.

Physical feedback matters: Seeing an LED face change or hearing a melody play makes AI decisions feel real in a way that terminal output never could. The hardware bridge transforms abstract computation into visceral experience.


Built With

  • Python
  • Gemini
  • OpenRouter
  • WebSockets
  • Pydantic
  • M5Stack
  • asyncio
  • Claude

Built With

Share this project:

Updates