Skip to content

The agent's tools and settings

gpt-5.6-luna on CodexRead 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.

config.template.toml

runtime-config
# AAS run configuration for Codex. Generated by `aas configure --runtime codex`;
# machine paths are replaced with __RUN_DIR__ etc. when published as runtime-config/.
# Derived from cozyblaze's portal-agent, run/config.template.toml
# (MIT, Copyright (c) 2026 cozyblaze; the license text is published next to this file as LICENSE).
model_reasoning_summary = "detailed"
hide_agent_reasoning = false
approval_policy = "never"
default_permissions = "aas-run"
web_search = "disabled"

[windows]
sandbox = "elevated"

[tools]
web_search = false

[features]
shell_tool = false
unified_exec = false
plugins = false
apps = false
browser_use = false
computer_use = false
image_generation = false
multi_agent = false
skill_search = false
hooks = false

[features.context_management]
experimental_mode = true

[apps._default]
enabled = false

[mcp_servers.node_repl]
command = "node"
enabled = false

# The AAS broker. Node permission flags limit filesystem writes to the run
# directory and reads to core plus the game plugin; hardening.mjs limits its
# network access to the game's endpoint(s).
[mcp_servers.balatro]
command = "node"
cwd = '__RUN_DIR__'
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',
]
startup_timeout_sec = 60
tool_timeout_sec = 180
enabled_tools = [
  "balatro_documentation",
  "balatro_screenshot",
  "balatro_exec",
]
default_tools_approval_mode = "approve"

[mcp_servers.balatro.env]
AAS_GAME_MODULE = "__REPO__/games/balatro/plugin.mjs"
AAS_RUN_DIR = "__RUN_DIR__"
AAS_ALLOWED_ENDPOINTS = "127.0.0.1:12347"

[permissions.aas-run]
extends = ":workspace"
description = "Write only inside the run directory; deny host reads and command networking."

[permissions.aas-run.filesystem]
":root" = "deny"
":minimal" = "read"
":tmpdir" = "deny"
":slash_tmp" = "deny"

[permissions.aas-run.network]
enabled = false

[shell_environment_policy]
inherit = "core"
ignore_default_excludes = false

LICENSE

runtime-config
MIT License

Copyright (c) 2026 cozyblaze

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.