An AI agent that plays Slay the Spire using Large Language Models. Unlike traditional RL approaches, this agent is controllable through natural language - you can change its strategy with prompts!
- 🤖 Multiple LLM Providers - Gemini, OpenAI, AWS Bedrock, Ollama (local)
- 🎮 Controllable Behavior - Change strategy through prompts
- 📊 Structured Logging - JSON logs of all AI decisions
- ⚙️ Config-Based - Easy to switch models and strategies
- 🔧 Extensible - Add new providers easily
You need Slay the Spire with modding support:
- Slay the Spire - Purchase from Steam
- ModTheSpire - Download from GitHub
- BaseMod - Download from Steam Workshop or GitHub
- CommunicationMod - Download from GitHub
Copy all .jar mod files to your ModTheSpire mods directory.
pip install -r requirements.txtOr install only what you need:
pip install python-dotenv # Required for all providers
# Then install your chosen provider:
pip install google-genai # For Gemini
pip install openai # For OpenAI
pip install boto3 # For AWS Bedrock
pip install langchain-ollama # For local Ollama models
pip install anthropic # For Anthropic Claude (direct API).env file!
Create a .env file in the spirecomm/ directory (same folder as main.py):
# .env file
# Google Gemini
GEMINI_API_KEY=your-gemini-api-key
# OpenAI
OPENAI_API_KEY=your-openai-api-key
# Anthropic Claude (direct API)
ANTHROPIC_API_KEY=your-anthropic-api-key
# AWS Bedrock (uses AWS credentials from ~/.aws/credentials or these env vars)
AWS_ACCESS_KEY_ID=your-aws-key
AWS_SECRET_ACCESS_KEY=your-aws-secret
AWS_DEFAULT_REGION=us-east-1Only include the keys you need for your chosen provider.
For Ollama (Local - No API Key Needed):
# Install Ollama from https://ollama.ai
ollama pull nemotron-3-nano:30b # Or your preferred model
# Make sure Ollama is running: ollama serveCommunication Mod needs to know how to run your Python agent. Edit the config file:
Config file location:
- Windows:
%LOCALAPPDATA%\ModTheSpire\CommunicationMod\config.properties - Mac:
~/Library/Preferences/ModTheSpire/CommunicationMod/config.properties - Linux:
~/.config/ModTheSpire/CommunicationMod/config.properties
Set the config contents:
command=/path/to/python /path/to/spirecomm/main.py
runAtGameStart=true
verbose=trueExample (Mac with conda):
command=/Users/yourname/miniconda3/bin/python /Users/yourname/projects/spirecomm/main.py
runAtGameStart=true
verbose=trueExample (Windows):
command=C\:\\Python311\\python.exe C\:\\Projects\\spirecomm\\main.py
runAtGameStart=true
verbose=true\\ and \:).
Edit main.py to select your config:
config_path = "configs/agent_config_gemini_aggressive.json"Available configs:
agent_config_gemini_aggressive.json- Google Gemini, aggressive playstyleagent_config_bedrock_haiku.json- AWS Bedrock Claude Haiku 4.5agent_config_gpt52.json- OpenAI GPT-5.2agent_config_ollama.json- Local Ollama models
Launch Slay the Spire with ModTheSpire:
# From your Slay the Spire installation directory
jre/bin/java -jar ModTheSpire.jarOr use the ModTheSpire launcher if you installed via Steam Workshop.
The AI agent will automatically start when you begin a new run!
{
"agent_name": "MyAgent",
"provider": "gemini",
"provider_config": {
"model": "gemini-3-flash-preview",
"temperature": 0.7
},
"use_ai_for": {
"combat": true,
"map": true,
"rest": true,
"events": true,
"shop": true,
"card_rewards": true,
"boss_relics": true,
"potions": false,
"grid_selection": true
},
"prompts": {
"combat": {
"system_additions": "Be aggressive! Prioritize damage over defense."
}
}
}| Provider | Config Value | Model Examples |
|---|---|---|
| Google Gemini | "gemini" |
gemini-3-flash-preview, gemini-2.0-flash |
| OpenAI | "openai" |
gpt-5.2-mini, gpt-4o |
| AWS Bedrock | "bedrock" |
us.anthropic.claude-haiku-4-5-20251001-v1:0 (Claude Haiku 4.5) |
| Ollama | "ollama" |
nemotron-3-nano:30b, llama3.3, qwen2.5 |
You can inject custom instructions to change agent behavior:
{
"prompts": {
"combat": {
"system_additions": "Focus on blocking. Only attack when you have excess energy."
},
"map": {
"strategy": "Avoid elite fights until Act 2. Prioritize rest sites when below 50% HP."
},
"events": {
"strategy": "High HP = take risks for rewards. Low HP = play safe."
}
}
}┌─────────────────┐
│ Slay the │ ← Game (with Communication Mod)
│ Spire │
└────────┬────────┘
│ Game State (JSON)
↓
┌─────────────────┐
│ Communication │ ← Bridge
│ Layer │
└────────┬────────┘
│
↓
┌─────────────────┐
│ LLM Agent │ ← Your AI (configurable!)
│ (llmAgent.py) │
└────────┬────────┘
│ Decision
↓
┌─────────────────┐
│ LLM Provider │ ← Gemini/OpenAI/Bedrock/Ollama
└─────────────────┘
To add a new LLM provider, edit neuralNet/llm_providers.py:
class MyProvider(LLMProvider):
def __init__(self, config):
super().__init__(config)
self.model_name = config.get("model_name", "default-model")
# Initialize your client
def generate(self, prompt: str) -> str:
# Call your LLM and return the response
return response_textThen register it in the create_provider function.
All AI decisions are logged to ai_logs/ in JSONL format:
{
"timestamp": "2026-01-15T10:30:45.123",
"phase": "combat",
"model": {
"name": "gemini-3-flash-preview",
"input_tokens": 245,
"output_tokens": 45
},
"decision": {
"action": "Strike",
"target_index": 0,
"reasoning": "Enemy is low HP, finish it off"
},
"game_state": {
"hp": 65,
"max_hp": 80,
"floor": 5
}
}spirecomm/
├── .env # ⚠️ YOUR API KEYS GO HERE (create this!)
├── requirements.txt # Python dependencies
├── main.py # Entry point
├── configs/ # Agent configurations
│ ├── agent_config_gemini_aggressive.json
│ ├── agent_config_bedrock_haiku.json
│ ├── agent_config_gpt52.json
│ └── agent_config_ollama.json
├── neuralNet/
│ ├── llm_providers.py # LLM provider implementations
│ └── structured_logger.py # Logging utilities
└── spirecomm/
└── ai/
├── llmAgent.py # Main LLM agent
├── agent.py # Base agent class
├── nnAgent.py # Legacy neural net agent
└── simpleAgent.py # Simple heuristic agent
Traditional RL agents learn optimal strategies but can't be easily controlled. They optimize for a fixed reward function.
LLM agents offer:
- Natural language control - "Be more aggressive", "Focus on poison builds"
- Explainable decisions - See the reasoning for each action
- Easy customization - Change strategy with prompts, not retraining
- Flexible providers - Switch models without code changes
- Python 3.8+
- Slay the Spire with Communication Mod
python-dotenvpackage (for loading API keys)- API key for your chosen LLM provider (or local Ollama)
- A
.envfile with your API keys (see setup instructions above)
Communication Mod is not receiving the "ready" signal from the Python process.
Common causes:
- Wrong Python path in
config.properties - Wrong path to
main.pyinconfig.properties - Missing Python dependencies
Debug: Check communication_mod_errors.log in your Slay the Spire directory for error details.
The agent runs as a subprocess from the game, NOT from your terminal. Environment variables you export in your shell won't work!
Solution: Create a .env file in the spirecomm/ directory with your API keys.
Check neuralNet.log for error messages. Common issues:
- Missing
.envfile - Wrong API key format
- Model name typo in config
- Ollama not running (for local models)
AWS Bedrock uses your AWS credentials. Make sure you have either:
- AWS credentials in
~/.aws/credentials - Or set
AWS_ACCESS_KEY_IDandAWS_SECRET_ACCESS_KEYin.env
- Agent decisions:
ai_logs/directory (JSONL files) - General agent log:
neuralNet.log - Communication Mod errors:
communication_mod_errors.log(in game directory) - ModTheSpire console: Shows real-time stdout from the agent
MIT License - See LICENSE file
- Original spirecomm package: ForgottenArbiter
- LLM agent extensions: Banjo Obayomi