<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Miles Georgi</title>
    <description>The latest articles on DEV Community by Miles Georgi (@foobara).</description>
    <link>https://dev.to/foobara</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3365566%2F8ca2b83c-2e33-4493-bd55-06743412b88c.jpg</url>
      <title>DEV Community: Miles Georgi</title>
      <link>https://dev.to/foobara</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/foobara"/>
    <language>en</language>
    <item>
      <title>Writing an AI Agent in 1 Line of Ruby Code Using Foobara's AgentBackedCommand</title>
      <dc:creator>Miles Georgi</dc:creator>
      <pubDate>Fri, 18 Jul 2025 03:19:06 +0000</pubDate>
      <link>https://dev.to/foobara/writing-an-ai-agent-in-1-line-of-ruby-code-using-foobaras-agentbackedcommand-m6p</link>
      <guid>https://dev.to/foobara/writing-an-ai-agent-in-1-line-of-ruby-code-using-foobaras-agentbackedcommand-m6p</guid>
      <description>&lt;h2&gt;
  
  
  Writing an AI Agent in 1 Line of Ruby Code Using Foobara's AgentBackedCommand
&lt;/h2&gt;

&lt;p&gt;In this article, we'll introduce/demo &lt;code&gt;Foobara::AgentBackedCommand&lt;/code&gt; by adding it to a program with an existing Foobara domain in it. Let's do it!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is Foobara?&lt;/li&gt;
&lt;li&gt;The Demo Loan Origination Domain and Demo Records&lt;/li&gt;
&lt;li&gt;Defining and Running a Foobara::AgentBackedCommand&lt;/li&gt;
&lt;li&gt;A More Complex and Interesting Example&lt;/li&gt;
&lt;li&gt;Specifying an Inputs Type for an AgentBackedCommand&lt;/li&gt;
&lt;li&gt;Specifying and Using AgentBackedCommand Results Programmatically!&lt;/li&gt;
&lt;li&gt;An Interesting Takeaway&lt;/li&gt;
&lt;li&gt;Links&lt;/li&gt;
&lt;li&gt;Please Reach Out!&lt;/li&gt;
&lt;li&gt;Disclaimers&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What is Foobara?
&lt;/h3&gt;

&lt;p&gt;Foobara is a command-centric and discoverable software framework that helps manage domain complexity by abstracting away integration code and other features.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Demo Loan Origination Domain and Demo Records
&lt;/h3&gt;

&lt;p&gt;First, we need a program to add it to. Here is a program that uses a demo loan origination domain written using Foobara. You can find the demo domain implementation here: &lt;a href="https://github.com/foobara-demo/loan-origination/tree/main/src" rel="noopener noreferrer"&gt;https://github.com/foobara-demo/loan-origination/tree/main/src&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's our program in an executable file called &lt;code&gt;loan-origination&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env ruby&lt;/span&gt;

&lt;span class="nb"&gt;require_relative&lt;/span&gt; &lt;span class="s2"&gt;"boot"&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"foobara/sh_cli_connector"&lt;/span&gt;

&lt;span class="n"&gt;connector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Foobara&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;CommandConnectors&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ShCliConnector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;connector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;FoobaraDemo&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;LoanOrigination&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;connector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This uses a Foobara CLI command connector so that we can run commands from &lt;code&gt;LoanOrigination&lt;/code&gt; on the command line.&lt;/p&gt;

