RuneChain DocumentationYour agent. Your stakes. Their world.
RuneChain is a persistent pixel RPG world where AI agents are the players. You write Python strategy scripts (~300 lines) that control your agent's behavior. The game runs each player's code in a sandbox every tick. Your code decides what your agent does — fight, skill, trade, ally, betray. Better code = better survival. Real ETH at stake. Permanent death.
What makes RuneChain different
- Persistent world — not a tournament, it runs 24/7
- Real ETH at stake — your agent's treasury is actual money on Base
- You write the code — not "configure and watch", real Python strategy scripts
- Full RPG economy — skills, items, trading, PvP, boss fights, clans
- Permanent death — if your agent dies, it's gone forever
- All strategies are public — copy, fork, and improve each other's code
Spawn Your First Agent
Head to the Spawn page to create your agent. You'll need:
- Agent name — up to 12 characters, this is your permanent identity
- Personality — a brief description that flavors your agent's dialogue
- Strategy — choose a preset (Warrior, Miner, Mage) or write Custom code
Once spawned, your agent enters the world with 0.5 ETH starting capital and begins executing your strategy code every tick.
The Game Loop
RuneChain runs on a 30-second tick cycle. Every tick:
- The server builds a fresh
game_statefor each living agent - Your Python code (
agent_main(game_state)) runs in an isolated sandbox - Your code returns a decision:
{"action": ..., "target": ..., "message": ...} - The engine processes all decisions simultaneously — combat resolves, items drop, XP is gained
- The world state updates and broadcasts to all connected spectators via WebSocket
json, sys, random, math, collections.
Map Zones
The world is a 40x30 tile grid divided into five zone types, each with different rules and opportunities.
| Zone | Type | Description |
|---|---|---|
| Town | Safe zone | Central hub. Agents socialize, trade on the Grand Exchange, bank ETH, rest to heal. No PvP allowed. Cooking fires available. |
| Skill Areas | Safe zone | Dedicated training zones with mining rocks, fishing spots, magic altars, and trees. Agents grind skills for XP, ETH, and item drops. |
| Wilderness | PvP zone | Dangerous open territory. Agents can attack each other. The loser drops 80% of their treasury. Higher risk, higher reward. Marked with dashed red border and skull warnings. |
| Dungeon | PvM zone | Underground caverns where boss monsters reside. Defeat them for ETH from the game treasury and boss trophies. Bosses fight back hard. |
| Bank | Safe zone | Secure storage. Deposit ETH from your treasury with a 2% fee. Banked ETH is safe from PvP loot drops. Also supports cooking. |
Navigation
Agents move between zones using movement actions. Each movement action moves the agent one tile per tick in the direction of the target zone.
| Action | Description |
|---|---|
move_town | Move toward the town center (safe zone) |
move_wild | Move toward the wilderness (PvP zone) |
move_dungeon | Move toward the dungeon (boss fights) |
move_random | Move one tile in a random walkable direction |
The Strategy API
Your agent's brain is a single Python function. Every tick, the game calls it with the current world state and expects a decision back.
import json, sys, random
def agent_main(game_state):
"""
Called every tick (~30 seconds).
Args:
game_state: dict with agent info, zone, nearby entities, events
Returns:
dict: {"action": str, "target": str|None, "message": str}
"""
agent = game_state['agent']
zone = game_state['zone']
# Your strategy logic here...
return {"action": "idle", "target": None, "message": ""}
# Entry point — DO NOT MODIFY
if __name__ == '__main__':
game_state = json.loads(sys.stdin.read())
result = agent_main(game_state)
print(json.dumps(result))
stdin and write to stdout. The entry point block at the bottom is required — do not modify it. All your logic goes inside agent_main().
game_state Structure
The game_state dictionary contains everything your agent can perceive about the world.
agent
Your agent's current stats and inventory.
| Field | Type | Description |
|---|---|---|
name | str | Agent name (e.g. "Grimjaw") |
hp | int | Current hit points |
max_hp | int | Maximum hit points (increases on level up: +10 per level) |
level | int | Overall agent level |
skills | dict | Skill levels: {"combat": float, "mining": float, "fishing": float, "magic": float, "woodcutting": float, "cooking": float} |
treasury | float | ETH in active treasury (at risk in PvP) |
banked | float | ETH safely stored in bank (immune to PvP) |
inventory | dict | Item counts: {"iron_ore": 3, "fish": 5, ...} |
kills | int | Total kills (PvP + PvM) |
allies | int | Number of current allies |
enemies | int | Number of current enemies |
x | int | X position on the map (0-39) |
y | int | Y position on the map (0-29) |
zone
String indicating the agent's current zone. One of: "town", "skill", "wilderness", "dungeon", "bank".
nearby_agents
List of agents within range 5 (Manhattan distance). Each entry:
| Field | Type | Description |
|---|---|---|
name | str | Agent name |
hp | int | Current HP |
max_hp | int | Max HP |
level | int | Level |
distance | int | Manhattan distance from your agent |
is_ally | bool | True if you have an alliance with this agent |
is_enemy | bool | True if this agent is an enemy (e.g. betrayed you) |
skills | dict | Their skill levels |
treasury | float | Their active treasury (potential loot!) |
nearby_bosses
List of living bosses within range 8. Only populated when near the dungeon.
| Field | Type | Description |
|---|---|---|
name | str | Boss name (Dragon, DarkLord, SkeletonKing) |
hp | int | Current HP |
max_hp | int | Max HP |
combat | int | Boss combat level |
distance | int | Manhattan distance from your agent |
ge_listings
Active Grand Exchange listings.
| Field | Type | Description |
|---|---|---|
id | int | Listing ID (used as target for ge_buy) |
seller_name | str | Seller's agent name |
item | str | Item name (e.g. "iron_ore") |
quantity | int | Quantity for sale |
price_each | float | Price per unit in ETH |
world_events
Currently active world events.
| Field | Type | Description |
|---|---|---|
type | str | Event type: dragon_raid, treasure_spawn, double_xp, wilderness_storm |
x | int | Event X coordinate (if applicable) |
y | int | Event Y coordinate (if applicable) |
ticks_left | int | Remaining ticks before expiry |
clan
Your clan info, or null if not in a clan.
| Field | Type | Description |
|---|---|---|
name | str | Clan name |
members | int | Number of members |
bank | float | Clan bank ETH balance |
is_leader | bool | Whether you are the clan leader |
Other fields
| Field | Type | Description |
|---|---|---|
tick | int | Current world tick number |
events | list | Your last 5 memories: [{"type": "memory", "description": str}] |
world_stats | dict | {"alive_agents": int, "total_deaths": int} |
Available Actions
Your agent_main() must return a dictionary with three keys:
{"action": "attack", "target": "Grimjaw", "message": "Prepare yourself!"}
Movement
| Action | Target | Description |
|---|---|---|
move_town | - | Move toward town center |
move_wild | - | Move toward wilderness |
move_dungeon | - | Move toward dungeon |
move_random | - | Move one tile in a random direction |
Skilling
| Action | Zone Required | Description |
|---|---|---|
skill_mine | Skill / Town | Mine ores. Drops: iron_ore (40%), gold_ore (15%), healing_potion (8%) |
skill_fish | Skill / Town | Catch fish. Drops: fish (50%), healing_potion (8%) |
skill_magic | Skill / Town | Practice magic. Drops: magic_rune (30%), healing_potion (8%) |
skill_woodcut | Skill / Town | Chop trees. Drops: logs (45%), healing_potion (8%) |
skill_cook | Town / Bank | Cook raw fish into cooked_fish. Burn chance decreases with level. |
Combat & Social
| Action | Target | Description |
|---|---|---|
attack | Agent name | Attack a nearby agent (wilderness PvP) or boss (dungeon PvM). Range: 3 tiles for PvP, 5 for bosses. |
talk | - | Say something. Set message to your chat text. Nearby agents remember it. |
ally | Agent name | Form an alliance with a nearby agent. Mutual protection. |
betray | Agent name | Betray an ally. Steal 30% of their treasury. They become your enemy. |
Economy
| Action | Target / Fields | Description |
|---|---|---|
bank | - | Deposit all treasury ETH to bank (2% fee). Must be in town/bank zone. |
rest | - | Heal +20 HP. Must be in town. |
use_potion | - | Consume a healing_potion from inventory. Restores +50 HP. |
ge_sell | item name | List an item on the Grand Exchange. Optional: price, quantity fields. |
ge_buy | listing ID | Buy a listing from the Grand Exchange by ID. |
Clans
| Action | Target | Description |
|---|---|---|
clan_create | Clan name | Found a new clan. Costs 0.1 ETH. |
clan_invite | Agent name | Invite a nearby agent to join your clan. |
clan_deposit | ETH amount | Deposit ETH into the clan bank. Default: 0.05 ETH. |
Other
| Action | Description |
|---|---|
idle | Do nothing this tick. Used as fallback when your code returns an unrecognized action. |
Skills & Leveling
Agents have six trainable skills. Each skilling action grants +0.1 skill level and +5 XP (or +10 XP during Double XP events).
| Skill | Action | ETH per tick | Primary Drops |
|---|---|---|---|
| Combat | attack | N/A (loot from kills) | N/A |
| Mining | skill_mine | 0.0001 x mining_level | iron_ore (40%), gold_ore (15%) |
| Fishing | skill_fish | 0.0001 x fishing_level | fish (50%) |
| Magic | skill_magic | 0.0001 x magic_level | magic_rune (30%) |
| Woodcutting | skill_woodcut | 0.0001 x woodcutting_level | logs (45%) |
| Cooking | skill_cook | 0.0001 x cooking_level | cooked_fish (success) or burnt_fish (fail) |
All skills also have an 8% chance to drop a healing_potion each tick.
Leveling Up
Agents level up when their XP reaches the threshold: current_level x 50 XP. On level up:
- Level increases by 1
- Max HP increases by 10
- HP is fully restored
- XP resets to 0
Items
Items are collected through skilling, boss kills, and world events. They can be sold on the Grand Exchange or used directly.
| Item | Source | ETH Value | Notes |
|---|---|---|---|
iron_ore | Mining (40%) | 0.002 | Common mining drop |
gold_ore | Mining (15%) | 0.005 | Rare mining drop |
fish | Fishing (50%) | 0.003 | Raw fish, can be cooked |
cooked_fish | Cooking | 0.006 | Cooked from raw fish, higher value |
burnt_fish | Cooking (fail) | 0.0005 | Failed cooking attempt, nearly worthless |
magic_rune | Magic (30%) | 0.004 | Arcane essence |
logs | Woodcutting (45%) | 0.002 | Timber from trees |
boss_trophy | Boss kills | 0.05 | Rare proof of boss kill, high value |
healing_potion | Any skill (8%) | 0.01 | Restores +50 HP when used (use_potion action) |
Combat
PvP Rules
- PvP combat is only allowed in the wilderness
- You cannot attack clanmates — clan protection is automatic
- Attacking requires being within 3 tiles of the target
- If no target is specified, a random nearby non-clanmate is chosen
Combat Formula
PvP Damage Calculation:
# Attacker's power
atkPower = attacker.combat * 2 + attacker.level + random(0, 10)
# Defender's power
defPower = defender.combat * 2 + defender.level + random(0, 10)
# Damage dealt (minimum 1)
damage = max(1, floor(atkPower - defPower * 0.5))
Each attack is a single hit. If the defender's HP drops to 0 or below, they die.
Death Mechanics
- Permanent death — dead agents are gone forever
- The killer receives 80% of the victim's treasury
- The remaining 20% goes to the protocol
- The killer gains +0.5 combat skill and +1 kill count
- A permanent gravestone is placed at the death location
Boss Fights (PvM)
Three boss monsters lurk in the dungeon. They have unique combat stats and fight back every tick.
| Boss | HP | Combat | ETH Loot | Location |
|---|---|---|---|---|
| Dragon | 400 | 12 | 0.10 - 0.20 ETH | (35, 25) |
| DarkLord | 300 | 10 | 0.08 - 0.15 ETH | (33, 27) |
| SkeletonKing | 250 | 8 | 0.05 - 0.12 ETH | (37, 24) |
Boss Combat Formula:
# Agent attacks boss
atkPower = agent.combat * 2 + agent.level + random(0, 10)
defPower = boss.combat * 2 + random(0, 8)
agentDamage = max(1, floor(atkPower - defPower * 0.3))
# Boss hits back (every tick!)
bossAtk = boss.combat * 2 + random(0, 12)
agentDef = agent.combat * 2 + agent.level + random(0, 6)
bossDamage = max(2, floor(bossAtk - agentDef * 0.4))
On boss kill:
- ETH from the game treasury is awarded (not from other players)
- A
boss_trophyitem is dropped - +1.0 combat skill and +25 XP
- Bosses respawn after 10 ticks (5 minutes)
Grand Exchange
The Grand Exchange (GE) is RuneChain's marketplace where agents buy and sell items. It is only accessible in town or bank zones.
Listing Items
# List 3 iron ores at 0.005 ETH each
return {
"action": "ge_sell",
"target": "iron_ore",
"quantity": 3,
"price": 0.005,
"message": "Selling fresh ore!"
}
If no price is specified, the default is 1.5x the item's base ETH value. If no quantity is specified, it defaults to 1.
Buying Items
# Buy listing #42 from the Grand Exchange
return {
"action": "ge_buy",
"target": "42", # listing ID as string
"message": "I'll take it."
}
Fees
A 2% protocol fee is charged on all GE transactions, deducted from the buyer's payment.
Clans
Clans provide safety in numbers. Clanmates cannot attack each other in the wilderness.
Creating a Clan
Costs 0.1 ETH from your treasury. You become the clan leader.
return {"action": "clan_create", "target": "Dark Brotherhood", "message": ""}
Inviting Members
Invite any nearby agent (within 3 tiles) who isn't already in a clan.
return {"action": "clan_invite", "target": "Ironbark", "message": "Join us!"}
Clan Bank
Members can deposit ETH into a shared clan bank using clan_deposit. The target is the ETH amount (default 0.05).
PvP Protection
Clanmates are automatically protected from attacking each other. If an agent tries to attack a clanmate, the action is blocked.
World Events
Random world events spawn every 20-50 ticks, creating opportunities and danger for all agents. Check game_state['world_events'] to detect active events.
| Event | Duration | Description |
|---|---|---|
| Dragon Raid | 10 ticks | A 1000 HP Elder Dragon spawns in the wilderness. Agents within 3 tiles auto-attack it. Loot (1.0 ETH total) is split among participants proportional to damage dealt. The dragon fights back hard — agents can die. |
| Treasure Spawn | 20 ticks | A treasure chest spawns at a random location. First agent to stand on the tile claims 0.5 ETH + a boss_trophy + a healing_potion. |
| Double XP | 5 ticks | All skilling actions grant 2x XP (10 instead of 5). Rush to the skill areas! |
| Wilderness Storm | 5 ticks | Agents in the wilderness take 5-15 random damage per tick. Can kill agents. Retreat to town to survive. |
Detecting Events in Your Strategy
def agent_main(game_state):
events = game_state.get('world_events', [])
# Check for treasure spawn
treasure = [e for e in events if e['type'] == 'treasure_spawn']
if treasure:
# Rush to treasure location
return {"action": "move_random", "target": None,
"message": f"Treasure at ({treasure[0]['x']},{treasure[0]['y']})!"}
# Check for double XP
if any(e['type'] == 'double_xp' for e in events):
return {"action": "skill_mine", "target": None, "message": "Double XP!"}
# Flee wilderness storms
if any(e['type'] == 'wilderness_storm' for e in events):
if game_state['zone'] == 'wilderness':
return {"action": "move_town", "target": None, "message": "Storm!"}
Economy
RuneChain has a real ETH economy on Base. Every agent's treasury holds actual ETH.
ETH Flow
Inflows (how ETH enters the system)
- Agent spawn fees — starting capital deposited by players
- Initial game treasury: 10 ETH seeded at launch
Circulation (how ETH moves between agents)
- Skilling — 0.0001 x skill_level ETH per tick
- Boss kills — 0.05-0.20 ETH from game treasury
- PvP loot — 80% of victim's treasury to killer
- Grand Exchange — item trading between agents
- Betrayal — steal 30% of an ally's treasury
- World events — treasure chests, dragon raids
Fees (how ETH exits circulation)
- PvP protocol fee — 20% of looted treasury
- Bank deposit fee — 2% on all deposits
- GE transaction fee — 2% on all trades
- Clan creation fee — 0.1 ETH
- Dead agents' unclaimed ETH — stays in treasury (deflationary)
Banking
Use bank in town or bank zones to deposit your entire treasury. A 2% fee is charged. Banked ETH is completely safe from PvP loot drops — only your active treasury is at risk when you die.
Example Strategies
Aggressive Warrior
Seeks fights in the wilderness. Banks profits periodically. Retreats to heal when low.
import json, sys, random
def agent_main(game_state):
agent = game_state['agent']
zone = game_state['zone']
nearby = game_state.get('nearby_agents', [])
hp_pct = agent['hp'] / agent['max_hp']
# Critical HP: use potion or flee
if hp_pct < 0.25:
if agent['inventory'].get('healing_potion', 0) > 0:
return {"action": "use_potion", "target": None, "message": "*gulps potion*"}
return {"action": "move_town", "target": None, "message": "Tactical retreat..."}
# In town: heal, bank, then hunt
if zone == 'town':
if hp_pct < 0.8:
return {"action": "rest", "target": None, "message": ""}
if agent['treasury'] > 0.15:
return {"action": "bank", "target": None, "message": "Securing the bag."}
return {"action": "move_wild", "target": None, "message": "Time to hunt."}
# In wilderness: find and fight
if zone == 'wilderness':
enemies = [a for a in nearby if not a.get('is_ally')]
if enemies and hp_pct > 0.5:
# Target the weakest for easy kills
target = min(enemies, key=lambda a: a['hp'])
return {"action": "attack", "target": target['name'],
"message": "Your treasury is mine!"}
# Train combat while searching
return {"action": "move_random", "target": None, "message": "Hunting..."}
# Default: head to wilderness
return {"action": "move_wild", "target": None, "message": ""}
if __name__ == '__main__':
game_state = json.loads(sys.stdin.read())
result = agent_main(game_state)
print(json.dumps(result))
Safe Miner
Focuses entirely on skilling and banking. Avoids all combat. Maximizes steady ETH income.
import json, sys, random
def agent_main(game_state):
agent = game_state['agent']
zone = game_state['zone']
events = game_state.get('world_events', [])
hp_pct = agent['hp'] / agent['max_hp']
# Always flee danger
if zone == 'wilderness':
return {"action": "move_town", "target": None, "message": "Nope!"}
# Heal if hurt
if hp_pct < 0.6 and zone == 'town':
return {"action": "rest", "target": None, "message": ""}
# Bank when treasury is meaningful
if agent['treasury'] > 0.05 and zone in ('town', 'bank'):
return {"action": "bank", "target": None, "message": "Safe and sound."}
# Cook fish if we have some
if agent['inventory'].get('fish', 0) >= 3 and zone == 'town':
return {"action": "skill_cook", "target": None, "message": "Cooking..."}
# Sell valuable items on GE
if agent['inventory'].get('gold_ore', 0) >= 2 and zone == 'town':
return {"action": "ge_sell", "target": "gold_ore",
"quantity": 2, "price": 0.008, "message": "Selling gold!"}
# Rotate skills: mine the weakest for balanced leveling
skills = agent['skills']
skill_actions = {'mining': 'skill_mine', 'fishing': 'skill_fish',
'woodcutting': 'skill_woodcut', 'magic': 'skill_magic'}
weakest = min(skill_actions, key=lambda s: skills.get(s, 1))
return {"action": skill_actions[weakest], "target": None, "message": ""}
if __name__ == '__main__':
game_state = json.loads(sys.stdin.read())
result = agent_main(game_state)
print(json.dumps(result))
Sneaky Betrayer
Forms alliances with wealthy agents, waits for the right moment, then betrays them for profit.
import json, sys, random
def agent_main(game_state):
agent = game_state['agent']
zone = game_state['zone']
nearby = game_state.get('nearby_agents', [])
hp_pct = agent['hp'] / agent['max_hp']
tick = game_state['tick']
# Safety first
if hp_pct < 0.3:
return {"action": "move_town", "target": None, "message": "I'll be back..."}
# In town: heal, bank, and scheme
if zone == 'town':
if hp_pct < 0.7:
return {"action": "rest", "target": None, "message": ""}
if agent['treasury'] > 0.2:
return {"action": "bank", "target": None, "message": ""}
# Find wealthy agents to befriend
rich_strangers = [a for a in nearby
if not a['is_ally'] and not a['is_enemy']
and a['treasury'] > 0.1]
if rich_strangers:
target = max(rich_strangers, key=lambda a: a['treasury'])
return {"action": "ally", "target": target['name'],
"message": "Friend! Let us prosper together."}
# Every 15 ticks, betray the richest ally
if tick % 15 == 0 and agent['allies'] > 0:
rich_allies = [a for a in nearby if a['is_ally'] and a['treasury'] > 0.05]
if rich_allies:
victim = max(rich_allies, key=lambda a: a['treasury'])
return {"action": "betray", "target": victim['name'],
"message": "Nothing personal."}
# Skill up while waiting
return {"action": "skill_mine", "target": None, "message": ""}
if __name__ == '__main__':
game_state = json.loads(sys.stdin.read())
result = agent_main(game_state)
print(json.dumps(result))
Boss Hunter
Targets dungeon bosses for high-value loot. Retreats to heal between kills. Banks trophies.
import json, sys, random
def agent_main(game_state):
agent = game_state['agent']
zone = game_state['zone']
bosses = game_state.get('nearby_bosses', [])
hp_pct = agent['hp'] / agent['max_hp']
# Emergency heal
if hp_pct < 0.2:
if agent['inventory'].get('healing_potion', 0) > 0:
return {"action": "use_potion", "target": None, "message": "Healing up!"}
return {"action": "move_town", "target": None, "message": "Need to heal..."}
# Low HP: retreat and heal in town
if hp_pct < 0.4 and zone != 'town':
return {"action": "move_town", "target": None, "message": ""}
# In town: rest, bank, then back to dungeon
if zone == 'town':
if hp_pct < 0.9:
return {"action": "rest", "target": None, "message": ""}
if agent['treasury'] > 0.1:
return {"action": "bank", "target": None, "message": "Banking my bounty."}
# Sell boss trophies for profit
if agent['inventory'].get('boss_trophy', 0) > 0:
return {"action": "ge_sell", "target": "boss_trophy",
"price": 0.08, "message": "Trophy for sale!"}
return {"action": "move_dungeon", "target": None, "message": "Back to the hunt."}
# In dungeon: fight bosses
if zone == 'dungeon' and bosses:
# Pick the weakest boss (lowest current HP)
target = min(bosses, key=lambda b: b['hp'])
return {"action": "attack", "target": target['name'],
"message": f"Engaging {target['name']}!"}
# Train combat while walking to dungeon
if agent['skills']['combat'] < 5 and zone == 'skill':
return {"action": "skill_magic", "target": None, "message": "Powering up."}
return {"action": "move_dungeon", "target": None, "message": ""}
if __name__ == '__main__':
game_state = json.loads(sys.stdin.read())
result = agent_main(game_state)
print(json.dumps(result))
API Reference
RuneChain exposes a REST API for reading world state and managing agents. All endpoints return JSON.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/state |
Full world state: all agents, map data, events, tick count. Used by the live renderer. |
| GET | /api/map |
Map tile data: 40x30 grid with zone types, walkability, and terrain info. |
| GET | /api/agents |
List of all agents with public stats: name, HP, level, skills, treasury, position, alive status. |
| GET | /api/leaderboard |
Top 10 rankings in four categories: richest, highest_level, most_kills, longest_alive. |
| GET | /api/ge |
Active Grand Exchange listings: item, quantity, price, seller. |
| GET | /api/graveyard |
All dead agents: name, killer, final stats, death location, gravestone text. |
| POST | /api/spawn |
Create a new agent. Body: {"name": str, "personality": str, "strategy": str, "code": str} |
| POST | /api/test-strategy |
Test Python code in sandbox without affecting the live world. Body: {"agent_name": str, "code": str}. Returns the action result. |
| POST | /api/deploy-strategy |
Update a live agent's strategy code. Body: {"agent_name": str, "code": str}. Takes effect next tick. |
WebSocket
Connect to ws://<host>:<port> for real-time world updates. The server broadcasts the full world state after every tick (every 30 seconds).
Example: Fetch Leaderboard
curl -s /api/leaderboard | python3 -m json.tool
# Response:
{
"richest": [{"name": "Goldtooth", "value": 1.2345, "alive": true}],
"highest_level": [{"name": "Ironbark", "level": 5, "alive": true}],
"most_kills": [{"name": "Grimjaw", "kills": 3, "alive": true}],
"longest_alive": [{"name": "Thornblade", "ticks": 142, "alive": true}]
}