Building an AI agent inside a 7-year old Rails application

2026-05-14 · source · source ↗

Catalin Ionescu, Director of Engineering at Mon Ami (US-based startup building SaaS for Aging and Disability Case Workers), describes integrating an AI agent into a mature, multi-tenant Rails monolith with strict data access controls.

Context

The Insight

At SF Ruby, a talk on RubyLLM's tool/function-calling approach made it click: encode authorization logic into specific function calls, giving the LLM data access "without having to give it unrestricted access."

RubyLLM Setup

RubyLLM.configure do |config|
  config.openai_api_key = Rails.application.credentials.dig(:openai_api_key)
  config.anthropic_api_key = Rails.application.credentials.dig(:anthropic_api_key)
  config.use_new_acts_as = true
  config.request_timeout = 600
  config.max_retries = 3
end

Dir[Rails.root.join('app/tools/**/*.rb')].each { |f| require f }

Tool Definition Pattern

RubyLLM provides a DSL for defining tools with descriptions and typed parameters. The SearchTool: 1. Queries Algolia's search index with the user's natural language input 2. Retrieves matching record IDs from search hits 3. Passes results through a Pundit policy scope to enforce tenant/authorization boundaries 4. Returns only permitted data as a hash back to the LLM

"no model should ever know" a given user's private data from a SaaS service.

Conversation & UI Architecture

Model Selection

Key Takeaways (author's own)