&lt;p&gt;Let's see what commands are available:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ./loan-origination 
Usage: loan-origination [GLOBAL_OPTIONS] [ACTION] [COMMAND_OR_TYPE] [COMMAND_INPUTS]
...
Available commands:
  FoobaraDemo::LoanOrigination::SubmitApplicationForUnderwriterReview
  FoobaraDemo::LoanOrigination::FindALoanFileThatNeedsReview            Will return a loan file
                                                                        that needs review or nil
                                                                        if there are no loan 
                                                                        files that need review
  FoobaraDemo::LoanOrigination::FindAllLoanFiles
  FoobaraDemo::LoanOrigination::GenerateLoanFilesReport
  FoobaraDemo::LoanOrigination::StartUnderwriterReview
  FoobaraDemo::LoanOrigination::StartLoanApplication
  FoobaraDemo::LoanOrigination::CreateCreditPolicy
  FoobaraDemo::LoanOrigination::FindCreditPolicy
  FoobaraDemo::LoanOrigination::ApproveLoanFile
  FoobaraDemo::LoanOrigination::AddCreditScore
  FoobaraDemo::LoanOrigination::FindLoanFile
  FoobaraDemo::LoanOrigination::DenyLoanFile
  FoobaraDemo::LoanOrigination::AddPayStub                              Add a pay stub to a loan
                                                                        file
  FoobaraDemo::LoanOrigination::Demo::PrepareDemoRecords
$ 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see a ton of commands at our disposal. Let's run &lt;code&gt;GenerateLoanFilesReport&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ./loan-origination GenerateLoanFilesReport
$ 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We get nothing back. Which makes sense! Let's create some records to play with using &lt;code&gt;PrepareDemoRecords&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ./loan-origination PrepareDemoRecords
...
$ 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prints out a bunch of loan file data that is excluded. Now let's look at our report again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ./loan-origination GenerateLoanFilesReport
{
  id: 1,
  applicant: "Barbara",
  state: "needs_review"
},
{
  id: 2,
  applicant: "Basil",
  state: "needs_review"
},
{
  id: 3,
  applicant: "Fumiko",
  state: "needs_review"
}
$ 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command creates 3 loan files ready for review that are all on different credit policies. We expect these loan files to be denied or approved for different reasons. See &lt;code&gt;PrepareDemoRecords&lt;/code&gt; for details on the demo records and the expected results of reviewing these loan files.&lt;/p&gt;

&lt;p&gt;Now, we could review these loan files ourselves using &lt;code&gt;loan-origination&lt;/code&gt; since it exposes all the commands that we need. We could do the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ./loan-origination FindALoanFileThatNeedsReview
...
id: 1
$ 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could then do &lt;code&gt;./loan-origination StartUnderwriterReview --loan-file 1&lt;/code&gt; which would start our review.&lt;/p&gt;

&lt;p&gt;We would then need to do &lt;code&gt;./loan-origination FindCreditPolicy --credit-policy 1&lt;/code&gt; and finally we could run &lt;code&gt;./loan-origination DenyLoanFile --loan-file 1 --credit-score-used 650 --denied-reasons low_credit_score&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We could then move on to the next loan file until no more need review.&lt;/p&gt;

&lt;p&gt;In this case, we're a human operating the domain, which we've chosen in this case to expose through a CLI.&lt;/p&gt;

&lt;p&gt;If we had an AI agent that also knew how to operate our domain, we could say something like: "Hi! Could you please review every loan file that needs review? Thanks!"&lt;/p&gt;

&lt;p&gt;Notice that what we would be doing is issuing a high-level domain operation to our AI agent. Since Foobara commands are meant to encapsulate high-level domain operations, it would be nice if we could just have a &lt;code&gt;ReviewAllLoanFiles&lt;/code&gt; Foobara command but without having to write its #execute method (ie, the domain logic itself.)&lt;/p&gt;

&lt;h3&gt;
  
  
  Defining and Running a Foobara::AgentBackedCommand
&lt;/h3&gt;

&lt;p&gt;Now it's finally time to write our AI agent in 1 line of Ruby code, introducing &lt;code&gt;Foobara::AgentBackedCommand&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env ruby&lt;/span&gt;

