RPGJS v4 game where AI agents live as NPC characters — they perceive through game events, act through game commands (skills), and use an in-repo agent system powered by the Moonshot (Kimi) API.
- RPGJS v4 game module (
main/) — maps, events (NPCs), GUIs, spritesheets, Tiled world assets - AI agent system (
src/agents/) — lane queue, agent runner, skills (move, say, look, emote, wait), perception engine, memory, bridge (RPGJS ↔ agent) - Supabase integration — optional agent memory persistence and player state (migrations in
supabase/migrations/) - Builder dashboard — in-game placement of AI and scripted NPCs (key B), conversation log (key L)
WIP / Experimental. The agent system is implemented and working; roadmap and coordination live in AGENTS.md and .ai/.
git clone https://github.com/AgentArtel/Open-RPG.git
cd Open-RPG
npm install
cp .env.example .envEdit .env and set your Moonshot API key:
MOONSHOT_API_KEY=sk-your-actual-key-here
Start the dev server:
npm run devOpen http://localhost:3000. You should see the game and the default map (simplemap). AI NPCs (e.g. Elder Theron) are spawned on the map; walk up and press the action key to talk. In the server console, look for [Adapter:elder-theron] and [Adapter:elder-theron] success=true to confirm the agent is processing.
| Variable | Required | Description |
|---|---|---|
MOONSHOT_API_KEY |
Yes | Moonshot/Kimi API key. Get from platform.moonshot.ai. Used for all LLM calls. |
KIMI_API_KEY |
No | Same key as MOONSHOT_API_KEY; fallback name used by some scripts. |
SUPABASE_URL |
For persistence | Supabase project URL. Used for agent memory and player state. |
SUPABASE_SERVICE_ROLE_KEY |
For persistence | Supabase service role key (Settings → API). |
PORT |
No | Server port (default 3000). |
KIMI_IDLE_MODEL / KIMI_CONVERSATION_MODEL |
No | Override LLM models (defaults from agent YAML). |
Security: Never use the VITE_ prefix for API keys or secrets — that exposes them to the client. The .env file is gitignored.
| Command | Description |
|---|---|
npm run dev |
Start dev server (game + client with HMR). |
npm run build |
Production build (rpgjs build). |
npm start |
Run production server (node dist/server/main.mjs). |
npx tsc --noEmit |
Type check without emitting files. |
Run npm run build and npx tsc --noEmit before committing. There is no npm run lint script in this repo.
The agent system is event-driven: RPGJS hooks (player action, proximity, leave) and a periodic idle tick (~15s) feed into a per-NPC lane queue. The agent runner builds a perception snapshot, calls the LLM (Kimi via the OpenAI-compatible API), and executes skills (move, say, look, emote, wait). Results are applied in the game and stored in memory.
flowchart LR
subgraph rpgjs [RPGJS]
Hook[onAction / onDetectInShape / idle tick]
end
subgraph bridge [Bridge]
Adapter[GameChannelAdapter]
end
subgraph agents [Agent system]
Lane[LaneQueue]
Runner[AgentRunner]
PE[PerceptionEngine]
LLM[Kimi API]
Skills[Skills]
end
Hook --> Adapter
Adapter --> Lane
Lane --> Runner
Runner --> PE
PE --> Runner
Runner --> LLM
LLM --> Runner
Runner --> Skills
Skills --> rpgjs
Open-RPG / AI NPCs: The agent system uses OpenClaw-inspired patterns (lane queue, agent runner, channel adapter, skill system, perception, memory) extracted and reimplemented in this repo. OpenClaw is not imported as a dependency. See docs/openclaw-patterns.md for the extraction rationale and pattern descriptions.
main/ # RPGJS autoload module (rpg.toml modules = ['./main'])
├── player.ts # Player lifecycle, builder input handling
├── server.ts # Server hooks, /health endpoint
├── events/ # NPCs: AgentNpcEvent, scripted NPCs, test NPCs
├── gui/ # Vue: builder-dashboard, conversation-log, npc-bubble
├── maps/ # simplemap
├── spritesheets/ # characters
├── worlds/ # Tiled .tmx / .tsx assets
├── database/ # (empty)
└── sounds/ # (empty)
src/
├── agents/ # AI agent system
│ ├── core/ # AgentManager, AgentRunner, LLMClient, LaneQueue
│ ├── skills/ # SkillRegistry, move/say/look/emote/wait
│ ├── perception/ # PerceptionEngine (game state → text snapshot)
│ ├── memory/ # InMemory + Supabase-backed agent memory
│ └── bridge/ # Bridge, GameChannelAdapter (RPGJS ↔ agent)
└── config/
├── supabase.ts # Supabase client
└── agents/ # YAML agent configs (elder-theron, test-agent)
supabase/migrations/ # 001_agent_memory.sql, 002_player_state.sql
Agents are defined in YAML under src/config/agents/. Example (elder-theron.yaml):
id: elder-theron
name: Elder Theron
graphic: female
personality: |
You are Elder Theron, the wise village elder...
model:
idle: kimi-k2-0711-preview
conversation: kimi-k2-0711-preview
skills: [move, say, look, emote, wait]
spawn:
map: simplemap
x: 300
y: 250
behavior:
idleInterval: 20000
patrolRadius: 3
greetOnProximity: trueAgentManager loads these at startup and spawns AI NPCs on the configured map.
- Railway:
railway.tomlandDockerfileare present. Build uses the Dockerfile; start command isnpm start; health check hits/health. - Docker:
docker build -t open-rpg .thendocker run -p 3000:3000 open-rpg. Requires env vars (e.g.MOONSHOT_API_KEY) at runtime. - Netlify / Vercel:
netlify.tomlandvercel.jsonexist and targetdist/standalonefor static build output. The primary game server is a Node process; use Railway or Docker for the full stack.
- Node version: This repo targets Node 18 (
package.jsonengines, Dockerfile). Usenode --versionand switch to 18+ if builds or runtime fail. - Missing API key: If NPCs don’t respond or the server logs LLM errors, ensure
MOONSHOT_API_KEYis set in.env(orKIMI_API_KEY). Restart the dev server after changing.env. - Port in use: Default is 3000. Set
PORTin.envor when runningnpm startif 3000 is taken.
Before opening a PR:
- Run
npm run buildandnpx tsc --noEmit(no lint script is defined). - Follow conventions and ownership in
AGENTS.md(Cursor vs Claude Code vs Kimi Overseer).
Not yet specified. No LICENSE file exists at the repo root.
Davidvitas
Attribution 4.0 International (CC BY 4.0) — https://creativecommons.org/licenses/by/4.0/deed.en