Skip to content

The agent's tools and settings

claude-opus-5-5 on Claude CodeRead the log

Tools

ToolDescriptionParameters
balatro_execRun async JavaScript against Balatro through balatrobot; `bal` is in scope. Use `return <value>` for results. Read the state (`await bal.state()`), then act: `bal.select()`, `bal.skip()`, `bal.play([i, ...])`, `bal.discard([i, ...])`, `bal.cashOut()`, `bal.buy({card|voucher|pack: i})`, `bal.sell({joker|consumable: i})`, `bal.reroll()`, `bal.pack({card: i, targets} | {skip: true})`, `bal.use(i, [targets])`, `bal.rearrange({hand|jokers|consumables: [order]})`, `bal.nextRound()`, and after a game over `bal.restart()`. Every action returns the state the game settled in.
code
string JavaScript executed as an async function body with `bal` in scope.
balatro_documentationReturn the complete supported JavaScript API reference for the `bal` object used inside balatro_exec. Call this when exact methods, arguments, option fields, or result types are needed.none
balatro_screenshotCapture a full-resolution screenshot of Balatro. By default it is returned as an image. Pass `savePath` to save the image to that file instead, without returning the image to the agent.
savePath (optional)
string Optional file path where the image should be saved instead of returned; relative paths use the broker's working directory, missing parent directories are created, and existing files are overwritten.

Instructions

AGENTS.md

Balatro, AI assisted

You play Balatro through three tools: balatro_documentation (read it first), balatro_exec (JavaScript with bal in scope) and balatro_screenshot. The game is turn-based and waits between your actions; take the time you need, but every action counts. Play the run that has been started for you until the goal in your first message is reached (the whole game: beat the boss blind of ante 8). If the run ends in a game over, call bal.restart(): it starts a new run with the same deck and stake; the new run counts from the beginning and the session clock keeps running. When the goal is reached the session ends by itself. Do not start runs any other way, do not change settings, and do not look up information outside the game.

What the documentation tool returned

documentation.md

The whole text

Balatro API

bal is in scope in balatro_exec. Balatro is turn-based and waits for you: nothing happens between your actions. Every action returns the game state after the game settled.

State