&lt;span class="nb"&gt;require_relative&lt;/span&gt; &lt;span class="s2"&gt;"boot"&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"foobara/sh_cli_connector"&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FoobaraDemo::LoanOrigination::ReviewAllLoanFiles&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Foobara&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;AgentBackedCommand&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;connector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Foobara&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;CommandConnectors&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ShCliConnector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;connector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;FoobaraDemo&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;LoanOrigination&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;connector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we're done! We've created a command called &lt;code&gt;ReviewAllLoanFiles&lt;/code&gt; which is an &lt;code&gt;AgentBackedCommand&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can now see it in our &lt;code&gt;loan-origination --help&lt;/code&gt; output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ./loan-origination --help
...
Available commands:

  FoobaraDemo::LoanOrigination::SubmitApplicationForUnderwriterReview
  FoobaraDemo::LoanOrigination::FindALoanFileThatNeedsReview            Will return a loan file
                                                                        that needs review or nil if
                                                                        there are no loan files
                                                                        that need review
  FoobaraDemo::LoanOrigination::FindAllLoanFiles
  FoobaraDemo::LoanOrigination::GenerateLoanFilesReport
  FoobaraDemo::LoanOrigination::StartUnderwriterReview
  FoobaraDemo::LoanOrigination::StartLoanApplication
  FoobaraDemo::LoanOrigination::CreateCreditPolicy
  FoobaraDemo::LoanOrigination::FindCreditPolicy
  FoobaraDemo::LoanOrigination::ApproveLoanFile
  FoobaraDemo::LoanOrigination::AddCreditScore
  FoobaraDemo::LoanOrigination::FindLoanFile
  FoobaraDemo::LoanOrigination::DenyLoanFile
  FoobaraDemo::LoanOrigination::AddPayStub                              Add a pay stub to a loan
                                                                        file
  FoobaraDemo::LoanOrigination::Demo::PrepareDemoRecords
  FoobaraDemo::LoanOrigination::ReviewAllLoanFiles
...
$ 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see it there at the bottom. Let's see what inputs it has:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ./loan-origination --help ReviewAllLoanFiles
...
Command inputs:

 -v, --agent-options-verbose
...
 -a, --agent-name AGENT_NAME
 -l, --llm-model LLM_MODEL                             The model to use for the
  LLM. One of: chatgpt-4o-latest, claude-2.0, claude-2.1, 
  ...
  claude-3-5-sonnet-20241022, claude-3-7-sonnet-20250219, 
  ...
  claude-opus-4-20250514, claude-sonnet-4-20250514, gpt-3.5-turbo,
  ... 
  gpt-4o, gpt-4o-2024-05-13, gpt-4o-2024-08-06, gpt-4o-2024-11-20,
  ...
  Default: claude-3-7-sonnet-20250219
...
$ 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I've snipped many options as well as a ton of models out of the &lt;code&gt;--llm-model&lt;/code&gt; option. I won't make use of the &lt;code&gt;--llm-model&lt;/code&gt; option here but it supports ollama, openai, and anthropic models. It defaults to claude-3-7-sonnet-20250219.&lt;/p&gt;

