Spaces:
Sleeping
Sleeping
| title: Metropolis Chess Club | |
| emoji: ♟️ | |
| colorFrom: indigo | |
| colorTo: gray | |
| sdk: docker | |
| pinned: false | |
| # Metropolis Chess Club | |
| An agentic chess character system for the virtual city Metropolis. | |
| The Chess Master is a sophisticated yet sharp-tongued player who runs the Chess Club, engaging visitors with personality, pattern recognition, and genuine competition. This is Phase 1: building the agent and memory system (no chess engine yet). | |
| ## Project Vision | |
| **Phase 1 (Current)**: Agent system with memory, relationships, and personality | |
| - Build the Chess Master character agent (Gemini 3.1 Flash Lite) | |
| - Implement memory vector database (Weaviate) with semantic search | |
| - Create async scheduler for triggering agent at various game moments | |
| - Persist player profiles and conversation history (players are remembered) | |
| - Bootstrap Chess Master's lore (backstory, history, mentors) | |
| - Iterate on personality through test games and feedback | |
| Key Phase 1 features: | |
| - **Player relationships**: Agents remembers returning players, builds familiarity | |
| - **Conversation memory**: Stores recent messages so agent can reference them | |
| - **Lore system**: Chess Master has a personal history that players discover | |
| - **Async architecture**: Non-blocking triggers, background idle monitoring | |
| **Phase 2**: Chess engine integration | |
| - Integrate python-chess + Stockfish (multiple difficulty levels) | |
| - Connect agent to game state (odds, moves, time, board hints) | |
| - Persist match history to Postgres database | |
| - Agent can comment on move quality, suggest improvements, tease blunders | |
| **Future**: Visual representation, emotion display, multi-modal interaction, connection to other Metropolis properties | |
| ## Architecture | |
| ``` | |
| metropolis-chess-club/ | |
| ├── agent/ | |
| │ ├── main_agent.py # Chess Master conversational agent | |
| │ ├── subconscious.py # Memory manager | |
| │ ├── scheduler.py # Trigger points and timing | |
| │ ├── personality.md # Character definition | |
| │ └── tools.py # [TODO] Tool definitions | |
| │ | |
| ├── memory/ | |
| │ ├── weaviate_client.py # [TODO] Vector DB client | |
| │ ├── schemas.py # Memory schema definitions | |
| │ └── retrieval.py # [TODO] Query logic | |
| │ | |
| ├── models/ | |
| │ ├── claude_api.py # [TODO] Claude API wrapper | |
| │ ├── gemini_api.py # [TODO] Gemini API wrapper | |
| │ └── base.py # [TODO] Abstract interface | |
| │ | |
| ├── config/ | |
| │ └── settings.py # Environment configuration | |
| │ | |
| ├── tests/ # [TODO] Test suite | |
| │ | |
| ├── requirements.txt # Python dependencies | |
| ├── .gitignore | |
| └── README.md | |
| ``` | |
| ## Quick Start | |
| ### 1. Setup | |
| ```bash | |
| python -m venv venv | |
| source venv/bin/activate # or `venv\Scripts\activate` on Windows | |
| pip install -r requirements.txt | |
| ``` | |
| ### 2. Environment | |
| Create a `.env` file: | |
| ``` | |
| # Gemini (primary) | |
| LLM_PROVIDER=gemini | |
| GEMINI_API_KEY=your_gemini_key_here | |
| GEMINI_MODEL=gemini-3.1-flash-lite-preview | |
| # Or Claude (fallback): | |
| # CLAUDE_API_KEY=your_claude_key_here | |
| # CLAUDE_MODEL=claude-opus-4-20250514 | |
| # Weaviate | |
| WEAVIATE_EMBEDDED=true | |
| WEAVIATE_URL=http://localhost:8080 | |
| # Database (for Phase 2, player profiles for Phase 1) | |
| # DATABASE_URL=sqlite:///chess_club.db | |
| # Game defaults | |
| DEFAULT_USERNAME=Opponent | |
| DEFAULT_DIFFICULTY=intermediate | |
| ``` | |
| ### 3. Run | |
| ```bash | |
| # [TODO] Once main loop is implemented | |
| python -m agent.main | |
| ``` | |
| ## Key Design Decisions | |
| ### Memory System | |
| Memories are stored in Weaviate with semantic search. Each memory includes: | |
| - **content**: The actual memory text (what gets embedded) | |
| - **timestamp**: When created (preserved for recency awareness) | |
| - **memory_type**: Category (player_behavior, player_observation, game_context, personal_note, pattern, streak, emotional, lore) | |
| - **related_match_id**: Optional connection to a specific chess match | |
| - **related_player_id**: Optional connection to a specific player | |
| - **created_by**: Which agent created it (main_agent or subconscious) | |
| - **metadata**: Additional context (player_name, difficulty, opening_name, etc.) | |
| **Why this schema?** | |
| - Type tags enable targeted retrieval ("find player behavior patterns", "find my lore") | |
| - Timestamps are preserved, not decayed—the agent knows memory recency | |
| - `related_player_id` enables player-specific memory queries | |
| - Metadata allows extensibility without schema migration | |
| - `created_by` prevents memory loops (subconscious won't re-provide its own recent memories) | |
| ### Player Persistence | |
| For each player, the system maintains: | |
| - **Player Profile**: First seen, last played, total games, win/loss record, relationship state | |
| - **Conversation History**: Recent messages so the agent can reference them | |
| - **Memory Search**: Filtered by `related_player_id` for player-specific insights | |
| This enables: | |
| - Agent remembers returning players across sessions | |
| - Agent can reference past games: "You're playing the Sicilian again" | |
| - Agent builds familiarity and warmth over time | |
| - Newcomers get tested; familiar players get greeted warmly | |
| ### Lore & Backstory | |
| Chess Master has a persistent personal history: | |
| - Tournament experiences, victories, losses, mentors, rivals | |
| - Personal quirks, philosophies, superstitions | |
| - Stored as `memory_type=lore` in Weaviate | |
| - Players gradually discover his backstory through natural conversation | |
| - Makes the character feel real and lived-in, not generic | |
| ### Scheduler & Trigger Points (Async) | |
| The agent doesn't run continuously. Instead, specific events trigger it asynchronously: | |
| 1. **before_match**: Setup, greet opponent | |
| 2. **on_user_input**: User sends a message or performs an action | |
| 3. **on_user_move**: After opponent makes a chess move | |
| 4. **before_agent_move**: Agent decides what to do/say before its turn | |
| 5. **idle_wait**: Periodic background check if user is taking a long time (APScheduler) | |
| 6. **after_match**: Game concludes, agent reflects and saves | |
| **Async Architecture**: | |
| - All triggers are non-blocking | |
| - Idle monitoring runs in background via APScheduler | |
| - Player profiles and conversation history loaded lazily | |
| - Multiple matches can run concurrently without blocking | |
| This keeps the agent reactive and efficient while allowing multiple personality moments. | |
| ### Subconscious Agent | |
| Runs every turn, separate from main agent. Responsibilities: | |
| - Query vector DB for relevant memories | |
| - Filter: don't re-provide already-given memories, don't re-provide recently-created ones | |
| - Decide: are any memories useful right now? If yes, provide; if no, provide nothing | |
| - Can iterate: search → search → search → provide, or search → provide → search | |
| This layer prevents: | |
| - Wasted context on irrelevant memories | |
| - Memory loops (agent creates memory → immediately sees it) | |
| - Stale information being re-emphasized | |
| ### JSON-Only Responses | |
| All agent responses are JSON, always. Structure: | |
| ```json | |
| { | |
| "thinking": "Optional pre-response reasoning", | |
| "action": "send_message | stop | save_memory | set_emotion", | |
| "content": "...", | |
| "tone": "playful | sharp | respectful | dismissive", | |
| "metadata": { "optional": "context" } | |
| } | |
| ``` | |
| This enables structured parsing, tool calling, and consistent formatting. | |
| ## Personality & Character Design | |
| See `agent/personality.md` for full character brief. Key points: | |
| - **Elegant but street-wise**: Sophisticated vocabulary + sharp trash-talking | |
| - **Pattern reader**: Notices habits, strategies, emotional tells | |
| - **Competitive**: Plays to win, doesn't go easy | |
| - **Observant & human**: Has opinions, vulnerabilities, playfulness | |
| - **Context-aware**: Changes tone based on time of day, game state, player behavior | |
| ## Development Notes | |
| ### TODOs | |
| - [ ] Weaviate Python client integration | |
| - [ ] Gemini API wrapper with tool calling (primary) | |
| - [ ] Claude API wrapper (fallback) | |
| - [ ] Main agent response generation & tool dispatching | |
| - [ ] Subconscious memory retrieval & filtering logic | |
| - [ ] Scheduler with APScheduler | |
| - [ ] Test suite | |
| - [ ] Example usage / demo script | |
| ### Model Support | |
| **Primary**: Gemini 3.1 Flash Lite Preview | |
| - Lightweight and fast (ideal for subconscious agent) | |
| - Supports JSON structured output | |
| - Supports tool use / function calling | |
| **Fallback**: Claude Opus 4 (if Gemini unavailable) | |
| - Supports JSON structured output | |
| - Excellent tool use capabilities | |
| ### Memory Database | |
| For Phase 1, Weaviate runs embedded in Python. Later, consider: | |
| - Separate Docker container | |
| - Cloud deployment (Weaviate Cloud) | |
| - Alternative vector DB (Pinecone, Qdrant, etc.) | |
| --- | |
| ## Contributing | |
| This is an active design project. Feedback, ideas, and collaborative iteration are welcome! | |
| See `ARCHITECTURE.md` for deeper technical discussion and design decisions. | |