Core Concepts¶
This page provides an in-depth look at RobotLab's fundamental building blocks.
Robot¶
A Robot is the primary unit of computation in RobotLab. It wraps an LLM with:
- A unique identity (name, description)
- A personality (system prompt/template)
- Capabilities (tools, MCP connections)
- A specific model configuration
Robot Anatomy¶
robot = RobotLab.build do
name "support_agent" # Unique identifier
description "Handles support requests" # Used for routing hints
model "claude-sonnet-4" # LLM model
# System prompt - defines personality
template <<~PROMPT
You are a friendly customer support agent for Acme Corp.
Always be polite and helpful. If you don't know something,
say so honestly.
PROMPT
# Tools - extend capabilities
tool :lookup_account do
description "Look up customer account"
parameter :email, type: :string, required: true
handler { |email:, **_| Account.find_by_email(email)&.to_h }
end
# MCP - external tool servers
mcp :inherit # Use network's MCP servers
end
Robot Lifecycle¶
stateDiagram-v2
[*] --> Created: RobotLab.build
Created --> Running: robot.run(state)
Running --> ToolExecution: tool_call
ToolExecution --> Running: result
Running --> Completed: stop_reason
Completed --> [*]
Robot Properties¶
| Property | Type | Description |
|---|---|---|
name |
String | Unique identifier within network |
description |
String | What the robot does |
model |
String | LLM model to use |
template |
String | System prompt |
local_tools |
Array | Defined tools |
mcp_clients |
Array | Connected MCP clients |
Tool¶
Tools give robots the ability to interact with external systems.
Tool Structure¶
tool = RobotLab::Tool.new(
name: "get_weather",
description: "Get current weather for a location",
parameters: {
location: {
type: "string",
description: "City name",
required: true
},
unit: {
type: "string",
enum: ["celsius", "fahrenheit"],
default: "celsius"
}
},
handler: ->(location:, unit: "celsius", **_context) {
WeatherAPI.current(location, unit: unit)
}
)
Tool Execution¶
When an LLM decides to use a tool:
- LLM generates a
ToolCallMessagewith tool name and arguments - RobotLab validates arguments against the tool's schema
- Tool handler is called with validated arguments
- Result is wrapped in a
ToolResultMessage - Result is sent back to the LLM for continued processing
Handler Context¶
Tool handlers receive context about the current execution:
handler: ->(param:, robot:, network:, state:) {
# robot - The Robot instance executing the tool
# network - The Network (or NetworkRun) context
# state - Current State with data, results, memory
}
Ignoring Context
Use **_context to accept but ignore context parameters:
ToolManifest¶
When you need to modify tool metadata without changing functionality:
manifest = RobotLab::ToolManifest.new(
tool: existing_tool,
name: "custom_name", # Override name
description: "New description" # Override description
)
Message Types¶
RobotLab uses a type hierarchy for messages:
classDiagram
Message <|-- TextMessage
Message <|-- ToolMessage
ToolMessage <|-- ToolCallMessage
ToolMessage <|-- ToolResultMessage
class Message {
+String type
+String role
+String content
+String stop_reason
}
class TextMessage {
+text?()
+user?()
+assistant?()
}
class ToolMessage {
+String id
+String name
+Hash input
}
class ToolCallMessage {
+Array~ToolMessage~ tools
}
class ToolResultMessage {
+ToolMessage tool
+Hash content
}
Message Roles¶
| Role | Description |
|---|---|
user |
Input from the user |
assistant |
Response from the LLM |
system |
System instructions |
tool |
Tool call or result |
Stop Reasons¶
| Reason | Description |
|---|---|
stop |
Natural completion |
tool |
Tool call requested |
max_tokens |
Token limit reached |
RobotResult¶
The output from a robot execution:
result = robot.run(state: state, network: network)
result.robot_name # => "support_agent"
result.output # => [TextMessage, ...]
result.tool_calls # => [ToolMessage, ...]
result.stop_reason # => "stop"
result.created_at # => Time
Accessing Response Content¶
# Get text response
text = result.output.select(&:text?).map(&:content).join
# Check if tools were called
has_tools = result.tool_calls.any?
# Get all tool names called
tool_names = result.tool_calls.map(&:name)
Configuration Hierarchy¶
RobotLab uses a cascading configuration system:
Global (RobotLab.configure)
│
├── mcp: [server1, server2]
├── tools: [tool1, tool2]
│
└── Network
│
├── mcp: :inherit | :none | [servers]
├── tools: :inherit | :none | [tools]
│
└── Robot
│
├── mcp: :inherit | :none | [servers]
└── tools: :inherit | :none | [tools]
The :inherit value pulls from the parent level.
Next Steps¶
- Robot Execution - Detailed execution flow
- Network Orchestration - Multi-robot coordination
- State Management - Managing conversation state