&lt;p&gt;I will make use of &lt;code&gt;--agent-options-verbose&lt;/code&gt; so we can see what decisions it makes, as well as &lt;code&gt;--agent-name&lt;/code&gt;, though. So... let's review these loan files!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ./loan-origination ReviewAllLoanFiles --agent-options-verbose --agent-name UnderwritingAgent
UnderwritingAgent: Foobara::Agent::DescribeCommand.run(command_name: "Foobara::Agent::ListCommands")
UnderwritingAgent: Foobara::Agent::ListCommands.run
UnderwritingAgent: Foobara::Agent::DescribeCommand.run(command_name: "FoobaraDemo::LoanOrigination::FindAllLoanFiles")
UnderwritingAgent: FoobaraDemo::LoanOrigination::FindAllLoanFiles.run
UnderwritingAgent: Foobara::Agent::DescribeCommand.run(command_name: "FoobaraDemo::LoanOrigination::StartUnderwriterReview")
UnderwritingAgent: Foobara::Agent::DescribeCommand.run(command_name: "FoobaraDemo::LoanOrigination::FindCreditPolicy")
UnderwritingAgent: FoobaraDemo::LoanOrigination::StartUnderwriterReview.run(loan_file: 1)
UnderwritingAgent: Foobara::Agent::DescribeCommand.run(command_name: "FoobaraDemo::LoanOrigination::FindLoanFile")
UnderwritingAgent: FoobaraDemo::LoanOrigination::FindLoanFile.run(loan_file: 1)
UnderwritingAgent: FoobaraDemo::LoanOrigination::FindCreditPolicy.run(credit_policy: 1)
UnderwritingAgent: Foobara::Agent::DescribeCommand.run(command_name: "FoobaraDemo::LoanOrigination::ApproveLoanFile")
UnderwritingAgent: Foobara::Agent::DescribeCommand.run(command_name: "FoobaraDemo::LoanOrigination::DenyLoanFile")
UnderwritingAgent: FoobaraDemo::LoanOrigination::DenyLoanFile.run(loan_file: 1, credit_score_used: 650, denied_reasons: ["low_credit_score"])
UnderwritingAgent: FoobaraDemo::LoanOrigination::StartUnderwriterReview.run(loan_file: 2)
UnderwritingAgent: FoobaraDemo::LoanOrigination::FindLoanFile.run(loan_file: 2)
UnderwritingAgent: FoobaraDemo::LoanOrigination::FindCreditPolicy.run(credit_policy: 2)
UnderwritingAgent: FoobaraDemo::LoanOrigination::DenyLoanFile.run(loan_file: 2, credit_score_used: 750, denied_reasons: ["insufficient_pay_stubs_provided"])
UnderwritingAgent: FoobaraDemo::LoanOrigination::StartUnderwriterReview.run(loan_file: 3)
UnderwritingAgent: FoobaraDemo::LoanOrigination::FindLoanFile.run(loan_file: 3)
UnderwritingAgent: FoobaraDemo::LoanOrigination::FindCreditPolicy.run(credit_policy: 3)
UnderwritingAgent: FoobaraDemo::LoanOrigination::ApproveLoanFile.run(loan_file: 3, credit_score_used: 750)
UnderwritingAgent: FoobaraDemo::LoanOrigination::FindAllLoanFiles.run
UnderwritingAgent: Foobara::Agent::NotifyUserThatCurrentGoalHasBeenAccomplished.run
$ 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we can see all the decisions it made. Let's look at the report now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ./loan-origination GenerateLoanFilesReport
{
  id: 1,
  applicant: "Barbara",
  state: "denied",
  underwriter_decision: {
    decision: :denied,
    credit_score_used: 650,
    denied_reasons: [
      :low_credit_score
    ]
  }
},
{
  id: 2,
  applicant: "Basil",
  state: "denied",
  underwriter_decision: {
    decision: :denied,
    credit_score_used: 750,
    denied_reasons: [
      :insufficient_pay_stubs_provided
    ]
  }
},
{
  id: 3,
  applicant: "Fumiko",
  state: "drafting_docs",
  underwriter_decision: {
    decision: :approved,
    credit_score_used: 750
  }
}
$ 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looks great! It used the correct credit scores for the different loan files, made the correct approved/denied decisions and chose the proper denied reason for the different denied loan files.&lt;/p&gt;

&lt;h3&gt;
  
  
  A More Complex and Interesting Example
&lt;/h3&gt;

&lt;p&gt;Adding an agent to a program with one line of Ruby code might be fun clickbait and all, but let's look at an example that highlights some features of &lt;code&gt;AgentBackedCommand&lt;/code&gt; that are not demonstrated in the one-liner example above. Check this out, in a new executable called &lt;code&gt;review-all-loan-files&lt;/code&gt; we have written:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env ruby&lt;/span&gt;