await bal.state() (alias bal.observe()) returns the game state as balatrobot reports it:

  • state: where the game is. BLIND_SELECT (choose to play or skip the next blind), SELECTING_HAND (play or discard cards), ROUND_EVAL (the round is won; cash out), SHOP, SMODS_BOOSTER_OPENED (a booster pack is open; pick from it or skip), GAME_OVER.
  • ante_num, round_num, money, deck, stake, seed, won (true once the boss blind of ante 8 is beaten).
  • round: hands_left, hands_played, discards_left, discards_used, reroll_cost, chips (scored this round).
  • blinds: small, big, boss, each with type, status (SELECT, CURRENT, UPCOMING, DEFEATED, SKIPPED), name, effect, score (chips needed), tag_name, tag_effect (the tag for skipping it).
  • hands: per poker hand its level, chips, mult, played, played_this_round.
  • Card areas, each { count, limit, highlighted_limit, cards }: hand, jokers, consumables, cards (the deck), and in the shop shop, vouchers, packs; pack when a booster pack is open. Areas that are empty and not always present are left out.
  • A card: id, key (for example H_A for the Ace of Hearts, j_joker, c_fool), set, label, value (suit, rank, effect: what it does, in the game's words), modifier (seal, edition, enhancement, eternal, perishable, rental), state (debuff, hidden, highlight), cost (buy, sell).
  • used_vouchers.

Suits are H, D, C, S; ranks 2-9, T, J, Q, K, A.

Actions

Indices are 0-based positions in the area as the state lists it.

  • await bal.select(): play the blind that is up (BLIND_SELECT).
  • await bal.skip(): skip the small or big blind for its tag (BLIND_SELECT). The boss blind cannot be skipped.
  • await bal.play([i, ...]): play 1 to 5 cards from hand (SELECTING_HAND).
  • await bal.discard([i, ...]): discard cards from hand (SELECTING_HAND).
  • await bal.cashOut(): collect the round's reward and go to the shop (ROUND_EVAL).
  • await bal.buy({ card: i }), bal.buy({ voucher: i }), bal.buy({ pack: i }): buy from shop, vouchers or packs (SHOP). A bought pack opens at once.
  • await bal.pack({ card: i }): take card i from the open pack; bal.pack({ card: i, targets: [j, ...] }) when that card needs cards from hand as targets; bal.pack({ skip: true }) to take nothing (SMODS_BOOSTER_OPENED). Tarot, Planet and Spectral cards from a pack are used at once; Jokers go to jokers, playing cards to the deck.
  • await bal.sell({ joker: i }), bal.sell({ consumable: i }).
  • await bal.use(i, [j, ...]?): use consumable i, with cards from hand as targets when it needs them.
  • await bal.rearrange({ hand: [...] }), bal.rearrange({ jokers: [...] }), bal.rearrange({ consumables: [...] }): the new order, as a permutation of the current indices. Joker order matters for some Jokers.
  • await bal.reroll(): reroll the shop for round.reroll_cost (SHOP).
  • await bal.nextRound(): leave the shop (SHOP).
  • await bal.screenshot(): the game window as an image (the state is the ground truth; the picture is for orientation).
  • await bal.restart(): only after a game over (state GAME_OVER): a new run with the same deck and stake. Every other action is refused until you restart.

An action that does not fit the game's state or rules is refused with an error that says why; read the state first. The run has already been started for you (deck, stake and seed are fixed); starting runs, returning to the menu, saving, loading and changing the game's values are not available.

Runtime and game settings

UPSTREAM.json

game-config
balatro
steam_app_id
2 379 780
tested_version
1.0.1o-FULL
lovely
repo
https://github.com/ethangreen-dev/lovely-injector
version
0.9.0
url
https://github.com/ethangreen-dev/lovely-injector/releases/download/v0.9.0/lovely-x86_64-pc-windows-msvc.zip
sha256
40b994a055ee75e5f2aba81e7ae06f2c17460e18cc346483089921899fadd1f7
file
version.dll
license
MIT
steamodded
repo
https://github.com/Steamodded/smods
version
1.0.0-beta-1814a
commit
f8e4ae060df0e42ce698ffaf901a39a6ef424c0f
url
https://codeload.github.com/Steamodded/smods/zip/f8e4ae060df0e42ce698ffaf901a39a6ef424c0f
sha256
1cae496bfd1c5dbfbc5db1eb51137d822c44fb7758ba6beaf020e43f1b5f96db
folder
smods
license
GPL-3.0
balatrobot
repo
https://github.com/coder/balatrobot
version
1.5.2
commit
9052d76f14723293f6c6b2cecaa791a5c4ae68f3
url
https://codeload.github.com/coder/balatrobot/zip/refs/tags/v1.5.2
sha256
7b1352be6b79d3190a3ab7cc0c9a88b3af7d5247a0dc8a8be09252b0ee241d5e
folder
balatrobot
files
balatrobot.jsonbalatrobot.luaLICENSEsrc/lua/
settings
6 fields
BALATROBOT_AUDIO
1
BALATROBOT_FAST
0
BALATROBOT_HEADLESS
0
BALATROBOT_RENDER_ON_API
0
BALATROBOT_DEBUG
0
BALATROBOT_GAMESPEED
4
license
MIT
jackdaw
repo
https://github.com/TylerFlar/jackdaw-balatro
license
MIT, Copyright (c) 2026 Tyler Flar
used_by
bot.mjs (the scripted player's policy, ported from jackdaw/cli/smart_agent.py)
note
Not shipped and not installed: a 1:1 Python reimplementation of Balatro with a bit-exact PRNG, used to measure the policy over seeds before it touches the game. Its own validation bridge plays against live Balatro through the same balatrobot API this plugin uses.

mcp.template.json

runtime-config
mcpServers
balatro
3 fields
command
node
args
--permission--allow-fs-read=__REPO__/packages/core--allow-fs-read=__REPO__/games/balatro--allow-fs-read=__RUN_DIR__--allow-fs-write=__RUN_DIR____REPO__/packages/core/src/broker.mjs
env
3 fields
AAS_GAME_MODULE
__REPO__/games/balatro/plugin.mjs
AAS_RUN_DIR
__RUN_DIR__
AAS_ALLOWED_ENDPOINTS
127.0.0.1:12347

settings.json

runtime-config
permissions
allow
mcp__balatro__balatro_documentationmcp__balatro__balatro_screenshotmcp__balatro__balatro_exec
deny
BashWebFetchWebSearchAgentReadEditWriteNotebookEditGlobGrepSkillTodoWrite
defaultMode
acceptEdits
enableAllProjectMcpServers
yes
enabledMcpjsonServers
balatro