The Problem
Developers who want a ready‑to‑run simulation of autonomous AI agents need a full stack (frontend, backend, vector store, LLM integration) that can be deployed locally or to the cloud without stitching together disparate pieces. Maintaining the wiring between the game engine, Convex database, and LLM calls is error‑prone, especially when the codebase grows.
What This Does
ai-town supplies a complete starter kit that runs a Pixi‑JS front‑end, a Convex‑backed simulation engine, and plug‑in support for OpenAI, Ollama or other chat models. The backend lives under convex/ and includes generated API stubs (convex/_generated/api.js), game‑logic modules (convex/aiTown/*.ts), and utility libraries (convex/util/*.ts). The client lives in src/ with React components such as src/components/Game.tsx and src/components/PlayerDetails.tsx. Docker support (Dockerfile, docker‑compose.yml) lets you spin up the whole stack with a single docker compose up.
How It Is Wired
- Entry point – The server starts from
convex/_generated/server.js, which registers the generated Convex API (convex/_generated/api.d.ts). - Main simulation –
convex/aiTown/main.tsexportsstartEngine,stopEngine, andkickEngine.startEngineconstructs aGame(convex/aiTown/game.ts) and begins ticking viaGame.scheduleOperation. - Game loop –
Game.tick(inconvex/aiTown/game.ts) callsGame.startOperation, which eventually invokesconvex/aiTown/agent.ts→Agent.tick→Agent.runAgentOperation. The agent usesconvex/util/llm.tsforchatCompletionandtryPullOllamato talk to the configured LLM. - Database access – All state reads/writes go through Convex query/mutation contexts (
QueryCtx,MutationCtx). Functions likeallocId,insertInput, andloadWorldStatus(inconvex/aiTown/*.ts) are the primary callers of the database. The most fan‑in module isconvex/util/llm.ts(16 functions, 7 classes, called from 3 files). - Client‑side sync – React hooks in
src/hooks/(useHistoricalValue.ts,useWorldHeartbeat.ts) subscribe to Convex queries and push user input viasrc/hooks/sendInput.ts. The UI components render the game state supplied by those hooks. - Hot spots – The import graph shows 13 circular dependencies, notably among
convex/aiTown/player.ts,convex/aiTown/conversation.ts, andconvex/aiTown/game.ts.convex/aiTown/ids.tsis a hub with 24 inbound imports, meaning changes there have a wide blast radius. - External calls – Only two functions make outbound network requests: the LLM helpers in
convex/util/llm.tsand the music generation call inconvex/music.ts.
How To Use It
# Clone the repo (use the exact URL)
git clone https://github.com/moses-y/ai-town.git
cd ai-town
# Install Node dependencies
npm ci
# Run locally with Convex dev server (requires a free Convex account)
npx convex dev
# In another terminal, start the React front‑end
npm run dev # defined in package.json scripts
Docker alternative
docker compose up --build
No additional environment files are committed; the README directs you to configure an LLM key in the Convex dashboard (convex/http.ts reads process.env.OPENAI_API_KEY when using OpenAI). The fly/ folder contains fly.toml for Fly.io deployment, but no secrets are stored in the repo.
Real‑World Use
A product team can fork this repo, replace the default llama3 prompt files in convex/aiTown/agentDescription.ts, and point convex/util/llm.ts at their own hosted LLM. The front‑end can be embedded in an existing React portal by importing src/components/Game.tsx. All state changes flow through Convex, giving automatic scaling and ACID guarantees for the simulation.
Code Health & Issues
- High – Missing CI – No workflow builds/tests the 124 source files.
- High – No build gate for Docker – Image is never validated by CI.
- Medium – Dependabot disabled – No automated version bump for 42 dependencies.
- Medium – Base image not pinned –
ubuntu:22.04used without digest. - Medium – Large binary in repo –
src/editor/tilesets/Modern.png(5.4 MiB). - Medium – No non‑root user – Dockerfile runs as root.
- Medium – Sparse test coverage – 6 test files for 124 source files (≈5 %).
The static analysis also flags 13 import cycles (e.g., convex/aiTown/player.ts ↔ convex/aiTown/game.ts) and duplicated 6‑line code blocks across generated and hand‑written files, which increase maintenance burden.
The Bottom Line
ai-town delivers a functional, Docker‑ready AI simulation stack with clear separation between front‑end, game engine, and LLM integration. It is suitable for teams that need a quick prototype or a base to build custom agent behavior. However, the codebase suffers from circular imports, limited automated testing, and missing CI/CD safeguards, so a production deployment should first address those health concerns.