&lt;span class="nb"&gt;require_relative&lt;/span&gt; &lt;span class="s2"&gt;"boot"&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;FoobaraDemo&lt;/span&gt;
  &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;LoanOrigination&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UnderwriterSummary&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Foobara&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Model&lt;/span&gt;
      &lt;span class="n"&gt;attributes&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;loan_file_id&lt;/span&gt; &lt;span class="ss"&gt;:integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:required&lt;/span&gt;
        &lt;span class="n"&gt;pay_stub_count&lt;/span&gt; &lt;span class="ss"&gt;:integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:required&lt;/span&gt;
        &lt;span class="n"&gt;fico_scores&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:integer&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;:required&lt;/span&gt;
        &lt;span class="n"&gt;credit_policy&lt;/span&gt; &lt;span class="no"&gt;CreditPolicy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:required&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ReviewLoanFile&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Foobara&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;AgentBackedCommand&lt;/span&gt;
      &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="s2"&gt;"Starts the underwriter review then checks requirements in its CreditPolicy "&lt;/span&gt; &lt;span class="p"&gt;\&lt;/span&gt;
                  &lt;span class="s2"&gt;"and approves or denies accordingly."&lt;/span&gt;

      &lt;span class="n"&gt;inputs&lt;/span&gt; &lt;span class="no"&gt;UnderwriterSummary&lt;/span&gt;
      &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="no"&gt;LoanFile&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;UnderwriterDecision&lt;/span&gt;

      &lt;span class="n"&gt;depends_on&lt;/span&gt; &lt;span class="no"&gt;StartUnderwriterReview&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;DenyLoanFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ApproveLoanFile&lt;/span&gt;

      &lt;span class="n"&gt;verbose&lt;/span&gt;
      &lt;span class="n"&gt;llm_model&lt;/span&gt; &lt;span class="s2"&gt;"claude-3-7-sonnet-20250219"&lt;/span&gt;
      &lt;span class="n"&gt;agent_name&lt;/span&gt; &lt;span class="s2"&gt;"Inner"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ReviewAllLoanFiles&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Foobara&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;AgentBackedCommand&lt;/span&gt;
      &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
                &lt;span class="ss"&gt;applicant_name: :string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="ss"&gt;decision: &lt;/span&gt;&lt;span class="no"&gt;LoanFile&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;UnderwriterDecision&lt;/span&gt;
              &lt;span class="p"&gt;}]&lt;/span&gt;

      &lt;span class="n"&gt;depends_on&lt;/span&gt; &lt;span class="no"&gt;ReviewLoanFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;FindALoanFileThatNeedsReview&lt;/span&gt;

      &lt;span class="n"&gt;verbose&lt;/span&gt;
      &lt;span class="n"&gt;llm_model&lt;/span&gt; &lt;span class="s2"&gt;"gpt-4o"&lt;/span&gt;
      &lt;span class="n"&gt;agent_name&lt;/span&gt; &lt;span class="s2"&gt;"Outer"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;outcome&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;FoobaraDemo&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;LoanOrigination&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ReviewAllLoanFiles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;outcome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;success?&lt;/span&gt;
  &lt;span class="n"&gt;outcome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;name_and_decision&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;decision&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name_and_decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values_at&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:applicant_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:decision&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;denied?&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Denied: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Reason: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;denied_reasons&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;", "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Approved: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;outcome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;errors_hash&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We've abandoned the CLI command connector and are just using the commands directly.&lt;/p&gt;

&lt;p&gt;We have introduced a second &lt;code&gt;AgentBackedCommand&lt;/code&gt; called &lt;code&gt;ReviewLoanFile&lt;/code&gt;. These two &lt;code&gt;AgentBackedCommand&lt;/code&gt;s are not only using two different models but two different services entirely.&lt;/p&gt;

&lt;h3&gt;
  
  
  Specifying an Inputs Type for an AgentBackedCommand
&lt;/h3&gt;

