Build with RubyLLM
Use the application's installed RubyLLM version and existing conventions. This skill describes the 2.0 API. Read Gemfile.lock, or inspect the installed gem before choosing an API:
bundle exec ruby -rruby_llm -e 'puts RubyLLM::VERSION'
bundle show ruby_llm
For a 1.x application, use its version's documentation and keep the requested change on 1.x unless the user asks for an upgrade. Adding an AI feature does not require upgrading the application's framework.
Choose the API for the task
RubyLLM has two public API families: conversations use chats, messages, tools, agents, structured output, streaming, and loop control; individual operations use paint, animate, speak, transcribe, ocr, moderate, embed, and rerank. Individual operations return typed results without requiring a chat. Some stream or have an asynchronous lifecycle.
Providers supply service endpoints, authentication, catalogs, and protocol selection. Protocols translate requests and responses. Both API families use this integration layer and shared services for model selection, configuration, accounting, and instrumentation. Build against the public API and let RubyLLM handle the service formats.
Rails integration adds persistence, attachments, streaming UI support, jobs, and generators around the same Ruby API.
Find the relevant API
The installed gem's public method signatures and RDoc describe the code the application actually runs. Use them when online documentation differs. Find the matching version through RubyLLM's documentation. During the 2.0 release-candidate period, the 2.0 guides and Markdown API reference are under rubyllm.com/next/.
Read the relevant page instead of loading the entire documentation site:
| Task | Guide path under the matching documentation version |
|---|---|
| Understand the framework's structure | overview/ |
| Configure a provider or select a model | configuration/, configuration-providers/, models/ |
| Chat, stream, or attach files | chat/, streaming/, attachments/ |
| Declare tools or require approval | tools/, tool-parameters/, tool-execution/ |
| Parse structured output | structured-output/ |
| Build reusable agents | agents/, prompt-rendering/ |
| Generate images or video | image-generation/, video-generation/ |
| Generate speech or transcribe audio | text-to-speech/, audio-transcription/ |
| Extract document text or moderate content | ocr/, moderation/ |
| Embed text or rank search results | embeddings/, rerank/ |
| Persist chats, attach files, or stream with Hotwire | rails/, rails-persistence/, rails-streaming/, rails-generators/ |
| Resume agents in background jobs | durable-agents/ |
| Track spend or handle failures | cost-and-usage-tracking/, error-handling/ |
| Submit batches or drive the conversation loop | batches/, agentic-workflows/ |
| Upgrade an existing application | upgrading/ |
Markdown guides use the same name with .md, such as chat.md. The API reference starts at api/RubyLLM.md; class references include api/RubyLLM/Chat.md and api/RubyLLM/Agent.md. If fetching documentation is unavailable, inspect the installed source and identify any remaining uncertainty.
Use the 2.0 API consistently
- Configure credentials through
RubyLLM.configure, following the application's secret storage. Select an existing configured provider. Verify explicit model IDs withRubyLLM.models.find(id, provider: ...); do not invent IDs or useassume_model_existsto hide a typo. - Start with
RubyLLM.chatfor a conversation. Set options with chainablewith_*methods. UseRubyLLM::Agentwhen instructions, tools, or options should be reused. Ordinary Ruby methods and jobs compose workflows. - Use individual operations directly for media, document processing, moderation, embeddings, and reranking. Read their typed results and use
saveon generated images, video, and speech. Check each operation's provider, model, and credentials; a configured chat provider may not offer every operation.animatewaits for completion; useanimate_laterwhen the application needs to manage the job. askruns the conversation and returns a message.ask_laterstages input and returns the chat. For explicit loop control, usegenerate,run_tools,step, andcomplete?. Approval can park the loop before completion; inspectawaiting_approval?and resume afterapproveordeny.- Read text through
message.contentand structured output throughmessage.parsed. Declare schemas withSchematist::Schemaor the schema DSL. Do not assumecontentis a parsed Hash. - Subclass
RubyLLM::Tool. Usedescription,parameter, or aparametersblock, and keyword arguments onexecute. Register tools withwith_tools; configure choice and concurrency withwith_tool_options. Keep application authorization in the tool or underlying service. Userequires_approvalwhen the product needs a user's decision before execution. - Use
with_thinking,with_caching,with_compaction, andwith_citationswithout arguments to enable them andfalseto disable them. They rejectnil. Read the relevant guide for supported options and model requirements. - Use shared RubyLLM options when available. Reserve
provider_optionsfor provider-specific request fields. Do not add a second provider SDK for functionality RubyLLM already supplies. - Read tokens through
message.tokens.input,.output,.cache_read,.cache_write, and.thinking; read cost throughmessage.cost.total. Unknown cost isnil, not zero. The ledger includes individual attempts; a successful answer can include earlier failed attempts. - RubyLLM enums are Symbols:
finish_reason == :stop, thinking effort:high. Provider slugs and model IDs remain Strings.
Integrate with Rails
For a new integration, use bin/rails generate ruby_llm:install, review its migrations, and follow the application's migration workflow. Load packaged model data with bin/rails ruby_llm:load_models. RubyLLM.models.refresh performs a network refresh and persists the result.
Applications own their chat and message models, declared with acts_as_chat and acts_as_message. RubyLLM owns the supporting model, tool-call, usage, and batch tables. Do not generate application Model or ToolCall classes from 1.x examples. Pass custom chat and message mappings to the generators when the application uses different names.
Use the same chat API on persisted records. Persisted ask returns the application's message record. Use the existing job backend for background work; retrieve and configure agents through their documented persistence API when a job resumes in another process. Prompt templates live under app/prompts by convention.
Pass Active Storage attachments through with: and retain the message attachment association set up by the install generator. For a Hotwire UI, use the Rails streaming guide or ruby_llm:chat_ui generator: persisted messages provide the targets for Turbo Streams. Individual operations work directly in Rails services and jobs with the same methods as plain Ruby.
For an upgrade, read the complete matching upgrade guide before editing migrations. The 2.0 cutover requires preparation, backfill, finish, and application-specific reconciliation before affected activity resumes. Legacy-column cleanup is a later phase. Checkpoints make a stopped backfill resumable; retained columns do not make a 1.x code rollback safe. Rehearse against an isolated snapshot and respect the application's deployment and recovery process.
Verify the application change
Run the application's relevant tests. Test tool business behavior, structured parsing, persisted conversation reconstruction, and job resumption where the change depends on them. Verify model calls with the application's existing recording or integration-test setup when needed; report which provider behavior was actually exercised. Keep the implementation within the requested feature and existing application architecture.