Skip to main content

Rewards & tools

This page answers two questions an RL or agent researcher actually has: what can the agent do inside an environment, and how do we score it? Tools are the actions; rewards are the signal.

Act, then score (click a node for source)​

Tools — the action space​

Every server ships the tools plugin, available on all images:

ToolEndpointWhat it does
BashPOST /api/tools/bashRun a bash script; returns bounded stdout/stderr and the exit code
Create filePOST /api/tools/file/createCreate a file with given content
Edit filePOST /api/tools/file/editReplace a 1-indexed, inclusive line range
Patch filePOST /api/tools/file/patchApply a unified diff
Upload chunkPOST /api/tools/file/uploadWrite one base64 chunk of raw bytes at an offset
Download chunkPOST /api/tools/file/downloadRead one base64 chunk of raw bytes from an offset

The three text file tools are also exposed as MCP tools (create_file, edit_file, patch_file) on the server's /mcp endpoint. With a JetBrains IDE plugin installed, an inspect endpoint runs the full IntelliJ static-analysis pipeline, and mcp-steroid exposes the IntelliJ Platform API (PSI, refactoring, debugger, VCS) as MCP tools. See the tools reference.

The Bash tool retains 1 MiB by default for each of stdout and stderr, split between the beginning and end of each stream. Callers can choose another positive byte limit or request complete output with max_output_bytes=None. A short marker reports omitted bytes when a stream is truncated; the marker itself is outside the per-stream limit. Output is still drained until completion or the execution timeout, preventing subprocess pipe deadlocks.

The two chunk endpoints are the binary channel. The orchestrator stores and replays a forwarded request as JSON text, so raw bytes cannot survive that round trip and base64 is what does. The client wraps them in upload_file / upload_bytes / download_file / download_bytes, which chunk the payload for you — use these rather than base64 through the bash tool, which is bounded by the size of a single shell script and puts the payload in the command log.

result = await server.execute_bash("python -m pytest -q")
await server.patch_file("/home/devuser/project/main.py", patch="--- ...")
await server.upload_file("./fixtures/repo.tar.gz", "/home/devuser/repo.tar.gz")

Rewards — the evaluation signal​

Three reward kinds turn the environment's state into a number an RL loop can train on. Each runs a script inside the sandbox and returns a structured result.

RewardCallResult
Compilationserver.compilation_reward(compilation_script=...).success (bool)
Setupserver.setup_reward(setup_check_script=...).success (bool)
Testserver.test_reward(test_script=...).passed, .failed, .output
result = await server.test_reward(test_script="cd /project && python -m pytest -q")
score = result.passed / (result.passed + result.failed)

Because the orchestrator persists every forwarded request and response, rewards can also be recomputed offline from stored runs — making evaluation reproducible.

How an episode uses both​

A typical RL episode: start_server with reuse_strategy=RESET → the agent acts via tools → call a reward → release the server for reuse. The full sequence is on the data flow page.

View source​