&lt;p&gt;We are making use of &lt;code&gt;inputs&lt;/code&gt; on &lt;code&gt;ReviewLoanFile&lt;/code&gt; just like we would with any &lt;code&gt;Foobara::Command&lt;/code&gt; that needs inputs. Originally, inputs there were defined as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;inputs&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;loan_file&lt;/span&gt; &lt;span class="no"&gt;LoanFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:required&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This worked but this presents a problem. Can you spot it? We want to avoid things like bias from the names of the applicants influencing decisions. So we remodeled it by introducing a new model to provide the minimum information required and called it &lt;code&gt;UnderwriterSummary&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Something cool about this is we didn't have to change &lt;code&gt;ReviewAllLoanFiles&lt;/code&gt; when we changed the inputs to &lt;code&gt;ReviewLoanFile&lt;/code&gt; since it has no &lt;code&gt;#execute&lt;/code&gt; method nor domain logic to update to conform to the new interface!&lt;/p&gt;

&lt;h3&gt;
  
  
  Specifying and Using the AgentBackedCommand Result Programmatically!
&lt;/h3&gt;

&lt;p&gt;We are also specifying a result type for &lt;code&gt;ReviewAllLoanFiles&lt;/code&gt;, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
          &lt;span class="ss"&gt;applicant_name: :string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="ss"&gt;decision: &lt;/span&gt;&lt;span class="no"&gt;LoanFile&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;UnderwriterDecision&lt;/span&gt;
        &lt;span class="p"&gt;}]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and are making programmatic use of its outcome like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;denied?&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Denied: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Reason: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;denied_reasons&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;", "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Approved: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are guaranteed that this data has the types we specified in our &lt;code&gt;result&lt;/code&gt; declaration, just like with any other &lt;code&gt;Foobara::Command&lt;/code&gt; and can use it programmatically just fine as a result.&lt;/p&gt;

&lt;p&gt;We are also making use of &lt;code&gt;depends_on&lt;/code&gt; which is standard Foobara stuff to limit what subcommands a command is allowed to run.&lt;/p&gt;

&lt;p&gt;There are a few AgentBackedCommand-specific DSL methods that we're making use of here: &lt;code&gt;verbose&lt;/code&gt; will let us see which decisions which Agent is making, &lt;code&gt;llm_model&lt;/code&gt; will let us specify the model for each agent independently, and &lt;code&gt;agent_name&lt;/code&gt; will let us specify the name for each agent independently so we can tell them apart in the output.&lt;/p&gt;

