skills: opt-in callable_module helper for await <skill>(...)#55
Draft
rasdani wants to merge 1 commit into
Draft
Conversation
Add `rlm.skill.callable_module(name)`: skill authors call it from
their package's `__init__.py` to make `await <skill>(...)` shorthand
for `await <skill>.run(...)`.
Mechanism: subclasses `types.ModuleType` with an async `__call__` that
forwards to `self.run`, then sets the skill module's `__class__` to
that subclass in place. `run` and `PARAMETERS` stay accessible as
ordinary module attributes.
The kernel's `_inject_startup` drops the ad-hoc `_CallableModule`
wrap that used to force every installed skill into a callable form
from rlm's side. Skills that want the shorthand opt in themselves;
skills that don't stay as plain modules and callers write
`await <skill>.run(...)` explicitly.
rlm's own `__init__.py` opts in (one call to `callable_module(__name__)`)
so `await rlm('sub-task')` keeps working inside the kernel — same
semantics as before, returns an `RLMResult`.
Kernel startup becomes: pre-import each installed skill into the
user namespace, `import rlm` if recursion is allowed. No ModuleType
subclassing in the f-string any more.
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Move the
await <skill>(...)→await <skill>.run(...)shorthand out of rlm's kernel-startup f-string and into a tiny public helper skill authors opt into.rlm.skill.callable_module(name)— sets the skill module's__class__to aModuleTypesubclass whose async__call__forwards toself.run. Call it once from the skill package's__init__.pyafterrunis bound at module scope.src/rlm/__init__.pyopts in forrlmitself, soawait rlm('sub-task')keeps returningRLMResultinside the kernel.src/rlm/tools/ipython.pydrops the kernel-side_CallableModulewrap loop. Kernel startup now just does__import__(name)for each installed skill andimport rlmif recursion is allowed. No ModuleType subclassing in the f-string.Skill author usage
After this,
await edit(...)is equivalent toawait edit.run(...);edit.run,edit.PARAMETERSstay accessible unchanged.Coordination
The system prompt continues to advertise "Each skill is an async function by the same name". That promise is only true for skills that have adopted the opt-in, so this PR must merge together with the coordinated research-environments migration:
→ PrimeIntellect-ai/research-environments#329 (draft): opts in for all seven existing skills (
rlm_swe/edit,rlm_deepdive/websearch,rlm_deepdive/open_webpage,rlm_browsecomp/{exa,serper}/{websearch,open_webpage}). Two-line addition per__init__.py, no logic changes.Merge order: merge #55 first, then #329 once the skill packages can pick up a released
rlmthat exposesrlm.skill.callable_module. Skills that never opt in stay as plain modules — callers writeawait <skill>.run(...).Test plan
pytest(2/2) andruff checkcleanrlm.skill.callable_moduleapplied to a fake module exposing an asyncrun,await mod(...)andawait mod.run(...)return the same value andmod.PARAMETERSis intactimport rlmmakesrlmcallable:callable(rlm)is True andtype(rlm).__call__forwards torlm.runvf-eval rlm-sweto confirmawait edit(...)still works end-to-end🤖 Generated with Claude Code