Ruby on Rails
Because deep-reasoning LLMs hallucinate from prompt examples and mirror hostility from raw user feedback, keeping proactive agents reliable requires wrapping database-backed Rails jobs in a pipeline of smaller, faster models that filter outputs and distill user complaints into neutral facts.
AI-assisted summary of Agents on Rails: Building AI Pipelines in plain Ruby - Daniela Velasquez — original source. Check the original for full context.
Source published:
Key ideas
- Proactive AI agents can be constructed natively using standard Ruby on Rails background jobs and database models, flipping passive dashboard UX by delivering unprompted, data-backed insights directly to users. (0:11)
- Because agent research jobs often run for 10 to 30 minutes, continuous deployment resets can wipe progress; persisting LLM conversation history to the database solves statelessness and allows seamless recovery. (3:50)
- Multi-agent quality control using fast, low-cost secondary LLM judges as binary classifiers effectively filters hallucinations, tone issues, and factually impossible recommendations before they reach production. (7:48)
- Direct user feedback risks poisoning subsequent LLM prompts with mirrored hostility; deploying an intermediary extraction agent distills raw grievances into neutral operational constraints. (13:35)
Detailed notes
## Background Published on YouTube by the Ruby on Rails channel on October 1, 2026, this video features Daniela Velasquez's talk from Rails World 2026. According to the show notes, she demonstrates how to move beyond passive dashboards and chatbots by building proactive AI agents—specifically an AI running coach that analyzes workout, sleep, and heart rate data alongside external weather forecasts—using plain Ruby on Rails jobs without any extra frameworks.
## TL;DR Daniela Velasquez shows how to build a proactive AI running coach using standard Ruby on Rails background jobs, database models, and lifecycle callbacks. The pipeline starts with a slow, high-reasoning researcher job that synthesizes athlete metrics and external tools like weather forecasts, while persisting conversation history in the database to survive stateless application deployments. Because LLMs frequently hallucinate or adopt poor tones, the researcher's output is filtered through a suite of fast, smaller "judge" LLMs trained to verify facts and empathy before anything reaches the user. Finally, when athletes push back on suggestions, an extraction agent triggered via an `after_create_commit` callback strips out human frustration and saves only clean, objective constraints for future runs.
## Atmosphere & style The talk feels pragmatic, grounded, and refreshingly demystifying, stripping away AI hype in favor of familiar Rails conventions and candid developer humor. Daniela maintains a lighthearted, conversational rapport with the audience, openly poking fun at how LLMs feel like they are "trolling" developers—highlighted by a comedic real-world story about a Shopify agent suggesting "Wawa shampoo" bundles to a bra merchant and a closing reel of bizarre AI slide-generation bloopers. The emotional arc moves from the excitement of proactive automation to the humorous reality of LLM hallucinations, ultimately settling into a reassuring sense of engineering control through simple, battle-tested Ruby patterns.
## Bulletin - [00:11](https://www.youtube.com/watch?v=OX5coKfra4c&t=11s) Proactive AI agents can be constructed natively using standard Ruby on Rails background jobs and database models, flipping passive dashboard UX by delivering unprompted, data-backed insights directly to users. - [03:50](https://www.youtube.com/watch?v=OX5coKfra4c&t=230s) Because agent research jobs often run for 10 to 30 minutes, continuous deployment resets can wipe progress; persisting LLM conversation history to the database solves statelessness and allows seamless recovery. - [07:48](https://www.youtube.com/watch?v=OX5coKfra4c&t=468s) Multi-agent quality control using fast, low-cost secondary LLM judges as binary classifiers effectively filters hallucinations, tone issues, and factually impossible recommendations before they reach production. - [13:35](https://www.youtube.com/watch?v=OX5coKfra4c&t=815s) Direct user feedback risks poisoning subsequent LLM prompts with mirrored hostility; deploying an intermediary extraction agent distills raw grievances into neutral operational constraints.
## Key takeaways - [00:11](https://www.youtube.com/watch?v=OX5coKfra4c&t=11s) Applications hold vast amounts of uninspected data, and proactive AI agents flip traditional passive dashboards by initiating coaching suggestions before the user asks. - [01:39](https://www.youtube.com/watch?v=OX5coKfra4c&t=99s) The primary researcher job relies on a slow, deep-thinking model with high reasoning confidence to synthesize internal application data alongside external tools like weather and web search. - [03:50](https://www.youtube.com/watch?v=OX5coKfra4c&t=230s) Because LLM API calls are stateless and researcher runs take up to 30 minutes, continuous deployments can wipe in-flight tasks unless message histories are recorded in the database. - [05:24](https://www.youtube.com/watch?v=OX5coKfra4c&t=324s) Prompt examples can inadvertently cause hallucinations when an agent runs out of ideas, such as recommending non-existent shampoo bundles to a merchant selling bras. - [07:48](https://www.youtube.com/watch?v=OX5coKfra4c&t=468s) Secondary LLM judges provide a safety layer by serving as focused binary classifiers that evaluate candidate suggestions against narrow criteria like tone, realism, and factual correctness. - [07:48](https://www.youtube.com/watch?v=OX5coKfra4c&t=468s) Calibrating an evaluator judge requires building a benchmark dataset of balanced positive and negative examples to measure classification accuracy before deployment. - [10:06](https://www.youtube.com/watch?v=OX5coKfra4c&t=606s) Evaluator judges should run on smaller, fast, low-reasoning models to minimize token costs and latency during asynchronous parallel execution. - [10:06](https://www.youtube.com/watch?v=OX5coKfra4c&t=606s) Each evaluation job persists both its binary verdict and explanatory reasoning directly to the database, allowing invalid recommendations to be discarded cleanly. - [12:01](https://www.youtube.com/watch?v=OX5coKfra4c&t=721s) Real-world user feedback captures external constraints that telemetry data cannot detect, requiring an explicit database model to record user responses. - [13:35](https://www.youtube.com/watch?v=OX5coKfra4c&t=815s) Passing unfiltered user complaints directly into LLM prompts can poison the model's context, causing it to adopt defensive or hostile tones in future generations. - [13:35](https://www.youtube.com/watch?v=OX5coKfra4c&t=815s) An intermediary extraction agent triggered by Rails model lifecycle callbacks strips emotional rhetoric and extracts pure, factual constraints into a sanitized attribute. - [15:28](https://www.youtube.com/watch?v=OX5coKfra4c&t=928s) Long-term agent memory requires background maintenance and auditing—termed a dreaming phase—to prune obsolete user constraints as real-world schedules evolve. - [15:28](https://www.youtube.com/watch?v=OX5coKfra4c&t=928s) The complete proactive pipeline forms an architectural loop: generation via researcher jobs, verification via judge jobs, delivery to users, and asynchronous feedback sanitization.
## Detailed walkthrough ### [00:11](https://www.youtube.com/watch?v=OX5coKfra4c&t=11s) The Why and How of Proactive AI Agents in Rails
Daniela Velasquez kicks off her talk by asking how we can put "agents on rails" using plain Ruby on Rails without needing extra frameworks. Exploring the motivation behind the idea, she notes that applications hold immense amounts of data with fascinating insights, but nobody has the time to sit and sift through it all. Traditional solutions like dashboards or chatbots still wait passively for users to ask questions. Daniela proposes flipping the dynamic so that applications go to the users proactively, "because sometimes you don't know what you don't know." To ground the talk, she introduces an example application tracking an athlete's workouts, sleep logs, and heart rates to coach them before they even ask.
- Plain Ruby on Rails can build proactive AI pipelines without heavy external frameworks. - The example application tracks athlete workouts, sleep logs, and heart rates to deliver proactive coaching.
```mermaid flowchart TD subgraph Problem["Traditional Approach"] A["App Data"] --> B["Dashboards & Chatbots"] B --> C["Wait for User Questions"] end subgraph Solution["Proactive Rails Agent"] D["Athlete Data & Context"] --> E["Researcher Job"] E --> F["Proactive Coaching Insights"] end style Problem fill:#f9f,stroke:#333,stroke-width:2px style Solution fill:#bbf,stroke:#333,stroke-width:2px accTitle: Proactive AI Agents versus Traditional Dashboards accDescr: A flowchart comparing passive dashboards with proactive Rails agent pipelines. ```
[01:39](https://www.youtube.com/watch?v=OX5coKfra4c&t=99s) Building the Basic Researcher Job and Prompt
The implementation starts with a simple Rails job called a researcher job. The heart of the LLM is the prompt, which in this case establishes the agent's persona: "You're a running coach. Study this athlete's workout, sleep, and heart rate, then propose concrete changes to the training for next week. Back every change with data you actually look at." Developers can choose any LLM provider they want and can afford, passing the prompt directly to them. Alongside the internal app data like workout history and sleep logs, the agent is given external tools such as weather forecasts and web search so it can look at the world around the athlete. Daniela describes the model as "basically the brain you're trying to rent," noting that you need a slow, deep-thinking model with high reasoning confidence rather than a fast one.
- The researcher job begins with a core prompt establishing the running coach persona. - Tools include internal data (workout history, sleep logs) and external data (weather forecasts, web search). - The setup requires a larger, slower model with high reasoning settings rather than a fast one.
[03:50](https://www.youtube.com/watch?v=OX5coKfra4c&t=230s) Fixing Stateless Deployments with Conversation Tracking
Running these researcher jobs takes time—anywhere from 10, 15, or 30 minutes depending on the tools and prompt complexity. However, continuous deployment poses a major challenge because when a deploy happens, the agent living inside a job resets to zero. Because LLM provider calls are stateless, they lose all memory of what was happening, wasting both time and money and frustrating bosses. To fix this, Daniela introduces a `past_conversation` record to track messages exchanged with LLM providers. If the conversation has no messages, the job stores the system prompt and a user message kicking off the research. It then enters a loop, passing the full message history to the LLM provider on every turn and saving incoming responses so the job can seamlessly recover if it restarts.
- LLM calls are stateless, meaning deployments wipe out agent progress and waste resources. - Tracking conversation history in the database allows jobs to restart and remember past back-and-forth messages.
[05:24](https://www.youtube.com/watch?v=OX5coKfra4c&t=324s) Agent Coaching Suggestions and the Trust Problem
Walking through a hypothetical output, Daniela shares what the agent might suggest: shifting Tuesday runs to start an hour later, adding two 45-minute bike rides to build an aerobic base, easing up on the first kilometers of long runs to prevent fading, and moving the Saturday long run to Sunday morning due to heavy rain. While this seems great, Daniela points out the harsh reality: "It's hard to trust them. They sometimes come up with very random ways of doing... very creative ways of not the right thing that you asked them to do. And honestly half the time I feel like they're just trolling you for what you're asking them to do." She shares a hilarious anecdote from Shopify where the researcher agent repeatedly suggested that merchants "bundle your Wawa shampoo and Wawa conditioner because they're usually bought together." After seeing it multiple times, she checked the merchant's store and discovered they were selling bras! The hallucination happened because "Wawa shampoo and conditioner" was buried as an example in the prompt, and the agent grabbed it whenever it ran out of ideas.
- The agent successfully synthesizes internal workout logs with external weather forecasts. - At Shopify, a researcher agent hallucinated non-existent "Wawa shampoo and conditioner" bundles for a merchant selling bras because the items were listed as examples in the prompt.
[07:48](https://www.youtube.com/watch?v=OX5coKfra4c&t=468s) Deploying LLM Judges to Keep Agents on Rails
To solve the trust problem and prevent agents from falling off the rails, Daniela humorously suggests throwing more LLMs at the problem—specifically, using secondary LLMs to act as judges. These judge LLMs have a much simpler job: acting as focused classifiers answering specific binary questions important to the application, such as catching made-up numbers, checking tone, or running reality checks on whether an athlete can actually execute a suggestion. To train the "kind judge," developers compile around 200 examples of kind suggestions and 200 examples of unkind ones. For instance, swapping an easy run for a chill session when dealing with hip pain is "kind," whereas telling someone running seven days a week to "stop before you break yourself" might not be super kind. Similarly, telling an athlete their knees hurt because they ran 900 km in the same shoes is realistic but perhaps a bit blunt, while suggesting they grab a snack at the 45-minute mark because their pace drops after 60 minutes is helpful and kind.
- Secondary LLM judges act as focused classifiers to evaluate and filter researcher output. - Training the kind judge involves curating 200 positive and 200 negative examples covering tone, empathy, and realism.
[10:06](https://www.youtube.com/watch?v=OX5coKfra4c&t=606s) Evaluating Prompts and Running LLM Judges
Daniela outlines the evaluation criteria for the "kind judge" prompt: *"Would a supportive coach say this? Blame, sarcasm, or threats fail. Honest data delivered kindly passes. Reply with pass or fail and why."* Once this prompt is written, it is benchmarked against an existing evaluation dataset to measure accuracy. This setup allows developers to freely iterate on prompt variations and benchmark different language models against each other to discover which one strikes the right balance between cost and performance.
Because these evaluator judges serve narrow, specialized roles, they do not require expensive flagship models with deep reasoning capabilities. Instead, smaller and significantly faster models keep background job execution cheap and snappy. As soon as the researcher finishes generating coaching suggestions, the pipeline moves to its second phase: dispatching a suite of focused judges across each individual suggestion. To evaluate kindness, Rails invokes an LLM provider client, passes the system instructions alongside the candidate suggestion text, sets the reasoning parameters low, and records the resulting pass/fail verdict and reasoning directly to the database.
Applying these checks to real-world researcher output quickly exposes problematic recommendations. For instance, when the researcher tells an athlete they just had their *"worst sleep"*, the kind judge flags it for lacking empathy. When another job proposes an outdoor ride, the fact-checking judge looks up equipment records, notes that *"they don't own a bike, so they cannot do this"*, and fails it immediately. As a result, out of four original coaching actions generated by the researcher, two are immediately disqualified—one for failing the tone test and the other for proposing an impossible activity.
- Evaluator prompt instructions: test whether a supportive coach would say the line; reject blame, sarcasm, or hostility; pass honest data communicated kindly. - Smaller models with minimal reasoning effort provide the speed and low token cost necessary for parallel evaluation jobs. - Each evaluation job persists its verdict (`pass` or `fail`) and underlying explanation alongside the suggestion record.
```mermaid flowchart TD accTitle: Evaluator Judge Pipeline accDescr: Pipeline showing researcher suggestions passing through specialized judges to filter the output.
subgraph Generation ["1. Researcher Agent"] R["Researcher Job"] --> S1["Suggestion 1: Sleep Notice"] R --> S2["Suggestion 2: Bike Ride"] R --> S3["Suggestion 3: Easy Jog"] R --> S4["Suggestion 4: Hydration Goal"] end
subgraph Evaluation ["2. Specialized Judges"] KJ["Kind Judge"] FJ["Fact-Checking Judge"] S1 -.->|"Evaluated by"| KJ S2 -.->|"Evaluated by"| FJ end
subgraph Results ["3. Athlete Delivery"] S1 -->|"Fail: Harsh tone"| REJ1["Discarded"] S2 -->|"Fail: No bike owned"| REJ2["Discarded"] S3 -->|"Pass"| OUT["Athlete Dashboard"] S4 -->|"Pass"| OUT end ```
---
[12:01](https://www.youtube.com/watch?v=OX5coKfra4c&t=721s) Filtering Pipeline Recap and Handling User Feedback
Recapping the flow up to this point, Daniela explains how an athlete's incoming metrics feed directly into a researcher agent running in a background job, which derives personalized workout recommendations. That batch triggers a secondary wave of asynchronous Rails jobs, running every suggestion through the specific domain judges that matter to the application. Each judge issues an independent thumbs-up or thumbs-down based on its assigned metric. Ultimately, the athlete sees only the vetted, high-confidence subset of suggestions that passed every single gate.
``` +-----------------------------------------------------------------------+ | Athlete Metrics & History (Sleep, Workouts, HR) | +-----------------------------------------------------------------------+ │ ▼ +-----------------------------------------------------------------------+ | Researcher Job: Proposes Candidate Suggestions | +-----------------------------------------------------------------------+ │ │ │ ▼ ▼ ▼ +-----------------+ +-----------------+ +-----------------+ | Kind Judge Job | | Fact Judge Job | | Custom App Job | | (Tone check) | | (Equipment/Log) | | (Safety check) | +-----------------+ +-----------------+ +-----------------+ │ │ │ └───────────────────────┼──────────────────────┘ ▼ +-----------------------------------------------------------------------+ | Approved Recommendations Displayed on Dashboard | +-----------------------------------------------------------------------+ ```
However, real-world users inevitably push back—especially once they realize recommendations are generated by an AI. An athlete might reply with personal schedule constraints that were never logged in their wearable data, such as: *"I work on Sundays from 6:00 a.m. to 3:00 p.m."* No matter how many external API tools or database integrations the agent started with, this context simply did not exist anywhere in the app. To prevent future pipelines from making the same mistake, the researcher needs a way to persist and recall user feedback.
Persisting this feedback begins with standard Rails architecture: an `AthleteFeedback` model inheriting from `ApplicationRecord` that `belongs_to:athlete` and `belongs_to:suggestion`. When the researcher job runs in subsequent iterations, it loads this historical feedback and injects it into its prompt context so the model learns from past interactions.
---
[13:35](https://www.youtube.com/watch?v=OX5coKfra4c&t=815s) Sanitizing Frustrations with an Extraction Agent
Feeding raw user text directly into subsequent agent prompts introduces serious risks. Because large language models thrive on matching tone and patterns, unvarnished human feedback can poison the pipeline. While an athlete might start out polite, repeated mismatches often lead to irritation and outright name-calling. If an angry user vents at an agent, passing that hostility directly into the researcher prompt risks having the agent *"pick up on the bad vibes"* and generate hostile or defensive suggestions in return. While downstream kind judges would catch those suggestions, wasting compute and token budget generating angry responses is completely counterproductive.
Daniela proposes solving the issue with another specialized agent: *"Another agent. So, you're going to pass that raw user feedback and give it to an agent that is just going to take all that noise. And you just want the fact."* Regardless of the emotional outburst, profanity, or sarcasm in the athlete's input, the extraction agent strips the noise down to the essential operational constraint: the athlete is unavailable to train between 6:00 a.m. and 3:00 p.m. on Sundays.
To implement this, Daniela hooks into the feedback model lifecycle using an `after_create_commit` callback. Acknowledging the perennial Rails community debate around callbacks—*"I know callbacks are not really loved by a lot of people, but I love callbacks"*—she shows how the callback enqueues a background processing job. This job instructs a small, low-reasoning LLM to review the rejected training suggestion, discard the emotional rhetoric, and output a single clean sentence summarizing what the coach must remember to prevent a recurrence. The distilled output is saved into a `processed_text` database column, which is the only version later exposed to the primary researcher agent.
- Feeding raw user complaints into LLM prompts can lead models to mirror the user's frustration or negative tone. - An intermediary extraction agent distills user vent sessions into clean, objective facts. - Rails lifecycle callbacks enqueue the background sanitization job immediately after feedback is recorded. - The primary researcher job ingests sanitized `processed_text` attributes rather than unedited user messages.
---
[15:28](https://www.youtube.com/watch?v=OX5coKfra4c&t=928s) Long-Term Memory Challenges, Final Recap, and AI Art Bloopers
Looking ahead, Daniela addresses an architectural frontier in agent design: long-term memory maintenance and fact obsolescence. Real-world facts change over time—athletes change jobs, work shifts shift, or schedules open up. If the agent permanently stores a rigid constraint that the athlete cannot train on Sunday mornings, it will eventually generate suboptimal plans when circumstances shift. This introduces what she refers to as the *"dreaming"* phase of AI systems, where background routines periodically audit, consolidate, and prune accumulated memory records to ensure stored facts remain accurate over months and years.
Daniela closes her talk by summarizing the complete architectural loop: 1. A **researcher job** analyzes athlete data to draft prospective workouts. 2. Independent **evaluator jobs** vet those suggestions against application quality gates. 3. Clean recommendations surface in the user interface. 4. Athletes submit corrections and **feedback**, which is asynchronously distilled into neutral facts and fed back into future researcher runs.
To wrap up, Daniela shares several humorous behind-the-scenes failures from generating her presentation slides with image generation models. She displays an uncanny, scary AI illustration that went off the rails, a slide where requesting images of "agents" resulted in the model drawing armed law enforcement officers and detectives, and another image where the model stubbornly refused repeated instructions to remove an imposing background character. She invites attendees to find her after the session to pick up custom illustrated sticker designs of the "little agents" featured throughout the talk.
## Notable quotes > [00:11](https://www.youtube.com/watch?v=OX5coKfra4c&t=11s) because sometimes you don't know what you don't know. — Daniela Velasquez
> [01:39](https://www.youtube.com/watch?v=OX5coKfra4c&t=99s) You're a running coach. Study this athlete's workout, sleep, and heart rate, then propose concrete changes to the training for next week. Back every change with data you actually look at. — Daniela Velasquez
> [01:39](https://www.youtube.com/watch?v=OX5coKfra4c&t=99s) basically the brain you're trying to rent — Daniela Velasquez
> [05:24](https://www.youtube.com/watch?v=OX5coKfra4c&t=324s) It's hard to trust them. They sometimes come up with very random ways of doing... very creative ways of not the right thing that you asked them to do. And honestly half the time I feel like they're just trolling you for what you're asking them to do. — Daniela Velasquez
> [05:24](https://www.youtube.com/watch?v=OX5coKfra4c&t=324s) bundle your Wawa shampoo and Wawa conditioner because they're usually bought together. — Daniela Velasquez
> [10:06](https://www.youtube.com/watch?v=OX5coKfra4c&t=606s) Would a supportive coach say this? Blame, sarcasm, or threats fail. Honest data delivered kindly passes. Reply with pass or fail and why. — Daniela Velasquez
> [10:06](https://www.youtube.com/watch?v=OX5coKfra4c&t=606s) worst sleep — Daniela Velasquez
> [10:06](https://www.youtube.com/watch?v=OX5coKfra4c&t=606s) they don't own a bike, so they cannot do this — Daniela Velasquez
> [12:01](https://www.youtube.com/watch?v=OX5coKfra4c&t=721s) I work on Sundays from 6:00 a.m. to 3:00 p.m. — Daniela Velasquez
> [13:35](https://www.youtube.com/watch?v=OX5coKfra4c&t=815s) pick up on the bad vibes — Daniela Velasquez
> [13:35](https://www.youtube.com/watch?v=OX5coKfra4c&t=815s) Another agent. So, you're going to pass that raw user feedback and give it to an agent that is just going to take all that noise. And you just want the fact. — Daniela Velasquez
> [13:35](https://www.youtube.com/watch?v=OX5coKfra4c&t=815s) I know callbacks are not really loved by a lot of people, but I love callbacks — Daniela Velasquez
> [15:28](https://www.youtube.com/watch?v=OX5coKfra4c&t=928s) dreaming — Daniela Velasquez
## Mentioned Daniela Velasquez, Ruby on Rails, Rails World 2026, Shopify, ApplicationRecord, Wawa
## Video description Most apps hold far more insight in their data than anyone has time to find. Dashboards and chatbots still wait for users to come ask. At Rails World 2026, Daniela Velasquez shows how to flip that around by building proactive AI agents in plain Rails, with no extra framework needed.
Daniela uses an example app that tracks an athlete's workouts, sleep, and heart rate. She builds an AI running coach that suggests training changes before the athlete asks. Everything starts with a simple Rails job. From there she adds a prompt, an LLM provider of your choice, and a set of tools the agent can decide to use, from in-app data like workout history and sleep logs to outside sources like weather forecasts and web search.
*** Thank you Shopify for sponsoring the editing and post-production of these videos. Check out insights from the Engineering team at: https://shopify.engineering/
#RailsWorld #RubyOnRails #AI #AIAgents #LLM #Ruby
[Source](https://www.youtube.com/watch?v=OX5coKfra4c)