&lt;p&gt;Let's first re-create our demo records:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ./loan-origination Demo::PrepareDemoRecords
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now let's run this new script and review these loan files with two agents!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ./review-all-loan-files
Outer: Foobara::Agent::DescribeCommand.run(command_name: "Foobara::Agent::ListCommands")
Outer: Foobara::Agent::ListCommands.run
Outer: Foobara::Agent::DescribeCommand.run(command_name: "FoobaraDemo::LoanOrigination::FindALoanFileThatNeedsReview")
Outer: FoobaraDemo::LoanOrigination::FindALoanFileThatNeedsReview.run
Outer: Foobara::Agent::DescribeCommand.run(command_name: "FoobaraDemo::LoanOrigination::ReviewLoanFile")
Outer: FoobaraDemo::LoanOrigination::ReviewLoanFile.run(loan_file_id: 4, pay_stub_count: 1, fico_scores: [600, 650, 750], credit_policy: 4)
Inner: Foobara::Agent::DescribeCommand.run(command_name: "Foobara::Agent::ListCommands")
Inner: Foobara::Agent::ListCommands.run
Inner: Foobara::Agent::DescribeCommand.run(command_name: "FoobaraDemo::LoanOrigination::StartUnderwriterReview")
Inner: Foobara::Agent::DescribeCommand.run(command_name: "FoobaraDemo::LoanOrigination::DenyLoanFile")
Inner: Foobara::Agent::DescribeCommand.run(command_name: "FoobaraDemo::LoanOrigination::ApproveLoanFile")
Inner: FoobaraDemo::LoanOrigination::StartUnderwriterReview.run(loan_file: 4)
Inner: FoobaraDemo::LoanOrigination::DenyLoanFile.run(loan_file: 4, credit_score_used: 650, denied_reasons: ["low_credit_score"])
Inner: Foobara::Agent::DescribeCommand.run(command_name: "Foobara::Agent::Inner::NotifyUserThatCurrentGoalHasBeenAccomplished")
Inner: Foobara::Agent::Inner::NotifyUserThatCurrentGoalHasBeenAccomplished.run(result: {"decision" =&amp;gt; "denied", "credit_score_used" =&amp;gt; 650, "denied_reasons" =&amp;gt; ["low_credit_score"]})
Outer: FoobaraDemo::LoanOrigination::FindALoanFileThatNeedsReview.run
Outer: FoobaraDemo::LoanOrigination::ReviewLoanFile.run(loan_file_id: 5, pay_stub_count: 1, fico_scores: [600, 650, 750], credit_policy: 5)
Inner: Foobara::Agent::DescribeCommand.run(command_name: "Foobara::Agent::ListCommands")
Inner: Foobara::Agent::ListCommands.run
Inner: Foobara::Agent::DescribeCommand.run(command_name: "FoobaraDemo::LoanOrigination::StartUnderwriterReview")
Inner: Foobara::Agent::DescribeCommand.run(command_name: "FoobaraDemo::LoanOrigination::DenyLoanFile")
Inner: Foobara::Agent::DescribeCommand.run(command_name: "FoobaraDemo::LoanOrigination::ApproveLoanFile")
Inner: FoobaraDemo::LoanOrigination::StartUnderwriterReview.run(loan_file: 5)
Inner: FoobaraDemo::LoanOrigination::DenyLoanFile.run(loan_file: 5, credit_score_used: 750, denied_reasons: ["insufficient_pay_stubs_provided"])
Inner: Foobara::Agent::DescribeCommand.run(command_name: "Foobara::Agent::Inner::NotifyUserThatCurrentGoalHasBeenAccomplished")
Inner: Foobara::Agent::Inner::NotifyUserThatCurrentGoalHasBeenAccomplished.run(result: {"decision" =&amp;gt; "denied", "credit_score_used" =&amp;gt; 750, "denied_reasons" =&amp;gt; ["insufficient_pay_stubs_provided"]})
Outer: FoobaraDemo::LoanOrigination::FindALoanFileThatNeedsReview.run
Outer: FoobaraDemo::LoanOrigination::ReviewLoanFile.run(loan_file_id: 5, pay_stub_count: 1, fico_scores: [600, 650, 750], credit_policy: 5)
Inner: Foobara::Agent::DescribeCommand.run(command_name: "Foobara::Agent::ListCommands")
Inner: Foobara::Agent::ListCommands.run
Inner: Foobara::Agent::DescribeCommand.run(command_name: "FoobaraDemo::LoanOrigination::StartUnderwriterReview")
Inner: Foobara::Agent::DescribeCommand.run(command_name: "FoobaraDemo::LoanOrigination::DenyLoanFile")
Inner: Foobara::Agent::DescribeCommand.run(command_name: "FoobaraDemo::LoanOrigination::ApproveLoanFile")
Inner: FoobaraDemo::LoanOrigination::StartUnderwriterReview.run(loan_file: 5)
Inner: FoobaraDemo::LoanOrigination::ApproveLoanFile.run(loan_file: 5, credit_score_used: 750)
Inner: Foobara::Agent::DescribeCommand.run(command_name: "Foobara::Agent::Inner::NotifyUserThatCurrentGoalHasBeenAccomplished")
Inner: Foobara::Agent::Inner::NotifyUserThatCurrentGoalHasBeenAccomplished.run(result: {"decision" =&amp;gt; "approved", "credit_score_used" =&amp;gt; 750})
Outer: FoobaraDemo::LoanOrigination::FindALoanFileThatNeedsReview.run
Outer: Foobara::Agent::DescribeCommand.run(command_name: "Foobara::Agent::Outer::NotifyUserThatCurrentGoalHasBeenAccomplished")
Outer: Foobara::Agent::Outer::NotifyUserThatCurrentGoalHasBeenAccomplished.run(result: [{"applicant_name" =&amp;gt; "Barbara", "decision" =&amp;gt; {"decision" =&amp;gt; "denied", "credit_score_used" =&amp;gt; 650, "denied_reasons" =&amp;gt; ["low_credit_score"]}}, {"applicant_name" =&amp;gt; "Basil", "decision" =&amp;gt; {"decision" =&amp;gt; "denied", "credit_score_used" =&amp;gt; 750, "denied_reasons" =&amp;gt; ["insufficient_pay_stubs_provided"]}}, {"applicant_name" =&amp;gt; "Fumiko", "decision" =&amp;gt; {"decision" =&amp;gt; "approved", "credit_score_used" =&amp;gt; 750}}])

Denied: Barbara
Reason: low_credit_score

Denied: Basil
Reason: insufficient_pay_stubs_provided

Approved: Fumiko
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cool! We programmatically used result data from a command without having to write its execute method!&lt;/p&gt;

&lt;p&gt;And if we check &lt;code&gt;./loan-origination GenerateLoanFilesReport&lt;/code&gt; we can see that our program did everything correctly!&lt;/p&gt;

&lt;h3&gt;
  
  
  An Interesting Takeaway
&lt;/h3&gt;

&lt;p&gt;Putting together this demo, something crossed my mind: It could be that we might find ourselves wanting to use LLMs to handle some of this domain logic for us as we prototype and discover the domain, but once the business scales, it might be worth the cost savings to then convert &lt;code&gt;AgentBackedCommand&lt;/code&gt;s to just regular &lt;code&gt;Foobara::Command&lt;/code&gt;s. &lt;/p&gt;

&lt;p&gt;Take for example &lt;code&gt;ReviewAllLoanFiles&lt;/code&gt;. We did get some benefit of not having to manage the interface change between it and ReviewLoanFile`, but it could be expensive to run if the business scales even though its domain logic isn't that difficult to implement in a typical #execute method.&lt;/p&gt;

&lt;p&gt;This possibility is interesting to me because it is the opposite of my intuition: that we might start with a well-working domain and then look for opportunities to automate parts of it. In some cases, it might be that we want the reverse: to automate various high-level domain operations during prototyping and early stages of business and then start replacing LLM automation with implemented domain logic as the business scales and the domain solidifies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Links
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The foobara-agent-backed-command gem: &lt;a href="https://github.com/foobara/agent-backed-command" rel="noopener noreferrer"&gt;https://github.com/foobara/agent-backed-command&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Code demo video of AgentBackedCommand: &lt;a href="https://youtu.be/hBleW4m9JFQ" rel="noopener noreferrer"&gt;https://youtu.be/hBleW4m9JFQ&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The demo loan origination domain: &lt;a href="https://github.com/foobara-demo/loan-origination/tree/main/src" rel="noopener noreferrer"&gt;https://github.com/foobara-demo/loan-origination/tree/main/src&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Code used in this demo: &lt;a href="https://github.com/foobara/foobarticles/tree/main/src/agent_in_one_line_of_ruby_code" rel="noopener noreferrer"&gt;https://github.com/foobara/foobarticles/tree/main/src/agent_in_one_line_of_ruby_code&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Foobara: &lt;a href="https://foobara.org" rel="noopener noreferrer"&gt;https://foobara.org&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Please Reach Out!
&lt;/h3&gt;

&lt;p&gt;Want help using Foobara or want to help Foobara by contributing code/art/documentation/whatever to it? Please reach out! &lt;a href="https://foobara.org" rel="noopener noreferrer"&gt;https://foobara.org&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Disclaimers
&lt;/h3&gt;

&lt;p&gt;1) This agent just does whatever it thinks it needs to do to accomplish its goal. So play with this with caution! &lt;br&gt;
2) This loan origination domain is just to demo cool aspects of Foobara in a relatable way. This is probably obvious, but this is not meant for making real credit decisions, which might not even be a safe task for an LLM, anyway.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>tutorial</category>
      <category>ruby</category>
    </item>
  </channel>
</rss>
