Basic Chat¶
A simple conversational robot example.
Overview¶
This example demonstrates the minimal setup for a conversational robot that can respond to user messages using robot.run("message").
The closest runnable file in this repository is
examples/01_simple_robot.rb.
The snippets below wrap that same API in a small REPL.
Complete Example¶
#!/usr/bin/env ruby
require "bundler/setup"
require "robot_lab"
# Build a simple assistant
assistant = RobotLab.build(
name: "assistant",
description: "A helpful conversational assistant",
system_prompt: <<~PROMPT,
You are a helpful, friendly assistant. You provide clear,
concise answers to questions. Be conversational but informative.
PROMPT
model: "claude-sonnet-4"
)
# Simple REPL
puts "Chat with the assistant (type 'quit' to exit)"
puts "-" * 50
loop do
print "\nYou: "
input = gets&.chomp
break if input.nil? || input.downcase == "quit"
next if input.empty?
# Run the robot with the user's message
result = assistant.run(input)
# Display response
puts "\nAssistant: #{result.last_text_content}"
end
puts "\nGoodbye!"
With Streaming¶
Pass a block to run to receive each RubyLLM::Chunk as it arrives.
[!WARNING] The yielded object is a
RubyLLM::Chunk. Read its text withchunk.content. There is nochunk.textmethod — a guard likeif chunk.respond_to?(:text)silently prints nothing.
#!/usr/bin/env ruby
require "bundler/setup"
require "robot_lab"
assistant = RobotLab.build(
name: "assistant",
system_prompt: "You are a helpful assistant.",
model: "claude-sonnet-4"
)
puts "Chat with streaming (type 'quit' to exit)"
puts "-" * 50
loop do
print "\nYou: "
input = gets&.chomp
break if input.nil? || input.downcase == "quit"
next if input.empty?
print "\nAssistant: "
assistant.run(input) { |chunk| print chunk.content }
puts
end
puts "\nGoodbye!"
You can also wire streaming once at build time with the on_content: callback,
which fires on every run:
assistant = RobotLab.build(
name: "assistant",
system_prompt: "You are a helpful assistant.",
on_content: ->(chunk) { print chunk.content }
)
assistant.run("Tell me a one-sentence fact about Ruby.")
When both are supplied, the stored on_content callback fires first, then the
block. See examples/05_streaming.rb
for all four variations (stored callback, per-call block, both, and via RunConfig).
With Template¶
Templates are .md files with YAML front matter, resolved from the configured
prompts directory (ROBOT_LAB_TEMPLATE_PATH). Parameters declared null in the
front matter are required and are supplied via context:.
#!/usr/bin/env ruby
require "bundler/setup"
require "robot_lab"
# Template file: prompts/support.md
# ---
# description: Support assistant
# parameters:
# company_name: null
# tone: friendly
# ---
# You are a <%= tone %> support assistant for <%= company_name %>.
assistant = RobotLab.build(
name: "assistant",
template: :support,
context: { company_name: "Acme Corp", tone: "friendly" },
model: "claude-sonnet-4"
)
puts "Chat with template-based assistant (type 'quit' to exit)"
puts "-" * 50
loop do
print "\nYou: "
input = gets&.chomp
break if input.nil? || input.downcase == "quit"
next if input.empty?
result = assistant.run(input)
puts "\nAssistant: #{result.last_text_content}"
end
puts "\nGoodbye!"
A full template-driven network lives in
examples/06_prompt_templates.rb.
With Memory¶
#!/usr/bin/env ruby
require "bundler/setup"
require "robot_lab"
assistant = RobotLab.build(
name: "assistant",
system_prompt: "You are a helpful assistant. Use the user's name when you know it.",
model: "claude-sonnet-4"
)
puts "Chat with memory (type 'quit' to exit)"
puts "-" * 50
# Store user info in the robot's inherent memory
assistant.memory[:user_name] = "Alice"
loop do
print "\nYou: "
input = gets&.chomp
break if input.nil? || input.downcase == "quit"
next if input.empty?
# The robot's persistent @chat maintains conversation history automatically
result = assistant.run(input)
puts "\nAssistant: #{result.last_text_content}"
end
puts "\nGoodbye!"
The full Memory API — subscriptions, StateProxy, blocking reads, clone and
reset — is demonstrated in
examples/10_memory.rb.
Bare Robot with Chaining¶
#!/usr/bin/env ruby
require "bundler/setup"
require "robot_lab"
# Build a bare robot with no template or prompt
robot = RobotLab.build(name: "bot")
# Configure via chaining
result = robot
.with_model("claude-sonnet-4")
.with_temperature(0.7)
.with_instructions("You are a pirate. Respond in pirate speak.")
.run("What is the weather like today?")
puts result.last_text_content
[!NOTE] Only the
with_*methods thatRubyLLM::Chatexposes are delegated:with_context,with_headers,with_instructions,with_model,with_params,with_schema,with_temperature,with_thinking,with_tool,with_tools(plus RobotLab's ownwith_templateandwith_bus). There is nowith_max_tokens/with_top_p/with_top_k— use a constructor kwarg (max_tokens: 2000) orwith_params(max_tokens: 2000, top_p: 0.3).
examples/09_chaining.rb walks through chaining and reconfiguration without
making any LLM calls.
Running¶
# Set API key
export ANTHROPIC_API_KEY="your-key"
# Simplest runnable robot
ruby examples/01_simple_robot.rb
# Streaming
ruby examples/05_streaming.rb
# with_* chaining and reconfiguration (no LLM calls)
ruby examples/09_chaining.rb
Key Concepts¶
- Robot Building: Use
RobotLab.build(name:, system_prompt:)orRobotLab.build(name:, template:)to create a robot - Execution: Call
robot.run("message")to send a message and get a response - Response: Access the text via
result.last_text_content(aliased asresult.reply) - Streaming: Pass a block to
robot.run("message") { |chunk| print chunk.content }, or seton_content:at build time - Memory: Access inherent memory via
robot.memory[:key] - Chaining: Configure with the delegated
with_*methods, which returnself - Conversation History: The persistent
@chatmaintains history across multipleruncalls