Skip to content

Gate skills behind RLM_ENABLED_TOOLS (default: edit)#30

Open
rasdani wants to merge 1 commit into
mainfrom
feat/rlm-enabled-tools
Open

Gate skills behind RLM_ENABLED_TOOLS (default: edit)#30
rasdani wants to merge 1 commit into
mainfrom
feat/rlm-enabled-tools

Conversation

@rasdani

@rasdani rasdani commented Apr 16, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds an allowlist env var `RLM_ENABLED_TOOLS` that filters discovered skills in two places:

  • `tools.get_installed_skills()` — the list surfaced in the system prompt's "Installed skills" line
  • `kernel_shim.install_shims()` — the proxy modules registered in the external ipython kernel so `import ` works

The CLI binaries themselves stay on PATH (we only gate the Python shim and prompt exposure).

`RLM_ENABLED_TOOLS` behavior
unset defaults to `edit`
`edit,websearch` allowlist of names
`*` no filtering (keep all)
`` (empty) disable all skills

Motivation

Both `edit` and `websearch` are installed unconditionally by `install.sh`. Previously this meant every rollout had websearch available regardless of the training config, and there was no way to turn it off short of deleting the skill from the repo or filtering at install time. This env var lets training orchestrators opt skills in/out per run.

Test plan

Verified in a live sandbox (python:3.11-slim):

  • `get_installed_skills()` unset → `['edit']`
  • `RLM_ENABLED_TOOLS=edit,websearch` → `['edit', 'websearch']`
  • `RLM_ENABLED_TOOLS=*` → `['edit', 'websearch']`
  • `RLM_ENABLED_TOOLS=""` → `[]`
  • `build_system_prompt(...)` with default env prints `Installed skills: `edit`.` (no websearch)

_kernel_shim_'s filter logic mirrors `tools`, so the same allowlist applies to proxy-module registration in external ipython kernels.

🤖 Generated with Claude Code


Note

Low Risk
Small, localized env-var gating around skill enumeration and shim registration; main risk is misconfiguration unintentionally hiding required tools.

Overview
Introduces RLM_ENABLED_TOOLS as an allowlist to control which skills are exposed at runtime, defaulting to edit, supporting * for no filtering and empty string for disabling all.

Updates tools.get_installed_skills() to filter discovered skill distributions via this allowlist, and updates kernel_shim.install_shims() to only register proxy modules for enabled skills so disabled tools are neither importable in external IPython kernels nor shown in the system prompt (while leaving the underlying CLIs on PATH).

Reviewed by Cursor Bugbot for commit d4b7209. Bugbot is set up for automated code reviews on this repo. Configure here.

RLM_ENABLED_TOOLS is a comma-separated allowlist of skill names. It
filters both the system-prompt "Installed skills" listing
(tools.get_installed_skills) and the kernel_shim sys.modules proxies,
so that a disabled skill is neither advertised to the agent nor
importable from the ipython kernel. The CLI itself stays on PATH.
RLM_ENABLED_TOOLS=* opts out of filtering entirely; "" disables every
skill; unset defaults to 'edit'.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit d4b7209. Configure here.

Comment thread src/rlm/tools.py
raw = os.environ.get("RLM_ENABLED_TOOLS", DEFAULT_ENABLED_TOOLS).strip()
if raw == "*":
return None
return frozenset(name.strip() for name in raw.split(",") if name.strip())

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enabled tools not normalized, breaking hyphenated skill matching

Low Severity

_parse_enabled_tools() returns raw user-provided names without applying _normalize_skill_name, but get_installed_skills() normalizes discovered names (hyphens → underscores) before the set intersection skills &= enabled. A skill whose distribution suffix contains hyphens (e.g. rlm-skill-web-search → discovered as web_search) would never match if the user writes web-search in RLM_ENABLED_TOOLS. Both sides of the intersection need consistent normalization.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit d4b7209. Configure here.

Comment thread src/rlm/kernel_shim.py
def _parse_enabled_tools() -> frozenset[str] | None:
"""Mirror of rlm.tools._parse_enabled_tools (duplicated to keep this
module independent of rlm.__init__, which pulls in openai)."""
raw = os.environ.get("RLM_ENABLED_TOOLS", "edit").strip()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicated default diverges from named constant

Low Severity

tools.py introduces a DEFAULT_ENABLED_TOOLS constant to centralize the default, but the duplicated _parse_enabled_tools() in kernel_shim.py hardcodes the string "edit" directly. If someone updates DEFAULT_ENABLED_TOOLS, the kernel shim's default silently diverges, causing the system prompt and kernel to disagree on which skills are enabled.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit d4b7209. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant