Documentation Index
Fetch the complete documentation index at: https://docs.reasonos.com/llms.txt
Use this file to discover all available pages before exploring further.
Agent SDK
The Agent SDK lets you customize and extend the RBS coding agent with project-specific capabilities. Define custom tools, system prompts, teammate roles, subagents, and slash commands — all in your WORKSPACE.rbs or BUILD.rbs files using the RBS DSL.
Overview
| Extension | API | Purpose |
|---|
| Tools | native.define_agent_tool() | Custom actions the agent can take. |
| Prompts | native.define_agent_prompt() | Specialized system prompts with linked tools. |
| Subagents | native.define_agent_subagent() | One-shot specialist agents for isolated tasks. |
| Teammate roles | native.define_agent_teammate_role() | Reusable roles for multi-agent teams. |
| Skills | native.define_agent_skill() | Slash commands for common workflows. |
Load the built-in agent tools (Git status, Git log, file analysis, etc.) in your workspace:
# WORKSPACE.rbs
load("@rbs//agent/tools.rbs", "AGENT_TOOLS_LOADED")
native.define_agent_tool(
name = "list_processes",
description = "List running processes on the system",
shell_cmd = "ps aux | head -20",
)
native.define_agent_tool(
name = "search_code",
description = "Search for a pattern in source files",
attrs = {
"pattern": attr.string(
doc = "The regex pattern to search for",
mandatory = True,
),
"file_type": attr.string(
doc = "File extension to search (e.g., 'py', 'java')",
default = "",
),
},
shell_cmd = "rg '{pattern}' --type {file_type}",
)
For complex logic, use an implementation function with full ctx access:
def _analyze_file_impl(ctx):
"""Analyze a file and return statistics."""
path = ctx.attr.path
# Read file content
content = ctx.file.read(path)
if content == None:
return ctx.output.error("File not found: " + path)
# Calculate statistics
lines = content.split("\n")
line_count = len(lines)
char_count = len(content)
# Run additional analysis
result = ctx.shell.capture(command = "wc -w " + path)
word_count = result.strip().split()[0] if result else "0"
return ctx.output.success(
message = "File analyzed",
data = {
"path": path,
"lines": line_count,
"characters": char_count,
"words": word_count,
},
)
native.define_agent_tool(
name = "analyze_file",
description = "Analyze a file and return statistics (line count, word count, etc.)",
attrs = {
"path": attr.string(
doc = "Path to the file to analyze",
mandatory = True,
),
},
implementation = _analyze_file_impl,
)
When using implementation, your function receives a ctx object with these modules:
ctx.attr — Access parameters
def _my_tool(ctx):
path = ctx.attr.path # String attribute
count = ctx.attr.count # Integer attribute
files = ctx.attr.files # List attribute
options = ctx.attr.options # Dict attribute
ctx.file — File operations
def _my_tool(ctx):
content = ctx.file.read("path/to/file.txt") # Read a file
ctx.file.write("output.txt", "Hello World") # Write a file
exists = ctx.file.exists("config.json") # Check existence
files = ctx.file.glob("src/**/*.py") # List files matching pattern
ctx.dir — Directory operations
def _my_tool(ctx):
entries = ctx.dir.list("src/") # List directory
ctx.dir.create("output/reports") # Create directory
exists = ctx.dir.exists("build/") # Check existence
ctx.dir.delete("tmp/", recursive = True) # Delete directory
ctx.shell — Execute commands
def _my_tool(ctx):
output = ctx.shell.capture(command = "git status --short") # Capture output
exit_code = ctx.shell.run(command = "make build") # Run without capturing
output = ctx.shell.capture(command = "npm test", cwd = "frontend/") # With working dir
ctx.path — Path manipulation
def _my_tool(ctx):
full_path = ctx.path.join("src", "main", "app.py") # Join paths
dir_name = ctx.path.dir("src/main/app.py") # Get directory
base = ctx.path.base("src/main/app.py") # Get base name
ext = ctx.path.ext("app.py") # Get extension
abs_path = ctx.path.abs("relative/path") # Absolute path
ctx.json — JSON operations
def _my_tool(ctx):
data = ctx.json.parse('{"name": "test", "count": 42}') # Parse JSON
json_str = ctx.json.stringify({"result": "success"}) # Serialize
pretty = ctx.json.stringify(data, indent = 2) # Pretty print
ctx.output — Return results
def _my_tool(ctx):
# Success with message and data
return ctx.output.success(
message = "Found 5 files",
data = {"files": ["a.py", "b.py"], "count": 5},
)
# Error
return ctx.output.error("File not found: " + path)
Custom prompts
Create specialized system prompts with linked tools:
native.define_agent_prompt(
name = "code_reviewer",
system_prompt = """You are a code review expert. Your role is to:
1. Analyze code for bugs and issues
2. Suggest improvements and best practices
3. Check for security vulnerabilities
4. Ensure code follows project conventions
Always explain your reasoning and provide specific examples.""",
tools = [
"read_files",
"code_search",
"analyze_file",
],
)
Custom subagents
Create subagent types for one-shot, isolated specialist tasks:
native.define_agent_subagent(
name = "security_auditor",
description = "Performs security analysis of code changes",
when_to_use = "When reviewing code for security vulnerabilities",
system_prompt = """You are a security auditor. Analyze the provided code for:
1. SQL injection vulnerabilities
2. XSS attack vectors
3. Authentication bypass risks
4. Sensitive data exposure
5. Dependency vulnerabilities
Report findings with severity levels and remediation steps.""",
tools = ["read_files", "code_search", "run_terminal_command"],
read_only = True,
)
| Parameter | Type | Required | Description |
|---|
name | string | Yes | Unique subagent name. |
description | string | Yes | What the subagent does. |
when_to_use | string | No | Guidance for when to invoke this subagent. |
system_prompt | string | Yes | System prompt for the subagent. |
tools | string list | No | Tools the subagent can use. |
read_only | bool | No | If True, the subagent cannot modify files. |
Custom teammate roles
Create reusable roles for multi-agent teams:
native.define_agent_teammate_role(
name = "ml_engineer",
description = "Machine learning specialist for model training and optimization",
system_prompt = """You are an ML engineer specializing in:
- PyTorch and distributed training (DDP, FSDP)
- Model architecture design and optimization
- Training pipeline development
- Hyperparameter tuning and experiment tracking
Always validate training code with small samples before full runs.""",
tools = ["read_files", "write_file", "run_terminal_command", "code_search"],
capabilities = ["model_training", "data_pipelines", "optimization"],
)
| Parameter | Type | Required | Description |
|---|
name | string | Yes | Role name (used in spawn_teammate). |
description | string | Yes | What this role specializes in. |
system_prompt | string | Yes | System prompt for teammates with this role. |
tools | string list | No | Tools available to this role. |
capabilities | string list | No | Declared capabilities for role matching. |
Custom roles are automatically available when spawning teammates:
rbs agent "Spawn an ml_engineer teammate to optimize the training pipeline"
Custom skills (slash commands)
Create slash commands for common workflows:
native.define_agent_skill(
name = "deploy",
description = "Deploy the application to staging or production",
usage = "/deploy [staging|production]",
prompt = """Deploy the application. Steps:
1. Run all tests
2. Build the production binary
3. Push to the container registry
4. Apply Kubernetes manifests
5. Verify the deployment is healthy
Target environment: {args}""",
tools = ["run_terminal_command", "read_files"],
)
| Parameter | Type | Required | Description |
|---|
name | string | Yes | Skill name (becomes a /command). |
description | string | Yes | What the skill does. |
usage | string | No | Usage example. |
prompt | string | Yes | Prompt template. Use {args} for user input. |
tools | string list | No | Tools the skill can use. |
Long-term memory
The coding agent has a persistent memory system that remembers things across sessions — design patterns, user corrections, file-specific notes, and architectural decisions. Memory is stored as human-editable markdown in .rbs/memory/.
How memory works
Session Start
├─→ Load rules (.agent-rules/, .cursorrules, etc.)
├─→ Load general memory (.rbs/memory/general.md)
└─→ Agent loop
├─→ read_files("src/api.py")
│ → File content returned
│ + .rbs/memory/src/api.py.md (auto-injected)
│ + .rbs/memory/src/_package.md (auto-injected)
├─→ Agent discovers pattern → memory_save(...)
├─→ User corrects agent → agent saves correction
└─→ Session ends → memory persists
Memory files are plain markdown, stored alongside your code:
.rbs/memory/
├── general.md # Project-wide notes
├── src/
│ └── api.py.md # Notes about src/api.py
└── services/
└── auth/
├── _package.md # Notes about the auth package
└── handler.py.md # Notes about handler.py
Each entry uses ## [m-xxxxxxxx] headers:
# General Project Memory
## [m-abc12345] 2026-02-17 10:30
> Tags: architecture, convention
This project uses dependency injection throughout.
Never create singletons — pass dependencies through constructors.
## [m-def67890] 2026-02-17 14:15
> Tags: user-correction
User correction: Use interfaces for the repository pattern,
not concrete implementations.
| Tool | Description |
|---|
memory_save | Save a new memory entry. |
memory_recall | Recall memories for a file or package. |
memory_update | Update an existing entry by ID. |
memory_delete | Delete a stale or incorrect entry. |
memory_search | Search across all memory files. |
memory_list | List all stored memory files. |
Editing memory directly
Memory files are just markdown. You can read, edit, add, and delete entries directly in your editor — the agent respects your changes.
## [m-user0001] 2026-02-17 16:00
> Tags: convention
We use dependency injection throughout the project.
Never create singletons or global state.
Complete example
# WORKSPACE.rbs
load("@rbs//agent/tools.rbs", "AGENT_TOOLS_LOADED")
# Custom tool: Check test coverage
def _coverage_check_impl(ctx):
result = ctx.shell.capture(command = "rbs test //... --coverage")
if result == None:
return ctx.output.error("Failed to run tests")
return ctx.output.success(
message = "Coverage report generated",
data = {"output": result},
)
native.define_agent_tool(
name = "check_coverage",
description = "Run tests and check code coverage",
implementation = _coverage_check_impl,
)
# Custom tool: Generate changelog
native.define_agent_tool(
name = "changelog",
description = "Generate changelog from recent git commits",
attrs = {
"since": attr.string(
doc = "Git ref to start from (e.g., 'v1.0.0', 'HEAD~10')",
default = "HEAD~10",
),
},
shell_cmd = "git log --oneline {since}..HEAD",
)
# Custom prompt for this project
native.define_agent_prompt(
name = "project_assistant",
system_prompt = """You are an assistant for this codebase.
Key conventions:
- Write tests for all new code
- Use dependency injection
- Update CHANGELOG.md for changes
When making changes, always run tests first.""",
tools = [
"read_files",
"write_file",
"str_replace",
"run_terminal_command",
"check_coverage",
"changelog",
],
)
# Custom teammate role
native.define_agent_teammate_role(
name = "data_engineer",
description = "Data pipeline and preprocessing specialist",
system_prompt = "You build efficient data loading and preprocessing pipelines.",
tools = ["read_files", "write_file", "run_terminal_command"],
capabilities = ["data_loading", "preprocessing", "augmentation"],
)
# Custom skill
native.define_agent_skill(
name = "release",
description = "Create a release",
usage = "/release [version]",
prompt = "Create release {args}: run tests, update changelog, tag, build, and publish.",
tools = ["run_terminal_command", "read_files", "write_file"],
)
Attribute types reference
| Type | Description | Example |
|---|
attr.string() | String value. | "hello" |
attr.int() | Integer value. | 42 |
attr.bool() | Boolean value. | True |
attr.string_list() | List of strings. | ["a", "b"] |
attr.label() | Build target label. | "//pkg:target" |
attr.label_list() | List of labels. | ["//a:x", "//b:y"] |
attr.string_dict() | String dictionary. | {"key": "value"} |
All attribute types support:
doc (string) — Description shown to the AI model.
mandatory (bool) — Whether the parameter is required.
default (any) — Default value.
Best practices
- Clear descriptions — Write descriptions that help the AI model understand when to use the tool.
- Document parameters — Use
doc for all attributes.
- Handle errors — Always check for errors and return meaningful messages.
- Keep tools focused — Each tool should do one thing well.
- Define roles for your team — Create custom teammate roles matching your project needs.
- Use subagents for isolation — Use read-only subagents for analysis tasks.
- Create skills for workflows — Turn common multi-step workflows into slash commands.