{"data":{"kind":"file","path":"README.md","version_id":"j9oemcxgi6thylyabfgphm07","entry":{"name":"README.md","path":"README.md","is_directory":false,"size":3807,"modified_at":"2026-04-28T06:28:45.950000","content_hash":"2f762f753c6e963238ba23fbf3e9556b952f9c030eadf188d77de83e1ba4dda3"},"entries":[],"content":"# RLM Secrets\n\nA puzzle environment designed to thoroughly test RLM (Recursive Language Model) functionality.\n\n## Overview\n\nThis environment tests all major RLM components through a file-based puzzle:\n\n- **Root-level tools**: `decrypt_position`, `unveil_file_number`\n- **Sub-LLM tools**: `get_code_from_file_data`\n- **Sub-LLM calls**: via `llm_batch`\n- **File operations**: `ls`, `cat`, `rm`\n\n## The Puzzle\n\n1. Several files with random names exist in the working directory\n2. Each file contains a random UUID as content\n3. Files have a hidden \"correct order\" (positions 1, 2, 3, ...)\n4. One position is designated as the \"file to keep\"\n\n### Solution Flow\n\n1. **List files**: Root LLM runs `ls` to discover files\n2. **Get codes**: For each file:\n   - Read content with `cat`\n   - Call sub-LLM via `llm_batch` asking it to use `get_code_from_file_data`\n   - Sub-LLM calls the tool and returns the code\n3. **Decrypt positions**: Root LLM calls `decrypt_position(filename, code)` to learn each file's position\n4. **Unveil answer**: Root LLM calls `unveil_file_number([sorted_filenames])` to learn which position to keep\n5. **Clean up**: Delete all files except the one at the revealed position\n6. **Answer**: Set `RLM_CONTENT` to the kept file's position, `RLM_READY=1`\n\n## Tools\n\n### Root-Level (called directly by root LLM)\n\n```bash\ndecrypt_position <filename> <code>\n```\n\nReturns the 1-indexed position if the code is valid, error message otherwise.\n\n```bash\nunveil_file_number --json '{\"sorted_filenames\": [\"file1.txt\", \"file2.txt\", ...]}'\n```\n\nReturns which position's file to keep if order is correct, error message otherwise.\n\n### Sub-LLM Level (called by sub-LLMs via tool use)\n\n```python\nget_code_from_file_data(filename: str, filecontent: str) -> str\n```\n\nReturns the decryption code if filename and content match, a fake code otherwise.\n\n## Usage\n\n```bash\nprime eval run rlm-secrets\n```\n\n## Reward Functions\n\nBoth reward functions have equal weight (0.5 each):\n\n- **correct_answer**: 1.0 if final answer matches correct position\n- **correct_filesystem_state**: 1.0 if exactly one .txt file remains AND it's the correct one\n\n## Configuration\n\n| Parameter | Default | Description |\n|-----------|---------|-------------|\n| `num_train_examples` | 100 | Training puzzles |\n| `num_files` | 4 | Files per puzzle |\n| `max_turns` | 50 | Max REPL iterations |\n| `sub_llm_max_turns` | 3 | Max tool turns for sub-LLMs |\n| `max_sub_llm_parallelism` | 5 | Concurrent sub-LLM calls |\n| `code_execution_timeout` | 120 | Bash execution timeout (seconds) |\n| `**kwargs` | - | Passed on `RLMEnv.__init__` |\n\nNote: The eval dataset is not built separately. For evaluation, re-instantiate the\nenvironment with a different `seed` to generate a new synthetic split.\n\n## Why This Environment?\n\nThis environment is specifically designed to test RLM capabilities:\n\n1. **Forces root-LLM usage**: The correct order can only be obtained by calling the root-level tools\n2. **Forces sub-LLM usage**: The code can only be obtained by having a sub-LLM call `get_code_from_file_data`\n3. **Forces sub-LLM tool use**: Sub-LLMs must use their tool to get the code\n4. **Tests file operations**: Model must list, read, and delete files\n5. **Tests information flow**: Data must flow: file → sub-LLM → root-LLM → tool → answer\n\nThe puzzle is simple enough that models should be able to solve it, while being complex enough to exercise all RLM components.\n\n## Changelog\n\n- 0.1.3: align arg names with simplified RLMEnv (`max_iterations` → `max_turns`, `sub_tool_max_turns` → `sub_llm_max_turns`)\n- 0.1.2: sandbox labels no longer force in the default label\n- 0.1.1:\n  - add default \"rlm-secrets\" label to the `sandbox_labels` no matter what the user passes ther in the kwargs\n  - dedupe `sandbox_labels` if passed via the kwargs\n","encoding":"utf-8","truncated":false,"total_bytes":3807},"status":null}