RCrewAI
Build powerful AI agent crews in Ruby that work together to accomplish complex tasks.
RCrewAI is a Ruby implementation of the CrewAI framework, allowing you to create autonomous AI agents that collaborate to solve problems and complete tasks with human oversight and enterprise-grade features.
π Features
- π€ Intelligent Agents: AI agents with reasoning loops, memory, and tool usage capabilities
- π Multi-LLM Support: OpenAI, Anthropic (Claude), Google (Gemini), Azure OpenAI, and Ollama
- π οΈ Rich Tool Ecosystem: Web search, file operations, SQL, email, code execution, PDF processing, and custom tools
- π§ Cognitive Memory: Semantic recall (embeddings + cosine) with optional SQLite persistence and short-term/long-term/entity/tool memory types
- π€ Human-in-the-Loop: Interactive approval workflows, human guidance, and collaborative decision making
- β‘ Advanced Task System: Dependencies, retries, async/concurrent execution, and context sharing
- ποΈ Hierarchical Teams: Manager agents that coordinate and delegate tasks to specialist agents
- π Production Ready: Security controls, error handling, logging, monitoring, and sandboxing
- π― Flexible Orchestration: Sequential, hierarchical, and concurrent execution modes
- π Flows: Event-driven workflows with
start/listen/router, branching, and persistent state - π Knowledge (RAG): Ground agents in your own documents with built-in retrieval
- π Ruby-First Design: Built specifically for Ruby developers with idiomatic patterns
π¦ Installation
Add this line to your application's Gemfile:
gem 'rcrewai'
And then execute:
$ bundle install
Or install it yourself as:
$ gem install rcrewai
πββοΈ Quick Start
require 'rcrewai'
# Configure your LLM provider
RCrewAI.configure do |config|
config.llm_provider = :openai # or :anthropic, :google, :azure, :ollama
config.temperature = 0.1
end
# Create intelligent agents with specialized tools
researcher = RCrewAI::Agent.new(
name: "researcher",
role: "Senior Research Analyst",
goal: "Uncover cutting-edge developments in AI",
backstory: "Expert at finding and analyzing the latest tech trends",
tools: [RCrewAI::Tools::WebSearch.new],
verbose: true
)
writer = RCrewAI::Agent.new(
name: "writer",
role: "Tech Content Strategist",
goal: "Create compelling technical content",
backstory: "Skilled at transforming research into engaging articles",
tools: [RCrewAI::Tools::FileWriter.new]
)
# Create crew with sequential process
crew = RCrewAI::Crew.new("ai_research_crew")
crew.add_agent(researcher)
crew.add_agent(writer)
# Define tasks with dependencies
research_task = RCrewAI::Task.new(
name: "research_ai_trends",
description: "Research the latest developments in AI for 2024",
agent: researcher,
expected_output: "Comprehensive report on AI trends with key insights"
)
writing_task = RCrewAI::Task.new(
name: "write_article",
description: "Write an engaging 1000-word article about AI trends",
agent: writer,
context: [research_task], # Uses research results as context
expected_output: "Publication-ready article saved as ai_trends.md"
)
crew.add_task(research_task)
crew.add_task(writing_task)
# Execute - agents will reason, search, and produce real results!
results = crew.execute
puts "β
Crew completed #{results[:completed_tasks]}/#{results[:total_tasks]} tasks"
π― Key Capabilities
π§ Advanced Agent Intelligence
- Multi-step Reasoning: Complex problem decomposition and solving
- Tool Selection: Intelligent tool usage based on task requirements
- Context Awareness: Memory-driven decision making from past executions
- Learning Capability: Short-term and long-term memory systems
π οΈ Comprehensive Tool Ecosystem
- Web Search: DuckDuckGo integration for research
- File Operations: Read/write files with security controls
- SQL Database: Secure database querying with connection management
- Email Integration: SMTP email sending with attachment support
- Code Execution: Sandboxed code execution environment
- PDF Processing: Text extraction and document processing
- Custom Tools: Extensible framework for building specialized tools
π€ Human-in-the-Loop Integration
- Interactive Approval: Human confirmation for sensitive operations
- Real-time Guidance: Human input during agent reasoning processes
- Task Confirmation: Human approval before executing critical tasks
- Result Validation: Human review and revision of agent outputs
- Error Recovery: Human intervention when agents encounter failures
ποΈ Enterprise-Grade Orchestration
- Hierarchical Teams: Manager agents coordinate and delegate to specialists
- Async Execution: Parallel task processing with intelligent dependency management
- Delegation Systems: Automatic task assignment based on agent capabilities
- Process Types: Sequential, hierarchical, and consensual execution modes
π§ LLM Provider Support
# OpenAI (GPT-4, GPT-3.5, etc.)
RCrewAI.configure do |config|
config.llm_provider = :openai
config.openai_api_key = ENV['OPENAI_API_KEY']
config.model = 'gpt-4'
end
# Anthropic Claude
RCrewAI.configure do |config|
config.llm_provider = :anthropic
config.anthropic_api_key = ENV['ANTHROPIC_API_KEY']
config.model = 'claude-3-sonnet-20240229'
end
# Google Gemini
RCrewAI.configure do |config|
config.llm_provider = :google
config.google_api_key = ENV['GOOGLE_API_KEY']
config.model = 'gemini-pro'
end
# Azure OpenAI
RCrewAI.configure do |config|
config.llm_provider = :azure
config.azure_api_key = ENV['AZURE_OPENAI_API_KEY']
config.azure_endpoint = ENV['AZURE_OPENAI_ENDPOINT']
config.model = 'gpt-4'
end
# Local Ollama
RCrewAI.configure do |config|
config.llm_provider = :ollama
config.ollama_url = 'http://localhost:11434'
config.model = 'llama2'
end
Per-agent LLM
The RCrewAI.configure block sets the crew-wide default. Any agent can override
it with the llm: option, so a single crew can mix providers and models β for
example a cheap model for workers and a stronger one for the manager:
# Provider only (uses that provider's configured model + key)
researcher = RCrewAI::Agent.new(name: 'researcher', role: '...', goal: '...',
llm: :anthropic)
# Provider + model (and optionally api_key / temperature)
manager = RCrewAI::Agent.new(name: 'manager', role: '...', goal: '...',
llm: { provider: :anthropic, model: 'claude-3-opus-20240229' })
worker = RCrewAI::Agent.new(name: 'worker', role: '...', goal: '...',
llm: { provider: :openai, model: 'gpt-4o-mini' })
# Or pass a pre-built client instance
worker = RCrewAI::Agent.new(name: 'worker', role: '...', goal: '...',
llm: my_client)
Omit llm: to use the global RCrewAI.configure settings. Overrides never
mutate the global configuration.
π€ Structured Output, Guardrails & File Output
Tasks can validate, transform, and persist their output:
task = RCrewAI::Task.new(
name: 'extract',
description: 'Extract the article title and word count as JSON',
agent: analyst,
# Structured output β validated & coerced against a JSON schema.
# Non-conforming output re-runs the agent with the error fed back.
output_schema: {
type: 'object',
properties: { title: { type: 'string' }, words: { type: 'integer' } },
required: ['title']
},
# Guardrail β ->(output) { [ok, value_or_error] }. On rejection the agent
# re-runs (up to guardrail_max_retries) with the reason appended.
guardrail: ->(out) { [out.length < 5000, 'must be under 5000 chars'] },
guardrail_max_retries: 3,
# Persist the result. Parent dirs are created unless create_directory: false.
output_file: 'out/report.md',
markdown: true
)
task.execute
task.structured_output # => { "title" => "...", "words" => 1234 }
task.raw_result # => the unprocessed string the agent produced
πΊοΈ Planning
Enable planning: on a crew to run a planner pass before execution. The planner
drafts a short plan for each task and folds it into the task description, giving
the executing agent a head start:
crew = RCrewAI::Crew.new('research_crew', planning: true)
# Optionally use a dedicated (e.g. stronger) planner model:
crew = RCrewAI::Crew.new('research_crew', planning: true,
planning_llm: { provider: :anthropic, model: 'claude-3-opus-20240229' })
Planning is best-effort: if the planner errors or returns unparseable output, the crew runs with the original tasks unchanged.
ποΈ Training & Testing
Iterate on a crew by training it with feedback or scoring repeated runs:
# Train: run N times, collect feedback after each run, persist to JSON.
crew.train(n_iterations: 3, filename: 'training.json')
# Provide feedback programmatically instead of prompting a human:
crew.train(n_iterations: 3, filename: 'training.json',
feedback: ->(iteration, result) { "run #{iteration}: #{result[:success_rate]}%" })
# Test: run N times and score each run (defaults to success_rate).
crew.test(n_iterations: 5)
# => { iterations: 5, scores: [...], average_score: 92.0 }
πͺ Kickoff Hooks & Batch Runs
Run setup/teardown around a crew, and batch it over many inputs:
crew.before_kickoff { |inputs| inputs.merge(started_at: Time.now) } # may transform inputs
crew.after_kickoff { |result| notify(result); result } # may transform result
crew.execute(inputs: { topic: 'ruby' })
crew.last_inputs # => the (possibly transformed) inputs the run used
# Batch: run the crew once per input set, results returned in order.
results = crew.kickoff_for_each(inputs: [
{ topic: 'ruby' },
{ topic: 'python' }
])
β±οΈ Rate Limiting
Cap an agent's LLM calls to stay under provider limits. Calls beyond the cap block until the rolling 60-second window frees up:
agent = RCrewAI::Agent.new(name: 'a', role: '...', goal: '...', max_rpm: 20)
The limiter (RCrewAI::RateLimiter) is thread-safe, so it holds under async
execution. max_rpm: nil (the default) or 0 means unlimited.
π§ Reasoning
Have an agent think through a plan before answering. The reasoning trace is
surfaced on the result and does not pollute task.result:
agent = RCrewAI::Agent.new(name: 'a', role: '...', goal: '...',
reasoning: true, max_reasoning_attempts: 3)
result = agent.execute_task(task)
result[:reasoning] # => the plan the agent drafted before answering
result[:content] # => the final answer
Off by default. If the reasoning pass keeps returning empty output past
max_reasoning_attempts, the agent proceeds without a plan.
πͺ Context Window Management
Keep long tool-use loops or large injected context from overflowing the model's context window. When enabled, the oldest non-system messages are dropped to fit before each LLM call (system messages and the latest message are always kept):
agent = RCrewAI::Agent.new(name: 'a', role: '...', goal: '...',
respect_context_window: true)
Window sizes come from RCrewAI::ContextWindow (with a conservative default for
unknown models); headroom for the response is reserved from max_tokens. Off by
default.
πΌοΈ Multimodal Input
Pass images to a vision-capable model via task attachments. Local files are base64-encoded automatically; URLs pass through:
RCrewAI.configure { |c| c.llm_provider = :openai; c.openai_model = 'gpt-4o' }
task = RCrewAI::Task.new(
name: 'describe', description: 'What is in this chart?', agent: agent,
attachments: [
{ type: :image, path: 'chart.png' },
{ type: :image, url: 'https://example.com/photo.jpg' }
]
)
Supported on OpenAI and Azure; other providers raise a clear error when attachments are present.
π Knowledge (RAG)
Ground agents in your own documents. Sources are chunked, embedded, and stored in an in-memory vector store; the most relevant chunks are injected into each task's prompt automatically.
kb = RCrewAI::Knowledge::Base.new(sources: [
RCrewAI::Knowledge::StringSource.new('Our refund window is 30 days.'),
RCrewAI::Knowledge::FileSource.new('docs/policy.txt'),
RCrewAI::Knowledge::PdfSource.new('handbook.pdf'),
RCrewAI::Knowledge::UrlSource.new('https://example.com/faq')
])
# Agent-level (role-specific) knowledge:
support = RCrewAI::Agent.new(name: 'support', role: '...', goal: '...', knowledge: kb)
# Or pass raw sources and let the agent build the base:
support = RCrewAI::Agent.new(name: 'support', role: '...', goal: '...',
knowledge_sources: [RCrewAI::Knowledge::StringSource.new('...')])
# Crew-level knowledge is shared with every agent:
crew = RCrewAI::Crew.new('support_crew', knowledge: kb)
Embeddings default to OpenAI's text-embedding-3-small. Use another provider
with RCrewAI::Knowledge::Embedder.new(provider: :ollama) (also :azure,
:google; :anthropic has no embeddings API), or pass any custom embedder:
(anything responding to embed(texts)) / vector store to swap the backend.
π§ Cognitive Memory
Agents remember what they've done and recall it semantically on future tasks. Memory is zero-config by default (in-memory, lexical recall); add an embedder for semantic recall and a SQLite store for persistence:
= RCrewAI::Knowledge::Embedder.new
store = RCrewAI::Memory::SqliteStore.new(path: '~/.rcrewai/memory.db')
agent = RCrewAI::Agent.new(
name: 'engineer', role: '...', goal: '...',
memory: { embedder: , store: store } # both optional
)
- Semantic recall β with an embedder, an agent recalls conceptually related past work even when the wording differs (falls back to word-overlap without one).
- Persistence β a
SqliteStoremakes memory survive restarts. - Memory types β
agent.memory.short_term/long_term/entity/tool. - Scoping β memory is scoped per agent so a shared store doesn't cross-read.
Memory is best-effort: embedding failures fall back to lexical similarity, so it never breaks agent execution.
π Flows
Beyond crews, RCrewAI has Flows β an event-driven workflow engine for orchestrating steps (and whole crews) with explicit branching and state:
class ArticleFlow < RCrewAI::Flow
start :outline
def outline
state.sections = %w[intro body conclusion]
state.sections.length
end
listen :outline
def draft(section_count)
state.words = section_count * 100
state.words
end
router :draft
def review(words)
words >= 250 ? :publish : :expand
end
listen :publish
def publish = state.status = 'published'
listen :expand
def = state.status = 'needs more work'
end
flow = ArticleFlow.new
flow.kickoff(inputs: { author: 'me' })
flow.state.status # => "published"
flow.state.id # => automatic UUID
start/listen/routerwire methods into a graph; a listener receives its trigger's return value.- Combine triggers with
and_(:a, :b)(all) andor_(:a, :b)(any). - State is a schemaless object with a UUID, seedable via
kickoff(inputs:). - Persistence: pass
state_store:(RCrewAI::Flow::FileStateStore.new(dir)or your own#save/#load) and callflow.restore(id)to resume. - Invoke a
Crewinside any step, or pause withhuman_feedback('Approve?').
π³οΈ Consensual Process
For decisions where multiple perspectives matter, the :consensual process has
several agents propose competing answers and vote to pick the best:
crew = RCrewAI::Crew.new('panel', process: :consensual, consensus_agents: 3)
crew.add_agent(junior)
crew.add_agent(senior)
crew.add_task(task)
crew.execute # each task: agents propose β all score 0β10 β highest wins
For every task, up to consensus_agents agents (default 3) propose a candidate
answer, all participants score each candidate, and the highest-scored candidate
becomes the result (ties break toward the task's assigned agent). A proposer that
errors is dropped; if all proposals fail the task is marked failed. Consensus
multiplies LLM calls, so consensus_agents bounds the cost on larger crews.
π‘ Examples
Hierarchical Team with Human Oversight
# Create a hierarchical crew with manager coordination
crew = RCrewAI::Crew.new("enterprise_team", process: :hierarchical)
# Manager agent coordinates the team
manager = RCrewAI::Agent.new(
name: "project_manager",
role: "Senior Project Manager",
goal: "Coordinate team execution efficiently",
manager: true,
allow_delegation: true
)
# Specialist agents with human-in-the-loop capabilities
data_analyst = RCrewAI::Agent.new(
name: "data_analyst",
role: "Senior Data Analyst",
goal: "Analyze data with human validation",
tools: [RCrewAI::Tools::SqlDatabase.new],
human_input: true, # Enable human interaction
require_approval_for_tools: true, # Human approves SQL queries
require_approval_for_final_answer: true # Human validates analysis
)
crew.add_agent(manager)
crew.add_agent(data_analyst)
# Execute with async/hierarchical coordination
results = crew.execute(async: true, max_concurrency: 2)
Async/Concurrent Execution
# Tasks that can run in parallel
research_task = RCrewAI::Task.new(
name: "market_research",
description: "Research market trends",
async: true
)
analysis_task = RCrewAI::Task.new(
name: "competitive_analysis",
description: "Analyze competitors",
async: true
)
crew.add_task(research_task)
crew.add_task(analysis_task)
# Execute with parallel processing
results = crew.execute(
async: true,
max_concurrency: 4,
timeout: 300
)
π οΈ CLI Usage
# Create a new crew
$ rcrewai new my_research_crew --process sequential
# Create agents with tools
$ rcrewai agent new researcher \
--role "Senior Research Analyst" \
--tools web_search,file_writer \
--human-input
# Create tasks with dependencies
$ rcrewai task new research \
--description "Research latest AI developments" \
--agent researcher \
--async
# Run crews
$ rcrewai run --crew my_research_crew --async
π Examples & Documentation
- Getting Started Guide: Learn the basics
- Human-in-the-Loop Example: Interactive AI workflows
- Hierarchical Teams: Manager coordination
- Async Execution: Performance optimization
- API Documentation: Complete API reference
π― Use Cases
RCrewAI excels in scenarios requiring:
- π Research & Analysis: Multi-source research with data correlation
- π Content Creation: Collaborative content development workflows
- π’ Business Intelligence: Data analysis and strategic planning
- π οΈ Development Workflows: Code analysis, testing, and documentation
- π Data Processing: ETL workflows with validation
- π€ Customer Support: Intelligent routing and response generation
- π― Decision Making: Multi-criteria analysis with human oversight
ποΈ Architecture
RCrewAI provides a flexible, production-ready architecture:
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β Crew Layer β β Human Layer β β Tool Layer β
β β β β β β
β β’ Orchestration β β β’ Approvals β β β’ Web Search β
β β’ Process Types β β β’ Guidance β β β’ File Ops β
β β’ Async Exec β β β’ Reviews β β β’ SQL Database β
β β’ Dependencies β β β’ Interventions β β β’ Email β
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β β β
ββββββββββββββββ¬ββββββββββββββββββ¬ββββββββββββββββββ
β β
βββββββββββββββββββ βββββββββββββββββββ
β Agent Layer β β LLM Layer β
β β β β
β β’ Reasoning β β β’ OpenAI β
β β’ Memory β β β’ Anthropic β
β β’ Tool Usage β β β’ Google β
β β’ Delegation β β β’ Azure β
βββββββββββββββββββ βββββββββββββββββββ
π Rails Integration
rcrew RAILS
For Rails applications, use the rcrew RAILS gem (rcrewai-rails) (repo here) which provides:
- ποΈ Rails Engine: Mountable engine with web UI for managing crews
- πΎ ActiveRecord Integration: Database persistence for agents, tasks, and executions
- β‘ Background Jobs: ActiveJob integration for async crew execution
- π― Rails Generators: Scaffolding for crews, agents, and tasks
- π Web Dashboard: Monitor and manage your AI crews through a web interface
- π§ Rails Configuration: Seamless integration with Rails configuration patterns
# Gemfile
gem 'rcrewai-rails'
# config/routes.rb
Rails.application.routes.draw do
mount RcrewAI::Rails::Engine, at: '/rcrewai'
end
# Generate a new crew
rails generate rcrew_ai:crew marketing_crew
# Create persistent agents and tasks through Rails models
crew = RcrewAI::Rails::Crew.create!(name: "Content Team", description: "AI content generation")
agent = crew.agents.create!(name: "writer", role: "Content Writer", goal: "Create engaging content")
Install rcrew RAILS: gem install rcrewai-rails
π€ Contributing
We welcome contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create a new Pull Request
π License
RCrewAI is released under the MIT License.
π Support
- Documentation: https://gkosmo.github.io/rcrewAI/
- Issues: GitHub Issues
- Discussions: GitHub Discussions
π Star History
Made with β€οΈ by the RCrewAI community