The rfx skills system enables natural language control of robots by exposing Python functions to LLM agents. Skills are automatically converted to tool schemas (OpenAI/Anthropic format) for agent consumption.Inspired by DimensionalOS’s skill-based architecture, the system uses decorators and docstring parsing to create agent-callable capabilities.
The SkillRegistry manages collections of skills for LLM agent integration:
from rfx.skills import SkillRegistry# Create a registryregistry = SkillRegistry()# Register skillsregistry.register(walk_forward)registry.register(survey)# Or register a raw functiondef wave(): '''Wave the front leg''' go2.set_motor_position(3, 0.5, 20.0, 0.5) # FL_HIPregistry.register(wave, tags=["gesture"])# List all skillsprint(registry.describe())# Output:# Available skills:# - walk_forward: Walk forward by the specified distance in meters# Parameters: distance: number# - look_around: Rotate in place to survey surroundings# - wave: Wave the front leg
The registry provides methods for managing and querying skills:
class SkillRegistry: def register(self, skill_or_func: Skill | Callable, **kwargs) -> Skill: """Register a skill or function.""" def unregister(self, name: str) -> Skill | None: """Remove a skill from the registry.""" def get(self, name: str) -> Skill | None: """Get a skill by name.""" def execute(self, name: str, **kwargs: Any) -> Any: """Execute a skill by name with arguments.""" def filter_by_tag(self, tag: str) -> list[Skill]: """Get skills with a specific tag.""" def to_tools(self) -> list[dict[str, Any]]: """Convert all skills to OpenAI tool format.""" def to_anthropic_tools(self) -> list[dict[str, Any]]: """Convert all skills to Anthropic tool format."""
The skills system parses docstrings to extract descriptions and parameter documentation. Both Google-style and NumPy-style docstrings are supported:
@rfx.skilldef move_joint(joint_id: int, angle: float, speed: float = 1.0): '''Move a single joint to target angle. This function commands a joint to move to the specified angle at the given speed. Args: joint_id: Joint identifier (0-11) angle: Target angle in radians speed: Movement speed multiplier Returns: True if command was successful ''' # Implementation return True
Parameter descriptions are automatically included in tool schemas. Write clear docstrings to help LLMs understand skill capabilities.
For testing or async code, use context-scoped registries:
from rfx.skills import skill_registry_contextasync def test_skills(): with skill_registry_context() as registry: @skill def test_skill(): '''Test skill''' pass registry.register(test_skill) # Registry is isolated to this context assert "test_skill" in registry # Registry is cleaned up after context exits
The global registry get_global_registry() is deprecated. Use skill_registry_context() for new code or get_current_registry() for backward compatibility.
Type hints are automatically converted to JSON schema types:
Python Type
JSON Type
str
"string"
int
"integer"
float
"number"
bool
"boolean"
list
"array"
dict
"object"
None / NoneType
"null"
Implementation in rfx/python/rfx/skills.py:322-341:
def _python_type_to_json_type(hint: Any) -> str: """Convert Python type hint to JSON schema type.""" origin = getattr(hint, "__origin__", None) if hint is str: return "string" elif hint is int: return "integer" elif hint is float: return "number" elif hint is bool: return "boolean" elif hint is list or origin is list: return "array" elif hint is dict or origin is dict: return "object" elif hint is None or hint is type(None): return "null" else: return "string"