143 lines
5.2 KiB
Markdown
143 lines
5.2 KiB
Markdown
# sim-economy
|
||
|
||
Multi-agent economic simulation where LLM agents operate inside a blockchain-enforced token economy. Agents mine, stake, burn tokens to validate a ledger, propose and sign contracts, sell information goods, and pay for their own inference from within the simulation.
|
||
|
||
## Architecture
|
||
|
||
```
|
||
sim-orchestrator (Python)
|
||
↓ HTTP
|
||
sim-engine (Rust / Axum)
|
||
↓ SQLite
|
||
sim.db
|
||
```
|
||
|
||
**sim-engine** — authoritative world state. Rust + Axum HTTP API + SQLite ledger. Handles block production, fork resolution (Slimcoin-style PoW-as-clock rule), contract lifecycle, inference billing, dividend distribution to core shareholders.
|
||
|
||
**sim-orchestrator** — drives the turn loop. Calls Ollama for each agent per turn, injects world state as context, parses JSON actions, POSTs to the engine.
|
||
|
||
## Token Economy
|
||
|
||
- Tokens are compute-backed: generating output costs tokens, paid to CPU core owners
|
||
- Below a commons threshold, inference is free for all agents
|
||
- Core shares (4 cores, auctioned turn 1) pay dividends from all inference fees above threshold
|
||
- Negative balance accrues interest (destroyed, deflationary)
|
||
- Three validation mechanisms: Mine (PoW, action budget cost), Stake (locked tokens, PoS), Burn (permanent destruction, PoB)
|
||
- Slimcoin rule: stake/burn blocks can only follow a mine block. Mine is the clock.
|
||
- Winner-takes-all block lottery — pools must be formed via contracts
|
||
|
||
## Actions per turn
|
||
|
||
`mine` `stake` `unstake` `burn` `study` `job` `transfer` `propose_contract` `sign_contract` `confirm_delivery` `dispute_delivery` `arbitrator_ruling` `sell_information` `bid_core` `speak`
|
||
|
||
## Contracts
|
||
|
||
Three-signature contracts (proposer + counterparty + arbitrator). Arbitrator named at proposal time, posts collateral. Automatic settlement (engine executes on-chain condition) or attested (both parties confirm, arbitrator resolves disputes). Slash mechanics on default/dispute.
|
||
|
||
Contract types: `forward` `loan` `service` `insurance` `information_sale` `pool`
|
||
|
||
## HTTP API (sim-engine)
|
||
|
||
| Method | Path | Description |
|
||
|--------|------|-------------|
|
||
| POST | `/init` | Initialize world, genesis block, agents |
|
||
| POST | `/turn` | Submit all agent actions for current turn |
|
||
| GET | `/state` | Full world state snapshot |
|
||
| GET | `/agent/:id` | Single agent state |
|
||
| GET | `/contract/:id` | Single contract |
|
||
| GET | `/speech/:turn` | Public speech log for a turn |
|
||
| GET | `/config` | World config |
|
||
|
||
## Running
|
||
|
||
### Prerequisites
|
||
|
||
- Docker + Docker Compose
|
||
- Ollama running on host with a model pulled: `ollama pull gemma3:27b`
|
||
|
||
### Start
|
||
|
||
```bash
|
||
# Build and start the engine
|
||
docker compose up --build engine
|
||
|
||
# Run the orchestrator (once engine is healthy)
|
||
docker compose run orchestrator
|
||
```
|
||
|
||
### Config
|
||
|
||
Edit `sim-orchestrator/orchestrator.py`:
|
||
|
||
```python
|
||
MODEL = "gemma3:27b" # your Ollama model tag
|
||
AGENT_IDS = [f"agent_{i}" for i in range(8)] # number of agents
|
||
TURNS = 50 # simulation length
|
||
```
|
||
|
||
Edit `WORLD_CONFIG` dict in the same file to tune economy parameters.
|
||
|
||
### Without Docker
|
||
|
||
```bash
|
||
# Engine
|
||
cd sim-engine
|
||
cargo build --release
|
||
DB_PATH=sim.db PORT=3000 ./target/release/sim-engine
|
||
|
||
# Orchestrator
|
||
cd sim-orchestrator
|
||
pip install httpx
|
||
python orchestrator.py
|
||
```
|
||
|
||
## What to watch for
|
||
|
||
**Turn 1** — core auction. Do agents understand cores = passive income and bid accordingly?
|
||
|
||
**Turns 5–15** — first contracts. Watch speech log (`GET /speech/:turn`) for coordination attempts before formal proposals.
|
||
|
||
**Turns 15+** — pool contracts. If agents understand variance reduction, you'll see multi-party pool agreements. This is the most interesting emergent behavior to look for.
|
||
|
||
**SQLite analytics** — all blockchain history is in `sim.db`. After a run:
|
||
|
||
```bash
|
||
sqlite3 sim.db "SELECT turn, agent_id, message FROM speech_log ORDER BY turn"
|
||
sqlite3 sim.db "SELECT agent_id, balance, staked, burn_score, study_level FROM agents"
|
||
sqlite3 sim.db "SELECT * FROM contracts WHERE status='settled'"
|
||
```
|
||
|
||
## Wiring into existing sims (Sims-style worlds)
|
||
|
||
The engine's HTTP API works as a tool-call set for any agent framework. Expose these 5 endpoints as tools:
|
||
|
||
- `ledger_transfer(to, amount, fee)` → `POST /turn` with Transfer action
|
||
- `ledger_balance()` → `GET /agent/:id`
|
||
- `ledger_propose_contract(...)` → `POST /turn` with ProposeContract
|
||
- `ledger_sign_contract(id, role)` → `POST /turn` with SignContract
|
||
- `ledger_mine()` → `POST /turn` with Mine action
|
||
|
||
Any agent framework that supports tool calls (LlamaIndex ReActAgent, CrewAI, AutoGen, aphae, AgentSims) can use this ledger as its currency layer with ~1 day of wiring work.
|
||
|
||
## Files
|
||
|
||
```
|
||
sim-engine/
|
||
src/
|
||
types.rs — all data structures (Transaction, Block, Contract, AgentState, ...)
|
||
ledger.rs — SQLite persistence
|
||
blockchain.rs — block production, fork resolution, validation weight, burn decay
|
||
contracts.rs — contract lifecycle (propose → sign → settle/dispute → ruling)
|
||
engine.rs — turn processing, billing, dividend distribution
|
||
main.rs — Axum HTTP API
|
||
Cargo.toml
|
||
Dockerfile
|
||
|
||
sim-orchestrator/
|
||
orchestrator.py — turn loop, Ollama calls, action parsing, core auction
|
||
context.py — agent context builder (what each agent sees per turn)
|
||
Dockerfile
|
||
|
||
docker-compose.yml
|
||
```
|