<?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: langchain</title>
    <description>The latest articles tagged 'langchain' on DEV Community.</description>
    <link>https://dev.to/t/langchain</link>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tag/langchain"/>
    <language>en</language>
    <item>
      <title>Benchmarking Gemini, Claude, and OpenAI for Structured Document Extraction</title>
      <dc:creator>Austin Vance</dc:creator>
      <pubDate>Fri, 14 Aug 2026 02:51:34 +0000</pubDate>
      <link>https://dev.to/focused_dot_io/benchmarking-gemini-claude-and-openai-for-structured-document-extraction-151j</link>
      <guid>https://dev.to/focused_dot_io/benchmarking-gemini-claude-and-openai-for-structured-document-extraction-151j</guid>
      <description>&lt;p&gt;A few fellow engineers and I were talking about field extraction the other day. They were both saying Gemini's been surprisingly good at pulling structured data off documents, which surprised me, since that's not really the model I'd have reached for first. So we ran an experiment using &lt;a href="https://www.langchain.com/langsmith/observability" rel="noopener noreferrer"&gt;LangSmith&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I printed ten copies of a form with the usual set of fields, names, dates, IDs, a checkbox, a signature line, and asked my coworker to help me fill them out by hand. I ran OCR on them too, mostly out of curiosity. It was pretty bad, which wasn't unexpected, especially on checkboxes.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Testing it&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I set up a LangGraph graph with one node that does the extraction, and passed in which provider to use as runtime context, so the eval could run the exact same graph once per model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ExtractionState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Runtime&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ExtractionContext&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;extractor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;EXTRACTORS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;extractor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;image_path&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I hand-labeled ground truth for every form and ran it all through LangSmith so I could score each model against the exact same data.&lt;/p&gt;

&lt;p&gt;Scoring took a bit of tuning, mostly because a plain exact string match evaluator will ding a model for writing "Sr" instead of "Sr." or "management" instead of "Management," which isn't actually wrong, it's just formatting. So everything got normalized first (lowercased, trailing punctuation stripped, dates parsed into one format, phone numbers stripped down to digits) and scored three ways: fraction of fields correct for partial credit, whether the whole record was perfect for a stricter all-or-nothing exact match, and field accuracy per dollar.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Field accuracy&lt;/th&gt;
&lt;th&gt;Exact match&lt;/th&gt;
&lt;th&gt;Perfect records&lt;/th&gt;
&lt;th&gt;Field accuracy / cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Claude (opus-5)&lt;/td&gt;
&lt;td&gt;0.934&lt;/td&gt;
&lt;td&gt;0.364&lt;/td&gt;
&lt;td&gt;4/11&lt;/td&gt;
&lt;td&gt;31.8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude (haiku-4-5)&lt;/td&gt;
&lt;td&gt;0.636&lt;/td&gt;
&lt;td&gt;0.091&lt;/td&gt;
&lt;td&gt;1/11&lt;/td&gt;
&lt;td&gt;207.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemini (3.1-pro-preview)&lt;/td&gt;
&lt;td&gt;0.934&lt;/td&gt;
&lt;td&gt;0.636&lt;/td&gt;
&lt;td&gt;7/11&lt;/td&gt;
&lt;td&gt;93.1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemini (flash-lite-latest)&lt;/td&gt;
&lt;td&gt;0.884&lt;/td&gt;
&lt;td&gt;0.455&lt;/td&gt;
&lt;td&gt;5/11&lt;/td&gt;
&lt;td&gt;1084.8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenAI (gpt-5.6-sol)&lt;/td&gt;
&lt;td&gt;0.860&lt;/td&gt;
&lt;td&gt;0.455&lt;/td&gt;
&lt;td&gt;5/11&lt;/td&gt;
&lt;td&gt;50.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenAI (gpt-5.4-nano)&lt;/td&gt;
&lt;td&gt;0.620&lt;/td&gt;
&lt;td&gt;0.091&lt;/td&gt;
&lt;td&gt;1/11&lt;/td&gt;
&lt;td&gt;814.4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Claude and Gemini ended up tied on average field accuracy, but Gemini still got a lot more whole forms completely right, which is a different thing to be measuring than it sounds like at first. The other thing that jumped out was the cheap tiers. Gemini's Flash Lite scored higher on field accuracy than OpenAI's flagship did, while Claude's Haiku and OpenAI's nano both fell off hard.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Picking a metric&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;No single model won across the board, and that's kind of the whole point. Field accuracy, exact match, and cost efficiency measure different things, so a model that dominates one of them can easily be the weakest on another. What's nice about having an eval running is that switching which one you care about is just a matter of changing what you sort by.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Optimizing for exact match&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A form that's 11 out of 12 fields right still needs someone to go fix that twelfth field, and that costs about the same as fixing a form that's only 6 out of 12 right, since either way a person has to open it back up. That's the case for caring about exact match instead of average field accuracy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.prod.website-files.com%2F69171c5b6a36fedc1f0d6866%2F6a7cb09f383e0fb625e744bc_image%2520%286%29.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.prod.website-files.com%2F69171c5b6a36fedc1f0d6866%2F6a7cb09f383e0fb625e744bc_image%2520%286%29.png" width="800" height="475"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;exact match and field accuracy per model with a baseline selected for exact match&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Optimizing for field accuracy&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Field accuracy gives partial credit for every field that's right, which matters more than exact match when a human is going to check every field anyway. Fewer wrong fields overall beats fewer broken records when the correction happens field by field instead of record by record.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.prod.website-files.com%2F69171c5b6a36fedc1f0d6866%2F6a7cb1b622a293d1cf534b1a_image%2520%287%29.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.prod.website-files.com%2F69171c5b6a36fedc1f0d6866%2F6a7cb1b622a293d1cf534b1a_image%2520%287%29.png" width="800" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;exact match and field accuracy per model with a baseline selected for field accuracy&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Optimizing for cost&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Cost efficiency matters most at volume, since a cheaper model that's a little less accurate can still get more forms extracted correctly per dollar than a pricier one that's only a little better.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.prod.website-files.com%2F69171c5b6a36fedc1f0d6866%2F6a7cb1e4bbce61d903d42d5f_image%2520%288%29.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.prod.website-files.com%2F69171c5b6a36fedc1f0d6866%2F6a7cb1e4bbce61d903d42d5f_image%2520%288%29.png" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;exact match, field accuracy, and accuracy per dollar with a baseline selected for accuracy per dollar&lt;/p&gt;

&lt;p&gt;So Chris and Mike were right, though the answer splits three ways. Gemini Pro won exact match and tied Claude Opus on field accuracy, and Gemini Flash Lite won on cost. Flash Lite is the one I didn't see coming, since it beat OpenAI's flagship on field accuracy too, at a tiny fraction of the price.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Technical References:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/focused-dot-io/form-extraction" rel="noopener noreferrer"&gt;Benchmarking LLMs for Structured Data Extraction GitHub Repo&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>langchain</category>
      <category>observability</category>
      <category>ai</category>
    </item>
    <item>
      <title>Building a Profitable AI Agent with LangChain: A Step-by-Step Tutorial</title>
      <dc:creator>Caper B</dc:creator>
      <pubDate>Fri, 14 Aug 2026 02:23:25 +0000</pubDate>
      <link>https://dev.to/caper_dev/building-a-profitable-ai-agent-with-langchain-a-step-by-step-tutorial-18h2</link>
      <guid>https://dev.to/caper_dev/building-a-profitable-ai-agent-with-langchain-a-step-by-step-tutorial-18h2</guid>
      <description>&lt;h1&gt;
  
  
  Building a Profitable AI Agent with LangChain: A Step-by-Step Tutorial
&lt;/h1&gt;

&lt;p&gt;LangChain is a powerful framework for building AI agents that can interact with various applications and services. In this tutorial, we'll explore how to create an AI agent that can earn money by automating tasks and providing value to users. We'll cover the practical steps to build and deploy our agent, and discuss the monetization strategies to generate revenue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Setting up the Environment
&lt;/h2&gt;

&lt;p&gt;To start, we need to set up our development environment. We'll use Python as our programming language and install the required libraries. Run the following command in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;langchain
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will install the LangChain library and its dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Creating the AI Agent
&lt;/h2&gt;

&lt;p&gt;Next, we'll create a simple AI agent using LangChain. Our agent will be able to interact with the Twitter API to post updates and respond to messages. Create a new Python file called &lt;code&gt;agent.py&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;langchain&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.agents&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Tool&lt;/span&gt;

&lt;span class="c1"&gt;# Define the Twitter API credentials
&lt;/span&gt;&lt;span class="n"&gt;twitter_api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;twitter_api_secret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_API_SECRET&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# Create a new LangChain agent
&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;langchain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Define a tool for interacting with the Twitter API
&lt;/span&gt;&lt;span class="n"&gt;twitter_tool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;twitter&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Interact with the Twitter API&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;functions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;post_update&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Post an update to Twitter&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;respond_to_message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Respond to a message on Twitter&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Add the Twitter tool to the agent
&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;twitter_tool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;YOUR_API_KEY&lt;/code&gt; and &lt;code&gt;YOUR_API_SECRET&lt;/code&gt; with your actual Twitter API credentials.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Implementing the Twitter Tool
&lt;/h2&gt;

&lt;p&gt;Now, we'll implement the functions for the Twitter tool. Create a new Python file called &lt;code&gt;twitter_tool.py&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tweepy&lt;/span&gt;

&lt;span class="c1"&gt;# Define the Twitter API credentials
&lt;/span&gt;&lt;span class="n"&gt;twitter_api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;twitter_api_secret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_API_SECRET&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# Create a new Tweepy API object
&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tweepy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;API&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tweepy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;OAuthHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;twitter_api_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;twitter_api_secret&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;# Define the function to post an update to Twitter
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;post_update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Define the function to respond to a message on Twitter
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;respond_to_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_direct_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;screen_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, replace &lt;code&gt;YOUR_API_KEY&lt;/code&gt; and &lt;code&gt;YOUR_API_SECRET&lt;/code&gt; with your actual Twitter API credentials.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Integrating the Twitter Tool with the AI Agent
&lt;/h2&gt;

&lt;p&gt;Now, we'll integrate the Twitter tool with our AI agent. In the &lt;code&gt;agent.py&lt;/code&gt; file, add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Import the Twitter tool functions
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;twitter_tool&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;post_update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;respond_to_message&lt;/span&gt;

&lt;span class="c1"&gt;# Define the function to handle incoming messages
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Use the AI agent to generate a response
&lt;/span&gt;    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Respond to the message using the Twitter tool
&lt;/span&gt;    &lt;span class="nf"&gt;respond_to_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Define the function to post updates to Twitter
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;post_update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Use the Twitter tool to post the update
&lt;/span&gt;    &lt;span class="nf"&gt;post_update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Monetizing the AI Agent
&lt;/h2&gt;

&lt;p&gt;To monetize our AI agent, we can use various strategies such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sponsored tweets&lt;/strong&gt;: Partner with brands to post sponsored tweets to our Twitter account.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Affiliate marketing&lt;/strong&gt;: Promote products or services and earn a commission for each sale made through our unique referral link.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Native advertising&lt;/strong&gt;: Use platforms like Taboola or Outbrain to promote content and earn revenue from clicks or conversions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can integrate&lt;/p&gt;

</description>
      <category>ai</category>
      <category>langchain</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Building a Multi-Agent AI Pipeline That Ships: LangGraph, RAG, and Evals That Matter</title>
      <dc:creator>manasviboineypally</dc:creator>
      <pubDate>Thu, 13 Aug 2026 17:14:25 +0000</pubDate>
      <link>https://dev.to/manasviboineypally/building-a-multi-agent-ai-pipeline-that-ships-langgraph-rag-and-evals-that-matter-32db</link>
      <guid>https://dev.to/manasviboineypally/building-a-multi-agent-ai-pipeline-that-ships-langgraph-rag-and-evals-that-matter-32db</guid>
      <description>&lt;p&gt;I spent 18 days building an AI product that converts research papers into audience-tailored PowerPoint presentations. Not a toy — a real deployed thing at &lt;a href="https://web-production-6eded.up.railway.app" rel="noopener noreferrer"&gt;doc2slides on Railway&lt;/a&gt; that anyone can use.&lt;/p&gt;

&lt;p&gt;The interesting parts weren't the "make it work" moments. They were the tradeoffs I had to make honestly, and the times I resisted the temptation to add a "clever" fix that would have made things worse.&lt;/p&gt;

&lt;p&gt;This post is about those decisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Doc2Slides&lt;/strong&gt; takes a PDF and produces a &lt;code&gt;.pptx&lt;/code&gt; file tailored to four audiences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Kid&lt;/strong&gt; — fun analogies, simple words&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Student&lt;/strong&gt; — educational, terms defined&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Engineer&lt;/strong&gt; — technical depth, assumes domain knowledge&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Executive&lt;/strong&gt; — business focus, impact-oriented&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The magic is that &lt;strong&gt;the same paper produces radically different output&lt;/strong&gt; based on the audience. A compiler theory paper for a kid becomes "compilers are like magic helpers." The same paper for an executive becomes "advancing compiler technology with formal frameworks."&lt;/p&gt;

&lt;p&gt;Code: &lt;a href="https://github.com/manasviboineypally/doc2slides" rel="noopener noreferrer"&gt;github.com/manasviboineypally/doc2slides&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The architecture: 5 agents in LangGraph
&lt;/h2&gt;

&lt;p&gt;I built this as a multi-agent pipeline instead of one giant LLM prompt. Here's the flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PDF Upload
    ↓
Parser        → extracts sections + metadata
    ↓
Summarizer    → RAG-based section summarization
    ↓
Planner       → designs slide structure for audience
    ↓
Writer        → generates audience-adaptive slide content
    ↓
Builder       → produces editable .pptx file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each agent is an independent node in a LangGraph state machine. They share a &lt;code&gt;TypedDict&lt;/code&gt; state and read/write specific fields.&lt;/p&gt;

&lt;p&gt;Here's what the graph definition actually looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langgraph.graph&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StateGraph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;END&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app.agents.state&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AgentState&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app.agents.parser&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;parser_agent&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app.agents.summarizer&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;summarizer_agent&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app.agents.planner&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;planner_agent&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app.agents.writer&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;writer_agent&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app.agents.builder&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;builder_agent&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;build_pipeline&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;StateGraph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;parser&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parser_agent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;summarizer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;summarizer_agent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;planner&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;planner_agent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;writer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;writer_agent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;builder&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;builder_agent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_entry_point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;parser&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;parser&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;summarizer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;summarizer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;planner&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;planner&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;writer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;writer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;builder&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;builder&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;END&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why LangGraph over a sequential chain?&lt;/strong&gt; Adding a new agent is a 2-line change to the graph. In a sequential chain, adding a new step often means refactoring the previous ones. State-based multi-agent design scales better.&lt;/p&gt;




&lt;h2&gt;
  
  
  The interesting tradeoff #1: My RAG top-1 precision is 42%
&lt;/h2&gt;

&lt;p&gt;I built an evaluation harness because I wanted to measure quality, not just claim it. Three eval types:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Parser evals&lt;/strong&gt; — deterministic ground-truth assertions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RAG evals&lt;/strong&gt; — top-K precision on hand-labeled query→section pairs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Summarizer evals&lt;/strong&gt; — LLM-as-judge scoring faithfulness, completeness, clarity&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The parser evals scored 100% (34/34 checks). The summarizer evals averaged 4.4/5.&lt;/p&gt;

&lt;p&gt;But the RAG top-1 precision came in at &lt;strong&gt;42%&lt;/strong&gt;. Only 3 of 7 queries returned the correct section as the top result.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My first instinct:&lt;/strong&gt; hide the number. Report top-3 (57%) instead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I did instead:&lt;/strong&gt; publish both numbers and explain why.&lt;/p&gt;

&lt;p&gt;Looking at the failures revealed a real limitation of RAG:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Query: "how does the genetic algorithm work?"&lt;/li&gt;
&lt;li&gt;Expected section: &lt;code&gt;Methodology&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Actual top result: &lt;code&gt;3.6 Stopping Criteria&lt;/code&gt; (a subsection of methodology)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Genetic algorithms are discussed in 6 subsections (3.1 through 3.6). Vector search returns the highest-scoring &lt;em&gt;chunk&lt;/em&gt;, not the highest-scoring &lt;em&gt;section&lt;/em&gt;. For queries about broad topics, subsections often outrank the parent section because they mention the specific term more densely.&lt;/p&gt;

&lt;p&gt;This is a known problem in RAG. Solutions include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hierarchical retrieval (search subsections, bubble to parent)&lt;/li&gt;
&lt;li&gt;Query rewriting to be more specific&lt;/li&gt;
&lt;li&gt;Retrieve top-K and let an LLM pick the right section&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these are fixed today. But I know exactly what's broken and why — which is more useful than pretending it works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt; deterministic metrics beat vibes. Vibes let you convince yourself the AI is smart. Metrics tell you where it's dumb.&lt;/p&gt;




&lt;h2&gt;
  
  
  The interesting tradeoff #2: I refused to use word count as a proxy for content density
&lt;/h2&gt;

&lt;p&gt;Users can request any number of slides between 3 and 50. When the paper's actual content density doesn't match the requested slide count, the LLM either pads shallow sections or compresses dense ones. This creates mild redundancy at high slide counts.&lt;/p&gt;

&lt;p&gt;The obvious fix: allocate slides based on section word count. Long section = more slides. Short section = fewer slides.&lt;/p&gt;

&lt;p&gt;I almost built this. Then I realized: &lt;strong&gt;word count is not content density&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A 100-word section with 3 distinct concepts should get multiple slides&lt;/li&gt;
&lt;li&gt;A 2000-word section rambling around one idea should get one slide&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Word count would systematically reward verbose sections and penalize concise ones. That's not a fix — it's a bug with math.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I did instead:&lt;/strong&gt; documented the tradeoff and shipped without the heuristic. From the project's &lt;code&gt;testing_notes.md&lt;/code&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Rejected quick fix:&lt;/strong&gt; using section word count as a proxy for content density. Word count is not density — a short section may contain multiple distinct ideas while a long section may ramble around one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Proper solution deferred:&lt;/strong&gt; content-aware slide allocation with LLM judgment, verified by an evaluation harness that measures output quality against ground truth. Requires infrastructure work not appropriate for the initial version.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt; the right answer to "should I add this heuristic?" is often "no." Heuristics feel like progress. Sometimes they're anti-progress dressed up as pragmatism.&lt;/p&gt;




&lt;h2&gt;
  
  
  The interesting tradeoff #3: SQLite dev → PostgreSQL prod is one variable
&lt;/h2&gt;

&lt;p&gt;I built with local SQLite during development but deployed to Railway with PostgreSQL. The migration was one line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/db/session.py
&lt;/span&gt;&lt;span class="n"&gt;DATABASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_engine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For local dev, &lt;code&gt;.env&lt;/code&gt; has:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;sqlite:///./doc2slides.db&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Railway, the environment variable is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;postgresql+psycopg2://postgres:xxx@host:5432/railway&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing else changes. SQLAlchemy models are backend-agnostic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is boring engineering.&lt;/strong&gt; But boring engineering is what lets you sleep at night. When someone asks "how do you handle database migrations?" the answer isn't a clever hack — it's "environment-driven configuration and a repository pattern."&lt;/p&gt;




&lt;h2&gt;
  
  
  The stack
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Choice&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Language&lt;/td&gt;
&lt;td&gt;Python 3.13&lt;/td&gt;
&lt;td&gt;AI ecosystem&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API&lt;/td&gt;
&lt;td&gt;FastAPI&lt;/td&gt;
&lt;td&gt;Async support, auto Swagger docs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Orchestration&lt;/td&gt;
&lt;td&gt;LangGraph&lt;/td&gt;
&lt;td&gt;State-based multi-agent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LLM&lt;/td&gt;
&lt;td&gt;OpenAI GPT-4o-mini&lt;/td&gt;
&lt;td&gt;Cheap enough for iteration, smart enough for structured output&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vector DB&lt;/td&gt;
&lt;td&gt;ChromaDB&lt;/td&gt;
&lt;td&gt;Local, no cloud dependency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Structured output&lt;/td&gt;
&lt;td&gt;JSON mode + Pydantic&lt;/td&gt;
&lt;td&gt;Two-layer validation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;td&gt;SQLAlchemy + PostgreSQL&lt;/td&gt;
&lt;td&gt;Env-driven, portable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frontend&lt;/td&gt;
&lt;td&gt;Vanilla HTML/CSS/JS&lt;/td&gt;
&lt;td&gt;No build step, portable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deployment&lt;/td&gt;
&lt;td&gt;Railway&lt;/td&gt;
&lt;td&gt;GitHub CI/CD, managed Postgres&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The frontend is worth calling out. I used no framework — just HTML, CSS, and vanilla JavaScript in ~500 lines. Zero build step. Anyone can clone the repo, open the file, and understand it in 5 minutes.&lt;/p&gt;

&lt;p&gt;For an MVP, that's a feature, not a limitation.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I didn't build (and why that's OK)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Skipped:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User authentication&lt;/li&gt;
&lt;li&gt;Multi-tenant workspaces&lt;/li&gt;
&lt;li&gt;Custom presentation templates&lt;/li&gt;
&lt;li&gt;Streaming responses&lt;/li&gt;
&lt;li&gt;Job queue with Celery/Redis&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; MVP. Every feature has a cost. Shipping the core value (PDF → audience-tailored slides) matters more than shipping every possible feature.&lt;/p&gt;

&lt;p&gt;For a portfolio project, "I could have added X but chose not to for these reasons" is a stronger answer than "I added X poorly."&lt;/p&gt;




&lt;h2&gt;
  
  
  Lessons I'd tell my past self
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Build evals before optimizing.&lt;/strong&gt; I built the pipeline first, then evals. If I had built evals first, I would have known earlier that my RAG had issues. Now I have to make eval-driven improvements Week 3.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Resist heuristics.&lt;/strong&gt; Every time I thought "this is a quick fix," it was actually a technical debt I was about to bake in. Word count as density. Silent AI slide count overrides. Boolean status flags instead of proper enums.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Deploy early.&lt;/strong&gt; I deployed on Day 16 of 18. I should have deployed on Day 8. Deployment reveals real bugs — environment variable typos, missing dependencies, hardcoded localhost URLs. The sooner you find them, the cheaper they are.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Document tradeoffs, not features.&lt;/strong&gt; Anyone can read code to know what it does. Almost no one leaves notes on &lt;strong&gt;why&lt;/strong&gt; a design choice was made. My &lt;code&gt;testing_notes.md&lt;/code&gt; file is where most of the actual engineering thinking lives.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;The project is live, but not "done." Future work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Content-aware slide count (with an eval harness measuring output quality)&lt;/li&gt;
&lt;li&gt;Multi-language support for input PDFs&lt;/li&gt;
&lt;li&gt;Custom presentation templates&lt;/li&gt;
&lt;li&gt;Fix RAG for hierarchical sections (subsection → parent bubbling)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to try Doc2Slides yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live demo:&lt;/strong&gt; &lt;a href="https://web-production-6eded.up.railway.app" rel="noopener noreferrer"&gt;web-production-6eded.up.railway.app&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code:&lt;/strong&gt; &lt;a href="https://github.com/manasviboineypally/doc2slides" rel="noopener noreferrer"&gt;github.com/manasviboineypally/doc2slides&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;60-second video demo:&lt;/strong&gt; &lt;a href="https://www.loom.com/share/693e5b567f284af99dc86286b33a4b66" rel="noopener noreferrer"&gt;Loom link&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Upload any PDF, pick your audience, get back a deck. Same paper, radically different output depending on who you say you're presenting to.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Author:&lt;/strong&gt; Manasvi Boineypally — &lt;a href="https://github.com/manasviboineypally" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; · &lt;a href="https://www.linkedin.com/in/manasviboineypally" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>langchain</category>
      <category>rag</category>
    </item>
    <item>
      <title>10 Best LangChain Development Companies</title>
      <dc:creator>Utsav Prajapati</dc:creator>
      <pubDate>Thu, 13 Aug 2026 09:29:10 +0000</pubDate>
      <link>https://dev.to/findyouralternative/10-best-langchain-development-companies-2e58</link>
      <guid>https://dev.to/findyouralternative/10-best-langchain-development-companies-2e58</guid>
      <description>&lt;p&gt;LangChain has become one of the default frameworks for building production LLM applications chaining prompts, connecting retrieval augmented generation (RAG) pipelines, and orchestrating multi-step AI agents instead of hand-rolling API calls. But "LangChain development" isn't really a standalone skill you hire for in isolation it sits on top of broader AI engineering, data infrastructure, and software delivery experience. That's why almost nobody on this list is a pure "LangChain shop." They're software and AI development companies with real generative-AI delivery experience, where LangChain (or a comparable orchestration framework) is one tool in a bigger toolkit.&lt;/p&gt;

&lt;p&gt;Here are 10 companies worth shortlisting if you're hiring for a LangChain or LLM-application build, what each one is actually good at, and who should reach for them.&lt;/p&gt;

&lt;p&gt;🔎 Want to compare these side-by-side with live pricing, reviews, and alternatives? Check the full &lt;a href="https://findalternatives.net/directory/langchain-developers" rel="noopener noreferrer"&gt;LangChain Developers&lt;/a&gt; on &lt;a href="https://findalternatives.net/" rel="noopener noreferrer"&gt;Find Alternatives&lt;/a&gt; it's updated as tools change.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick Rundown&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here's the full list at a glance before we dive into details:&lt;/p&gt;

&lt;p&gt;1.Aalpha — India based outsourcing shop offering AI-driven web, mobile, and enterprise app development&lt;br&gt;
2.Sigma Software — 20+ year IT partner with a dedicated AI/agentic workflow practice&lt;br&gt;
3.Accenture — Global consulting giant with a large scale enterprise AI practice&lt;br&gt;
4.N-iX — Eastern European engineering firm focused on measurable, production grade AI adoption&lt;br&gt;
5.Lunar Logic — Small, product focused Polish agile software house&lt;br&gt;
6.Turing — AI powered talent cloud for hiring pre-vetted remote AI engineers&lt;br&gt;
7.Savvy Apps — US based, Globant owned mobile and web product design agency&lt;br&gt;
8.InData Labs — Dedicated AI and data science consultancy with 10+ years in ML/NLP&lt;br&gt;
9.Andersen — Large global software company with a formal AI native delivery practice&lt;br&gt;
10.Valor Software — Frontend-focused consultancy (Angular, Vue, React) now building AI powered features&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffuha0tr45e4i67pu0kum.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffuha0tr45e4i67pu0kum.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.aalpha.net/" rel="noopener noreferrer"&gt;&lt;strong&gt;1. Aalpha&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Aalpha is an India-based IT consulting and custom software outsourcing company, founded in 2008, with a long track record in web, mobile, and cloud/SaaS development across 5,500+ projects. It has more recently repositioned around "AI-driven IT solutions," building AI-powered web, mobile, and enterprise applications on top of its existing full-stack engineering base.&lt;/p&gt;

&lt;p&gt;Best for: Startups and SMEs wanting a cost-effective offshore partner that can bolt AI features onto a broader web/mobile build.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sigma.software/" rel="noopener noreferrer"&gt;&lt;strong&gt;2. Sigma Software&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sigma Software Group is a 20+ year-old IT partner (originally from Ukraine, now headquartered in Sweden) recognized on IAOP's World's Top 100 Outsourcing list. Its newer AI practice focuses specifically on applying AI across the software development lifecycle itself coding, testing, refactoring alongside building AI-powered products and agentic workflows for clients.&lt;/p&gt;

&lt;p&gt;Best for: Enterprises that want an established outsourcing partner already running structured, human in the loop AI adoption pilots, not a startup experimenting for the first time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.accenture.com/in-en" rel="noopener noreferrer"&gt;&lt;strong&gt;3. Accenture&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Accenture is one of the largest global consulting and technology services firms, with a substantial enterprise AI practice spanning strategy, implementation, and managed services across virtually every industry. For LangChain-based projects, that means access to deep pockets of specialized talent and established governance frameworks at enterprise consulting scale and pricing.&lt;/p&gt;

&lt;p&gt;Best for: Large enterprises that need AI development bundled with broader digital-transformation strategy and change management.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.n-ix.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;4. N-iX&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;N-iX is a 24 year old Eastern European engineering firm (2,400+ engineers) that positions itself around what it calls "Pragmatic AI Software Engineering" measuring what AI tools actually deliver on a client's codebase before scaling them, rather than adopting AI for its own sake. It holds AWS AI Services Competency and partners with Google Cloud, Palantir, and Snowflake, and publishes concrete before/after metrics from its AI rollouts.&lt;/p&gt;

&lt;p&gt;Best for: Enterprises that want AI development decisions backed by measured engineering outcomes, not vendor hype.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.lunarlogic.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;5. Lunar Logic&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lunar Logic is a small (roughly 30-person), product-focused agile software house based in Kraków, working in Ruby on Rails, Elixir, React, and mobile. It's built around a flat, transparent operating structure with no fixed management layer, and a strong emphasis on validating product ideas UX research, prototyping, feasibility before committing to a full build.&lt;/p&gt;

&lt;p&gt;Best for: Startups that want a small, senior, highly collaborative team for a scoped LLM-powered product rather than a large offshore bench.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.turing.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;6. Turing&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Turing isn't a traditional dev shop it's an AI-powered talent cloud that sources, vets, and matches remote engineers (including AI/ML specialists) to companies like OpenAI, Coinbase, and Salesforce, drawing from a database of millions of developers worldwide. For LangChain work specifically, that means you're hiring individually vetted engineers into your own team structure rather than contracting an agency for a fixed-scope project.&lt;/p&gt;

&lt;p&gt;Best for: Companies that want to augment an in-house team with individual, pre-vetted AI engineers rather than outsource the whole build.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.savvyapps.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;7. Savvy Apps&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Savvy Apps is a US-based mobile and web design/development agency (founded 2009, acquired by Globant in 2020) with a long client list including Levi's, Toyota, and PBS, and design-industry recognition including a Webby Award and an Apple Editor's Choice. It's a product design first shop rather than an AI specialist, but that design discipline matters for LLM-powered apps where the conversational UX is as important as the backend chain logic.&lt;/p&gt;

&lt;p&gt;Best for: Teams that want strong product design and UX craftsmanship wrapped around an AI feature, not just backend orchestration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://indatalabs.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;8. InData Labs&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;InData Labs is a dedicated AI and data science consultancy (founded 2014, Cyprus-headquartered) with over a decade of focus specifically on machine learning, NLP, computer vision, and more recently generative AI, RAG systems, and AI agents. Unlike most companies on this list, AI is the entire business rather than one service line layered on top of general software development.&lt;/p&gt;

&lt;p&gt;Best for: Teams that want a partner whose core expertise is AI/data science itself, not a generalist dev shop offering AI as an add-on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://andersenlab.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;9. Andersen&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Andersen is a large (3,700+ employee) global software development company with development centers across Europe, the US, and the Middle East, and a formal "AI-native" delivery practice that embeds AI tools into its own SDLC requirements analysis, architecture documentation, test generation while also building custom AI solutions for clients. It's completed 120+ AI projects across industries.&lt;/p&gt;

&lt;p&gt;Best for: Enterprises wanting a large, established vendor with both AI product delivery and AI-augmented internal processes to speed up the build itself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://valor-software.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;10. Valor Software&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Valor Software is a frontend-focused development consultancy, well known in the Angular community since 2013 as the creator of the popular ngx-bootstrap library, with growing depth in Vue.js and React as well. Its more recent work includes AI-powered features personalized recommendations, conversational AI components, RAG and vector-search integrations built on top of its existing frontend and product engineering strength.&lt;/p&gt;

&lt;p&gt;Best for: Teams building a LangChain-powered feature into an existing Angular, Vue, or React product who want frontend expertise as strong as the AI backend.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A few quick filters to decide faster&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Want AI as the core specialty, not an add-on? InData Labs, whose entire practice is AI and data science.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Need enterprise-scale delivery with governance and change management? Accenture or Andersen.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Want measured, metrics-driven AI adoption over hype? N-iX, which publishes concrete before/after engineering results.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Building a small, scoped product and want a lean senior team? Lunar Logic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Want to hire individual AI engineers into your own team instead of outsourcing the whole build? Turing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Already have a frontend stack (Angular/Vue/React) and need AI features bolted on? Valor Software.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Need strong product design/UX around the AI feature, not just backend logic? Savvy Apps.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;"LangChain development company" isn't really its own category it's a specific skill sitting inside a broader spectrum, from dedicated AI/data-science consultancies to large enterprise IT firms to lean, design-focused product studios that happen to build AI features well. The right pick depends less on who name-drops LangChain in their marketing and more on whether their broader engineering, design, or AI-strategy strengths match what your project actually needs around the LLM logic itself.&lt;/p&gt;

&lt;p&gt;If you're evaluating partners for your team, start with 1–2 from this list based on the kind of project you're running, trial them on a real (but low-risk) piece of the build, and see how much of the LangChain and RAG complexity they actually take off your plate over the next 30 days.&lt;/p&gt;

&lt;p&gt;👉 Browse and compare more tools at &lt;a href="https://findalternatives.net/" rel="noopener noreferrer"&gt;Find Alternatives&lt;/a&gt; 📩 Got a tool to suggest or a correction to flag? &lt;a href="https://findalternatives.net/contact" rel="noopener noreferrer"&gt;Contact us here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Which of these have you worked with or who else belongs on this list? Drop it in the comments 👇&lt;/p&gt;

</description>
      <category>langchain</category>
      <category>development</category>
    </item>
    <item>
      <title>How to Build a Voice Agent with LangChain?</title>
      <dc:creator>Ciphernutz</dc:creator>
      <pubDate>Thu, 13 Aug 2026 08:16:55 +0000</pubDate>
      <link>https://dev.to/ciphernutz/how-to-build-a-voice-agent-with-langchain-1cjl</link>
      <guid>https://dev.to/ciphernutz/how-to-build-a-voice-agent-with-langchain-1cjl</guid>
      <description>&lt;h1&gt;
  
  
  How to Build a Voice Agent with LangChain: Architecture, Streaming, Tools, and Production Patterns
&lt;/h1&gt;

&lt;p&gt;Building a voice agent is not simply a matter of connecting speech-to-text to an LLM and adding text-to-speech.&lt;/p&gt;

&lt;p&gt;A production voice agent has to solve a harder problem:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do you make an AI system listen, reason, use tools, remember context, and respond quickly enough that the conversation still feels natural?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;LangChain can handle the agent and tool-orchestration layer, but the realtime experience depends heavily on what happens around it.&lt;/p&gt;

&lt;p&gt;A practical architecture looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User microphone
      ↓
Audio streaming
      ↓
Speech-to-Text (STT)
      ↓
Transcript / turn detection
      ↓
LangChain Agent
      ↓
Tools / APIs / Business Logic
      ↓
Streaming response
      ↓
Text-to-Speech (TTS)
      ↓
User hears response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;LangChain's current voice-agent documentation describes this as the &lt;strong&gt;"sandwich" architecture&lt;/strong&gt;: STT → agent → TTS. The advantage is that each layer can be replaced independently, while the agent can continue using the broader LangChain ecosystem.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You Actually Need to Build
&lt;/h2&gt;

&lt;p&gt;Before writing code, separate the voice agent into five responsibilities:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Audio transport&lt;/strong&gt; — moves microphone audio to the backend and audio responses back to the client.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Speech recognition&lt;/strong&gt; — converts audio into text.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent reasoning&lt;/strong&gt; — decides what the user wants and what action to take.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool execution&lt;/strong&gt; — interacts with databases, CRMs, calendars, APIs, or internal systems.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Speech synthesis&lt;/strong&gt; — converts the response back into audio.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This separation matters because these components have different performance characteristics.&lt;/p&gt;

&lt;p&gt;For example, changing your TTS provider should not require rewriting your business logic. Similarly, changing the LLM should not require rebuilding your audio transport.&lt;/p&gt;

&lt;p&gt;That modularity is one of the strongest reasons to use a cascaded architecture instead of putting everything into one model.&lt;/p&gt;

&lt;h1&gt;
  
  
  1. Choose the Voice Architecture First
&lt;/h1&gt;

&lt;p&gt;There are two major ways to build a voice agent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Architecture A: STT → Agent → TTS
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Audio
  ↓
STT
  ↓
Text
  ↓
LangChain Agent
  ↓
Text
  ↓
TTS
  ↓
Audio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives you control over every component.&lt;/p&gt;

&lt;p&gt;You can choose one STT provider, another LLM, and a completely different TTS provider.&lt;/p&gt;

&lt;p&gt;It also makes debugging easier because you can inspect the transcript, agent decision, tool call, and final response independently.&lt;/p&gt;

&lt;p&gt;The trade-off is additional infrastructure and potential latency.&lt;/p&gt;

&lt;h3&gt;
  
  
  Architecture B: Speech-to-Speech
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Audio
  ↓
Multimodal Voice Model
  ↓
Audio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can reduce the number of moving pieces and can preserve more information about how something was spoken, such as tone.&lt;/p&gt;

&lt;p&gt;However, it can reduce your control over individual components and introduce provider-specific constraints.&lt;/p&gt;

&lt;p&gt;For business applications where tool execution, observability, provider flexibility, and deterministic workflows matter, the cascaded architecture remains highly practical.&lt;/p&gt;

&lt;h1&gt;
  
  
  2. Use Streaming Instead of Waiting for Complete Responses
&lt;/h1&gt;

&lt;p&gt;This is where many voice-agent implementations go wrong.&lt;br&gt;
A naive implementation waits for the entire chain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Record entire sentence
       ↓
Transcribe
       ↓
Wait for complete LLM response
       ↓
Generate complete audio
       ↓
Play response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The user experiences one long delay.&lt;br&gt;
A streaming architecture instead looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Audio chunk
   ↓
STT starts immediately
   ↓
Transcript arrives
   ↓
Agent starts generating
   ↓
First response tokens arrive
   ↓
TTS starts
   ↓
Audio starts playing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The system does not wait for every stage to finish before the next stage begins.&lt;/p&gt;

&lt;p&gt;LangChain's official voice-agent example uses asynchronous streaming and &lt;code&gt;RunnableGenerator&lt;/code&gt; to connect STT, the agent, and TTS. The documentation notes that this pipeline can achieve sub-700 ms latency with suitable STT and TTS providers.&lt;/p&gt;

&lt;p&gt;The important lesson is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Realtime voice is primarily a pipeline-design problem, not just a model-selection problem.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Research on realtime voice agents similarly identifies streaming and pipelining across STT, LLM, and TTS as a central mechanism for reducing perceived latency.&lt;/p&gt;

&lt;h1&gt;
  
  
  3. Create the LangChain Agent
&lt;/h1&gt;

&lt;p&gt;Once speech has been converted into text, the voice layer can hand the request to a normal LangChain agent.&lt;/p&gt;

&lt;p&gt;Current LangChain applications use &lt;code&gt;create_agent&lt;/code&gt; as the primary entry point.&lt;/p&gt;

&lt;p&gt;A minimal agent can look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.agents&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_agent&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check_order_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Return the current status of an order.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Order &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;order_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; is currently being processed.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;openai:gpt-5.4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;check_order_status&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;system_prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    You are a customer support voice agent.

    Keep spoken responses short.
    Ask for missing information instead of guessing.
    Use tools whenever the user asks for account-specific information.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important part is not the five lines of code.&lt;/p&gt;

&lt;p&gt;It is the &lt;strong&gt;tool boundary&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A voice agent should not directly manipulate your database or business systems through arbitrary model-generated text.&lt;/p&gt;

&lt;p&gt;Instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User:
"Where is order 4821?"

       ↓

Agent

       ↓

check_order_status("4821")

       ↓

Business system

       ↓

Structured result

       ↓

Agent

       ↓

"Your order is currently being processed."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;LangChain agents can reason over available tools and execute them as part of the agent loop. The current agent implementation is built on LangGraph's runtime.&lt;/p&gt;

&lt;h1&gt;
  
  
  4. Design Tools for Voice, Not Just for Chat
&lt;/h1&gt;

&lt;p&gt;This is an overlooked part of voice-agent engineering.&lt;/p&gt;

&lt;p&gt;A tool that works well for a text chatbot may be poorly designed for a voice agent.&lt;/p&gt;

&lt;p&gt;For example, avoid giving the agent a tool that returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"customer_id": 1827,
 "subscription_status": "active",
 "plan": "enterprise",
 "billing_cycle": "annual",
 "last_payment": "...",
 "payment_method": "..."}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;if the only thing the user asked was:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Is my subscription active?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead, make the tool return information that the agent can quickly reason over.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_subscription_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Check whether a customer&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s subscription is active.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The voice agent can then respond:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Yes, your subscription is active."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The rule is simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Design tools around decisions, not database tables.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This reduces unnecessary reasoning and makes spoken responses easier to control.&lt;/p&gt;

&lt;h1&gt;
  
  
  5. Keep Spoken Responses Short
&lt;/h1&gt;

&lt;p&gt;A language model optimized for written chat can produce paragraphs.&lt;/p&gt;

&lt;p&gt;A voice agent should not.&lt;/p&gt;

&lt;p&gt;Compare:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chatbot response:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Certainly. I can help you with that. According to the information available in your account, your order has been processed successfully and is currently in transit. You can expect delivery within the next two to three business days..."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Voice response:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Your order is in transit. It should arrive within two to three business days."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Voice requires a different response policy.&lt;/p&gt;

&lt;p&gt;A useful system instruction is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are a voice assistant.

Speak naturally and concisely.

Prefer one or two sentences per response.
Do not read JSON, URLs, IDs, tables, or long lists aloud.

Ask one question at a time.
If a tool fails, explain the problem briefly and offer the next action.

Never invent information that is unavailable from a tool.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is not merely prompt optimization.&lt;br&gt;
It is &lt;strong&gt;interface design&lt;/strong&gt;.&lt;/p&gt;
&lt;h1&gt;
  
  
  6. Add Conversation Memory Carefully
&lt;/h1&gt;

&lt;p&gt;Voice conversations become awkward if the agent forgets what was said five seconds earlier.&lt;/p&gt;

&lt;p&gt;Consider:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;User: "I want to book an appointment tomorrow."&lt;br&gt;
Agent: "What time?"&lt;br&gt;
User: "Around 4."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Please ensure the agent understands that "4" refers to the appointment.&lt;/p&gt;

&lt;p&gt;LangChain's voice-agent example uses conversation state with a checkpointer and a unique thread ID so the agent can retain context across turns.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User
 ↓
Voice session ID
 ↓
Conversation state
 ↓
LangChain agent
 ↓
Response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a production system, distinguish between:&lt;/p&gt;

&lt;h3&gt;
  
  
  Short-term conversation state
&lt;/h3&gt;

&lt;p&gt;Things said during the current call.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;user's name&lt;/li&gt;
&lt;li&gt;requested appointment time&lt;/li&gt;
&lt;li&gt;current order number&lt;/li&gt;
&lt;li&gt;selected product&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Long-term business memory
&lt;/h3&gt;

&lt;p&gt;Information that should survive the call.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;customer preferences&lt;/li&gt;
&lt;li&gt;previous interactions&lt;/li&gt;
&lt;li&gt;account information&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not put every piece of customer data into the LLM's conversation history.&lt;/p&gt;

&lt;p&gt;Retrieve what is needed for the current decision.&lt;/p&gt;

&lt;h1&gt;
  
  
  7. Handle Interruptions
&lt;/h1&gt;

&lt;p&gt;This is one of the biggest differences between a chatbot and a voice agent.&lt;/p&gt;

&lt;p&gt;Imagine the agent is saying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Your appointment is scheduled for Thursday at—"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The user interrupts:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Actually, make that Friday."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A real voice interface should stop speaking.&lt;/p&gt;

&lt;p&gt;That means your system needs to support &lt;strong&gt;barge-in&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A simplified flow is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Agent speaking
      ↓
User starts talking
      ↓
Detect interruption
      ↓
Stop TTS playback
      ↓
Cancel/ignore remaining audio
      ↓
Process new user input
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without interruption handling, the system feels less like a conversation and more like an IVR reading a script.&lt;/p&gt;

&lt;p&gt;This is why audio transport, turn detection, and cancellation logic are just as important as the LLM.&lt;/p&gt;

&lt;h1&gt;
  
  
  8. Use WebSockets for Browser-Based Streaming
&lt;/h1&gt;

&lt;p&gt;For a browser-based implementation, WebSockets are a practical transport layer.&lt;/p&gt;

&lt;p&gt;The client captures microphone audio:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Browser microphone
       ↓
PCM audio chunks
       ↓
WebSocket
       ↓
Backend
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The backend sends synthesized audio back through the same connection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Backend
   ↓
TTS audio chunks
   ↓
WebSocket
   ↓
Browser
   ↓
Speaker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;LangChain's reference voice application uses WebSockets for bidirectional audio streaming and notes that the same general architecture can be adapted to telephony or WebRTC.&lt;/p&gt;

&lt;p&gt;The important design decision is to keep the transport layer independent from the agent.&lt;/p&gt;

&lt;p&gt;Your agent should not care whether the request came from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a browser&lt;/li&gt;
&lt;li&gt;a mobile application&lt;/li&gt;
&lt;li&gt;a phone call&lt;/li&gt;
&lt;li&gt;a WebRTC client&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It should receive an input event and return agent events.&lt;/p&gt;

&lt;h1&gt;
  
  
  9. Connect the Pieces with an Async Pipeline
&lt;/h1&gt;

&lt;p&gt;A simplified LangChain pipeline can conceptually look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_core.runnables&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;RunnableGenerator&lt;/span&gt;

&lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;RunnableGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stt_stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;RunnableGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;agent_stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;RunnableGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tts_stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each stage consumes and produces a stream.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;STT events
    ↓
Agent events
    ↓
TTS events
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is more useful than treating the voice agent as one giant function.&lt;/p&gt;

&lt;p&gt;Each stage can be measured independently.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Audio received
     ↓
STT first transcript       180 ms
     ↓
Agent first token          220 ms
     ↓
TTS first audio            160 ms
     ↓
User hears response       ~560 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These measurements tell you where the actual bottleneck is.&lt;/p&gt;

&lt;h1&gt;
  
  
  10. Measure the Right Latency
&lt;/h1&gt;

&lt;p&gt;Do not measure only total API response time.&lt;/p&gt;

&lt;p&gt;For voice systems, track at least:&lt;/p&gt;

&lt;h3&gt;
  
  
  Time to first transcript
&lt;/h3&gt;

&lt;p&gt;How quickly does the system understand the user's speech?&lt;/p&gt;

&lt;h3&gt;
  
  
  Time to first token
&lt;/h3&gt;

&lt;p&gt;How quickly does the agent begin responding?&lt;/p&gt;

&lt;h3&gt;
  
  
  Time to first audio
&lt;/h3&gt;

&lt;p&gt;How quickly does the user hear the response?&lt;/p&gt;

&lt;h3&gt;
  
  
  Total response duration
&lt;/h3&gt;

&lt;p&gt;How long does the agent take to finish speaking?&lt;/p&gt;

&lt;h3&gt;
  
  
  Tool latency
&lt;/h3&gt;

&lt;p&gt;How long do external API calls take?&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User finishes speaking
        │
        ├── STT: 210 ms
        │
        ├── Agent starts: 35 ms
        │
        ├── CRM API: 420 ms
        │
        ├── LLM first token: 180 ms
        │
        └── TTS first audio: 140 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your first-audio latency is 1.2 seconds, changing the LLM may not solve the problem if the real bottleneck is a 700 ms CRM API.&lt;/p&gt;

&lt;h1&gt;
  
  
  11. Make External Tools Fast
&lt;/h1&gt;

&lt;p&gt;Voice agents expose slow backend systems immediately.&lt;/p&gt;

&lt;p&gt;Imagine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Voice input
 ↓
Agent
 ↓
CRM
 ↓
Database
 ↓
Payment API
 ↓
Agent
 ↓
TTS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even if your LLM is extremely fast, the conversation can feel slow because of downstream services.&lt;/p&gt;

&lt;p&gt;Use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;timeouts&lt;/li&gt;
&lt;li&gt;retries where safe&lt;/li&gt;
&lt;li&gt;caching&lt;/li&gt;
&lt;li&gt;parallel API requests where possible&lt;/li&gt;
&lt;li&gt;lightweight tool responses&lt;/li&gt;
&lt;li&gt;asynchronous execution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, if the agent needs customer information and appointment availability, those lookups may not always need to happen sequentially.&lt;/p&gt;

&lt;p&gt;But be careful with parallel execution when tools have side effects.&lt;/p&gt;

&lt;p&gt;Reading two systems in parallel is very different from creating two appointments simultaneously.&lt;/p&gt;

&lt;h1&gt;
  
  
  12. Add Failure Handling Before Production
&lt;/h1&gt;

&lt;p&gt;Voice agents fail differently from chatbots.&lt;/p&gt;

&lt;p&gt;Potential failures include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;STT misses a word&lt;/li&gt;
&lt;li&gt;user speaks over the agent&lt;/li&gt;
&lt;li&gt;network drops&lt;/li&gt;
&lt;li&gt;TTS fails&lt;/li&gt;
&lt;li&gt;tool times out&lt;/li&gt;
&lt;li&gt;LLM generates an invalid tool argument&lt;/li&gt;
&lt;li&gt;user changes their request halfway through&lt;/li&gt;
&lt;li&gt;external API returns incomplete data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent should have explicit fallback behavior.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tool timeout
     ↓
Retry if operation is safe
     ↓
Still failing?
     ↓
Tell the user
     ↓
Offer alternative action
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Never let the model hide a failed transaction by pretending it succeeded.&lt;/p&gt;

&lt;p&gt;For actions such as payments, bookings, cancellations, or account changes, the system should verify the actual backend result before confirming completion.&lt;/p&gt;

&lt;h1&gt;
  
  
  13. Where LangChain Helps — and Where It Doesn't
&lt;/h1&gt;

&lt;p&gt;LangChain is useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;agent orchestration&lt;/li&gt;
&lt;li&gt;tool calling&lt;/li&gt;
&lt;li&gt;model abstraction&lt;/li&gt;
&lt;li&gt;conversation state&lt;/li&gt;
&lt;li&gt;streaming agent output&lt;/li&gt;
&lt;li&gt;integrating business tools&lt;/li&gt;
&lt;li&gt;connecting the agent to LangGraph-based workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But LangChain is not your complete voice infrastructure.&lt;/p&gt;

&lt;p&gt;You still need to solve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;microphone capture&lt;/li&gt;
&lt;li&gt;audio encoding&lt;/li&gt;
&lt;li&gt;WebSockets/WebRTC&lt;/li&gt;
&lt;li&gt;speech recognition&lt;/li&gt;
&lt;li&gt;voice synthesis&lt;/li&gt;
&lt;li&gt;interruption handling&lt;/li&gt;
&lt;li&gt;latency management&lt;/li&gt;
&lt;li&gt;telephony integration, if applicable&lt;/li&gt;
&lt;li&gt;production monitoring&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of LangChain as the &lt;strong&gt;reasoning and orchestration layer&lt;/strong&gt;, not the entire voice stack.&lt;/p&gt;

&lt;h1&gt;
  
  
  14. When LangGraph Becomes Important
&lt;/h1&gt;

&lt;p&gt;A simple voice assistant might only need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User → Agent → Tool → Response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A business workflow can become more complicated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Incoming call
      ↓
Identify customer
      ↓
Understand intent
      ↓
Check account
      ↓
Determine eligibility
      ↓
Call external system
      ↓
Human approval?
   ↙       ↘
 Yes        No
 ↓           ↓
Human       Complete
review
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is where graph-based orchestration becomes valuable.&lt;/p&gt;

&lt;p&gt;LangChain's current &lt;code&gt;create_agent&lt;/code&gt; implementation already uses LangGraph underneath, while direct LangGraph workflows are useful when you need more explicit control over state, branching, persistence, interrupts, or complex workflows.&lt;/p&gt;

&lt;p&gt;The important point is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do not add LangGraph simply because you are building a voice agent. Add graph-level orchestration when the workflow actually needs it.&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  15. A Production Voice Agent Architecture
&lt;/h1&gt;

&lt;p&gt;A practical production architecture could look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                    ┌──────────────────┐
                    │   Web / Mobile   │
                    │  / Phone Client  │
                    └────────┬─────────┘
                             │
                       Audio Stream
                             │
                             ▼
                    ┌──────────────────┐
                    │  Audio Gateway   │
                    │ WebSocket/WebRTC │
                    └────────┬─────────┘
                             │
                             ▼
                    ┌──────────────────┐
                    │       STT        │
                    └────────┬─────────┘
                             │
                          Transcript
                             │
                             ▼
                    ┌──────────────────┐
                    │ LangChain Agent  │
                    │                  │
                    │ State + Tools    │
                    └───────┬──────────┘
                            │
                ┌───────────┼───────────┐
                ▼           ▼           ▼
             CRM/API    Database    Calendar
                │           │           │
                └───────────┼───────────┘
                            │
                            ▼
                    Agent Response
                            │
                            ▼
                    ┌──────────────────┐
                    │       TTS        │
                    └────────┬─────────┘
                             │
                             ▼
                       Audio Stream
                             │
                             ▼
                            User
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This architecture has an important property:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Every layer can evolve independently.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can replace the STT provider without rebuilding the agent.&lt;br&gt;
You can replace the LLM without rebuilding the audio gateway.&lt;/p&gt;

&lt;p&gt;You can replace the CRM without changing the voice interface.&lt;br&gt;
That is what makes the architecture suitable for production.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Building a voice agent with LangChain is not primarily about writing an LLM prompt.&lt;/p&gt;

&lt;p&gt;The difficult engineering work is around the LLM:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;streaming audio&lt;/li&gt;
&lt;li&gt;reducing time-to-first-audio&lt;/li&gt;
&lt;li&gt;managing conversation state&lt;/li&gt;
&lt;li&gt;designing voice-specific tools&lt;/li&gt;
&lt;li&gt;handling interruptions&lt;/li&gt;
&lt;li&gt;controlling external API latency&lt;/li&gt;
&lt;li&gt;validating side effects&lt;/li&gt;
&lt;li&gt;recovering from failures&lt;/li&gt;
&lt;li&gt;monitoring complete conversations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;LangChain gives you a strong agent and tool-orchestration layer, while the voice infrastructure handles the real-time UI interface. Its current documentation demonstrates this separation through a streaming STT → LangChain agent → TTS architecture.&lt;/p&gt;

&lt;p&gt;If you’re planning to take this architecture beyond a prototype and build a production-ready voice system with custom workflows, backend integrations, multilingual support, monitoring, and low-latency interactions, explore Ciphernutz’s AI Voice Agent Development services.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The goal is not to make an LLM speak. The goal is to make a business workflow conversational without making it unreliable.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>langchain</category>
      <category>voiceagent</category>
      <category>ai</category>
      <category>llm</category>
    </item>
    <item>
      <title>Build a Profitable AI Agent with LangChain: A Step-by-Step Tutorial</title>
      <dc:creator>Caper B</dc:creator>
      <pubDate>Wed, 12 Aug 2026 18:22:59 +0000</pubDate>
      <link>https://dev.to/caper_dev/build-a-profitable-ai-agent-with-langchain-a-step-by-step-tutorial-4i62</link>
      <guid>https://dev.to/caper_dev/build-a-profitable-ai-agent-with-langchain-a-step-by-step-tutorial-4i62</guid>
      <description>&lt;h1&gt;
  
  
  Build a Profitable AI Agent with LangChain: A Step-by-Step Tutorial
&lt;/h1&gt;

&lt;p&gt;LangChain is a powerful framework for building AI agents that can interact with the world in various ways. In this tutorial, we'll explore how to build an AI agent that can earn money by automating tasks and providing value to users. We'll cover the technical aspects of building the agent, as well as the monetization strategies to make it profitable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Setting up LangChain
&lt;/h2&gt;

&lt;p&gt;To get started with LangChain, you'll need to install the &lt;code&gt;langchain&lt;/code&gt; library using pip:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;langchain
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once installed, you can import the library and create a new LangChain agent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;langchain&lt;/span&gt;

&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;langchain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;LLMLAgent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Defining the Agent's Capabilities
&lt;/h2&gt;

&lt;p&gt;Next, you'll need to define the capabilities of your AI agent. This can include tasks such as text generation, language translation, or data analysis. For this example, let's say we want our agent to generate affiliate marketing content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_capability&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text_generation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;langchain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;TextGenerationCapability&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Integrating with Affiliate Marketing Platforms
&lt;/h2&gt;

&lt;p&gt;To monetize our agent, we'll need to integrate it with an affiliate marketing platform. Let's use the Amazon Associates API as an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;amazon_api&lt;/span&gt;

&lt;span class="n"&gt;amazon_api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;amazon_api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AmazonAPI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_API_SECRET&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_capability&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;affiliate_marketing&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;langchain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AffiliateMarketingCapability&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amazon_api&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Training the Agent
&lt;/h2&gt;

&lt;p&gt;To train our agent, we'll need to provide it with a dataset of examples. For this example, let's use a dataset of product reviews:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;

&lt;span class="n"&gt;reviews&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;product_reviews.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;train&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reviews&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text_generation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Deploying the Agent
&lt;/h2&gt;

&lt;p&gt;Once our agent is trained, we can deploy it to a cloud platform such as AWS or Google Cloud. Let's use AWS Lambda as an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;aws_lambda&lt;/span&gt;

&lt;span class="n"&gt;aws_lambda&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;aws_lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AWSLambda&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_AWS_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_AWS_SECRET&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;aws_lambda&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Monetization Strategies
&lt;/h2&gt;

&lt;p&gt;Now that our agent is deployed, let's discuss some monetization strategies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Affiliate marketing&lt;/strong&gt;: Our agent can generate affiliate marketing content and earn commissions for each sale made through its unique referral link.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sponsored content&lt;/strong&gt;: Our agent can generate sponsored content for brands and earn revenue for each piece of content created.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data analysis&lt;/strong&gt;: Our agent can analyze data for clients and earn revenue for its insights and recommendations.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Example Use Case
&lt;/h2&gt;

&lt;p&gt;Let's say we want our agent to generate affiliate marketing content for a new product launch. We can use the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;New Product&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;This is a new product&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;affiliate_marketing&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This would output a piece of affiliate marketing content that our agent can use to promote the product and earn commissions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this tutorial, we've built a profitable AI agent using LangChain that can earn money by automating tasks and providing value to users. We've covered the technical aspects of building the agent, as well as the monetization strategies to make it profitable. By following these steps and using the code examples provided, you can build your own AI agent and start earning money today.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Get started with LangChain today and start building your own profitable AI agent!&lt;/strong&gt; &lt;a href="https://langchain.dev/" rel="noopener noreferrer"&gt;Sign up for a free trial&lt;/a&gt; and start exploring the possibilities of AI-powered automation.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>langchain</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>LCEL vs. Legacy Chains: From Recipe Confusion to Clear Pipelines 🚀</title>
      <dc:creator>Charles Uwagbale</dc:creator>
      <pubDate>Wed, 12 Aug 2026 01:02:56 +0000</pubDate>
      <link>https://dev.to/anetor/-lcel-vs-legacy-chains-from-recipe-confusion-to-clear-pipelines-3f</link>
      <guid>https://dev.to/anetor/-lcel-vs-legacy-chains-from-recipe-confusion-to-clear-pipelines-3f</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Legacy Chains are the old way—rigid, class-heavy, and frustrating. LCEL is the new standard—visual, modular, and future-proof. &lt;strong&gt;Always choose LCEL for new projects.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  😫 The Frustration (The Legacy Way)
&lt;/h2&gt;

&lt;p&gt;Building a chain in LangChain used to feel like following a recipe where every ingredient was labeled differently in every cookbook. &lt;/p&gt;

&lt;p&gt;"Add &lt;code&gt;input_documents&lt;/code&gt;"—wait, is that the same as &lt;code&gt;docs&lt;/code&gt;? What about &lt;code&gt;context&lt;/code&gt;? And why does this chain expect &lt;code&gt;llm&lt;/code&gt; but that one expects &lt;code&gt;model&lt;/code&gt;?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🧠 You had to memorize specific class names (&lt;code&gt;LLMChain&lt;/code&gt;, &lt;code&gt;ConversationChain&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;🙏 You prayed your inputs matched the variable names perfectly (&lt;code&gt;input_documents&lt;/code&gt; vs. &lt;code&gt;docs&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;🐛 Debugging meant printing variables mid-way through.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🏛️ What is the Legacy Chain?
&lt;/h2&gt;

&lt;p&gt;It is the "Old Class Way." You tell the computer &lt;em&gt;how&lt;/em&gt; to store memory and &lt;em&gt;how&lt;/em&gt; to loop. You create an object, pass parameters to its constructor, and call &lt;code&gt;.run()&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚡ What is LCEL?
&lt;/h2&gt;

&lt;p&gt;It is the "New Pipe Way." You tell the computer &lt;em&gt;what&lt;/em&gt; the flow is—LCEL optimizes the &lt;em&gt;how&lt;/em&gt; for you. You define a sequence using the &lt;code&gt;|&lt;/code&gt; symbol, like an assembly line where each component passes its output to the next.&lt;/p&gt;

&lt;h2&gt;
  
  
  💡 The "Aha!" Moment
&lt;/h2&gt;

&lt;p&gt;LCEL fixes this by treating your workflow like a &lt;strong&gt;plumbing pipe&lt;/strong&gt;—no more guesswork, just clear connections. You connect sections together using the &lt;code&gt;|&lt;/code&gt; (pipe) operator. Data flows in one end and comes out the other. No magic, just plumbing.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚔️ Side-by-Side Showdown
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Legacy (Old):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.chains&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;LLMChain&lt;/span&gt;
&lt;span class="n"&gt;chain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LLMChain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;LCEL(New):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_core.output_parsers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StrOutputParser&lt;/span&gt;
&lt;span class="n"&gt;chain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;StrOutputParser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Notice the difference? No class names to memorize. No guessing about method names. Just a visual pipeline that reads like a recipe.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;😱The Composability Nightmare (Legacy)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine you have a chatbot that answers questions from documents. In Legacy, you'd write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.chains&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;RetrievalQA&lt;/span&gt;
&lt;span class="c1"&gt;# One class for retrieval...
&lt;/span&gt;&lt;span class="n"&gt;retrieval_chain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RetrievalQA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_chain_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;retriever&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;retriever&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now imagine you want to:&lt;/p&gt;

&lt;p&gt;📝 Add a summarization step?&lt;/p&gt;

&lt;p&gt;📊 Log every prompt to a database?&lt;/p&gt;

&lt;p&gt;🧠 Route questions to different models based on complexity?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In Legacy, each change required rewriting the entire class or hunting for a specific subclass&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🧱The Composability Paradise (LCEL)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In LCEL, everything is a LEGO brick. Need to add a summarizer? | it in. Want to log prompts? | a logger between the prompt and the LLM.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# LCEL: Mix, match, and extend
&lt;/span&gt;&lt;span class="n"&gt;chain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;retriever&lt;/span&gt; 
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt; 
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;logging_middleware&lt;/span&gt;   &lt;span class="c1"&gt;# Your custom step!
&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt; 
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;summarizer&lt;/span&gt;           &lt;span class="c1"&gt;# Another custom step!
&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;output_parser&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The magic&lt;/strong&gt;: Every component in LCEL uses the same interface. That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;🔄 You can reuse any chain inside another chain.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🌿 You can branch into parallel chains.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🔧 You can swap components without breaking everything.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Composability is not a feature; it's the architecture.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🏆 The 4 Core Upgrades
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;👀 Explicit over Implicit: LCEL shows the data flow visually. No more guessing what goes where.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;📡 Built-in Streaming: Legacy forces you to wait. LCEL allows chain.stream() out of the box.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🧩 Composability: In LCEL, if you can pipe it, you can chain it. Mix and match components freely.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🎯 Standardized Interface: Everything uses the same methods (.invoke(), .stream(), .batch()). Learn once, use everywhere.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ⚠️ Watch Out: The "Too Much Piping" Trap
&lt;/h2&gt;

&lt;p&gt;LCEL is powerful, but don't overdo it. A chain with 10+ pipes becomes hard to debug.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;chain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;  &lt;span class="c1"&gt;# 3 steps
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Bad:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;chain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;retriever&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;router&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;fallback&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;  &lt;span class="c1"&gt;# 8+ steps
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rule of thumb:&lt;/strong&gt; If your chain doesn't fit on one screen, split it into smaller sub-chains.&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ When to use which?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;✅ Use LCEL: For new projects, production APIs, and streaming chatbots.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;❌ Use Legacy: Only if you are patching a production bug in an old system and cannot refactor.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📚 Watch out for next article
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Runnables Explained: From Zero to Hero with .invoke(), .stream(), and .batch()&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Feedback:&lt;/strong&gt; Your opinion matters. Leave a comment with your biggest takeaway or a question you still have.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>langchain</category>
      <category>python</category>
    </item>
    <item>
      <title>Build a Profitable AI Agent with LangChain: A Step-by-Step Tutorial</title>
      <dc:creator>Caper B</dc:creator>
      <pubDate>Tue, 11 Aug 2026 10:22:33 +0000</pubDate>
      <link>https://dev.to/caper_dev/build-a-profitable-ai-agent-with-langchain-a-step-by-step-tutorial-h9l</link>
      <guid>https://dev.to/caper_dev/build-a-profitable-ai-agent-with-langchain-a-step-by-step-tutorial-h9l</guid>
      <description>&lt;h1&gt;
  
  
  Build a Profitable AI Agent with LangChain: A Step-by-Step Tutorial
&lt;/h1&gt;

&lt;p&gt;LangChain is a powerful framework for building AI agents that can interact with the world. In this tutorial, we'll show you how to create an AI agent that can earn money by automating tasks and providing value to users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before we begin, make sure you have the following installed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python 3.8+&lt;/li&gt;
&lt;li&gt;LangChain library (&lt;code&gt;pip install langchain&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;A LangChain-compatible LLM (Large Language Model) such as LLaMA or PaLM&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Set up Your LangChain Environment
&lt;/h2&gt;

&lt;p&gt;To start, you'll need to set up your LangChain environment. This involves creating a new LangChain project and configuring your LLM.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;langchain&lt;/span&gt;

&lt;span class="c1"&gt;# Create a new LangChain project
&lt;/span&gt;&lt;span class="n"&gt;project&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;langchain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Project&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;profitable_agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Configure your LLM
&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;langchain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;LLM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llama&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;model_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;7b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2048&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;top_p&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.95&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;frequency_penalty&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;presence_penalty&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Define Your Agent's Goals and Objectives
&lt;/h2&gt;

&lt;p&gt;Next, you'll need to define your agent's goals and objectives. What tasks do you want your agent to automate? What value do you want it to provide to users?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Define your agent's goals and objectives
&lt;/span&gt;&lt;span class="n"&gt;agent_goals&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Automate data entry tasks&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Provide customer support&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Generate high-quality content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Train Your Agent
&lt;/h2&gt;

&lt;p&gt;Now it's time to train your agent. You'll need to provide your agent with a dataset of examples that demonstrate the tasks you want it to automate.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Load your dataset
&lt;/span&gt;&lt;span class="n"&gt;dataset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;langchain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Train your agent
&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;langchain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;goals&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;agent_goals&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_steps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;learning_rate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Deploy Your Agent
&lt;/h2&gt;

&lt;p&gt;Once your agent is trained, you can deploy it to a production environment. You can use a cloud platform like AWS or Google Cloud to host your agent.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Deploy your agent to a cloud platform
&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;platform&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;aws&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;us-west-2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;instance_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;t2.micro&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Monetize Your Agent
&lt;/h2&gt;

&lt;p&gt;Now that your agent is deployed, you can start monetizing it. Here are a few ways you can earn money with your agent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Freemium model&lt;/strong&gt;: Offer a basic version of your agent for free and charge for premium features.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subscription model&lt;/strong&gt;: Charge users a monthly or yearly fee to access your agent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Advertising model&lt;/strong&gt;: Display ads to users and earn revenue from clicks or impressions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, you can use a library like &lt;code&gt;stripe&lt;/code&gt; to handle payments and subscriptions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;stripe&lt;/span&gt;

&lt;span class="c1"&gt;# Set up Stripe
&lt;/span&gt;&lt;span class="n"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your_stripe_api_key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# Create a payment plan
&lt;/span&gt;&lt;span class="n"&gt;plan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;month&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;currency&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;usd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your_product_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this tutorial, we showed you how to build a profitable AI agent with LangChain. By following these steps, you can create an agent that automates tasks and provides value to users. With the right monetization strategy, you can earn significant revenue with your agent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Get started today&lt;/strong&gt; and build your own profitable AI agent with LangChain. Join the LangChain community and start building your agent now. &lt;a href="https://langchain.dev/" rel="noopener noreferrer"&gt;Get started with LangChain&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>langchain</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>LangGraph Practical Guide: When to Use It Over LangChain</title>
      <dc:creator>Amrendra N Mishra</dc:creator>
      <pubDate>Tue, 11 Aug 2026 03:01:49 +0000</pubDate>
      <link>https://dev.to/amrendra_n_mishra/langgraph-practical-guide-when-to-use-it-over-langchain-2956</link>
      <guid>https://dev.to/amrendra_n_mishra/langgraph-practical-guide-when-to-use-it-over-langchain-2956</guid>
      <description>&lt;h2&gt;
  
  
  Why Automate Content Creation
&lt;/h2&gt;

&lt;p&gt;Creating content manually for 9 channels would take 8+ hours daily. I have a full-time job as VP at JPMorgan. The math doesnt work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pipeline
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Trending Topic CSV
       ↓
  AI Script (Ollama/Gemini)
       ↓
  Google Cloud TTS (Voice)
       ↓
  Pexels Images + MoviePy Video
       ↓
  YouTube API Upload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Scheduling with Mac LaunchAgents
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;plist&lt;/span&gt; &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;"1.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Label&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;com.gyaaninfive.youtube&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;ProgramArguments&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;array&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;/usr/bin/python3&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;/path/to/upload.py&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;StartCalendarInterval&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Hour&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&amp;lt;integer&amp;gt;&lt;/span&gt;18&lt;span class="nt"&gt;&amp;lt;/integer&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Minute&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&amp;lt;integer&amp;gt;&lt;/span&gt;15&lt;span class="nt"&gt;&amp;lt;/integer&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/plist&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One plist per channel. Runs at the exact scheduled time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Total Monthly Cost
&lt;/h2&gt;

&lt;p&gt;Google Cloud TTS: Free (4M chars/month)&lt;br&gt;
Pexels API: Free&lt;br&gt;
YouTube API: Free&lt;br&gt;
Ollama: Free (local)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Total: ₹0/month&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/amrendramishra/ai-tools" rel="noopener noreferrer"&gt;Full code on GitHub&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;9 channels. Daily uploads. Zero manual work.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>langchain</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Understanding the Deep Agents Interpreter with Programmatic Tool Calling</title>
      <dc:creator>Syeed Talha</dc:creator>
      <pubDate>Mon, 10 Aug 2026 08:44:46 +0000</pubDate>
      <link>https://dev.to/syeedmdtalha/understanding-the-deep-agents-interpreter-with-programmatic-tool-calling-50n8</link>
      <guid>https://dev.to/syeedmdtalha/understanding-the-deep-agents-interpreter-with-programmatic-tool-calling-50n8</guid>
      <description>&lt;p&gt;Tool calling is an important part of AI agents. It allows a model to search the web, query a database, call an API, or perform another external action.&lt;/p&gt;

&lt;p&gt;Normal tool calling works well for simple tasks. But it becomes less efficient when an agent needs to call the same tool many times, process intermediate results, or run several independent operations in parallel.&lt;/p&gt;

&lt;p&gt;This is the problem the Deep Agents interpreter solves.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the Deep Agents interpreter?
&lt;/h2&gt;

&lt;p&gt;The interpreter gives a Deep Agent a small, in-memory JavaScript environment powered by QuickJS.&lt;/p&gt;

&lt;p&gt;Instead of asking the model to manage every tool call separately, the model can write JavaScript that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Calls approved tools&lt;/li&gt;
&lt;li&gt;Runs loops&lt;/li&gt;
&lt;li&gt;Handles conditional logic&lt;/li&gt;
&lt;li&gt;Retries failed operations&lt;/li&gt;
&lt;li&gt;Runs independent calls in parallel&lt;/li&gt;
&lt;li&gt;Filters and combines results&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Only the final result of that JavaScript execution is returned to the model.&lt;/p&gt;

&lt;p&gt;In simple terms, the model decides &lt;strong&gt;what work should be done&lt;/strong&gt;, while JavaScript handles &lt;strong&gt;how the repeated work should be organized&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens without an interpreter?
&lt;/h2&gt;

&lt;p&gt;Suppose an agent needs to research three topics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Retrieval&lt;/li&gt;
&lt;li&gt;Memory&lt;/li&gt;
&lt;li&gt;Evaluation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without an interpreter, the workflow may look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Model calls the retrieval search tool
→ Model receives the result

Model calls the memory search tool
→ Model receives the result

Model calls the evaluation search tool
→ Model receives the result

Model combines all results
→ Model writes the answer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every result returns to the model before the next step can be decided.&lt;/p&gt;

&lt;p&gt;This creates several problems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;More model turns&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The model may need to repeatedly call a tool, read its output, and decide what to do next.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Larger model context&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every intermediate tool result becomes part of the model’s context, even when the result only needs to be filtered or passed to another step.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Unreliable repeated calls&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Asking a model to perform the same operation across many items does not guarantee that every item will be processed consistently.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Limited workflow control&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A normal batch of tool calls is fixed when the model creates it. The model cannot loop, retry, branch on a result, or feed one result into another call without an additional model turn.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the interpreter changes the workflow
&lt;/h2&gt;

&lt;p&gt;With an interpreter, the workflow becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Model creates one JavaScript program
→ JavaScript calls all approved tools
→ JavaScript processes and combines the results
→ Model receives one combined result
→ Model writes the final answer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For our three research topics, JavaScript can run all searches at the same time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;topics&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;retrieval&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;memory&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;evaluation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;topics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;webSearch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;query&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="nx"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; best practices`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;results&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="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Promise.all()&lt;/code&gt; runs the independent searches in parallel. The interpreter then combines the results before returning them to the model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Complete example
&lt;/h2&gt;

&lt;p&gt;The following agent searches for retrieval, memory, and evaluation best practices in parallel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dotenv&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_dotenv&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;deepagents&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_deep_agent&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.tools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tool&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_nvidia_ai_endpoints&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ChatNVIDIA&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_quickjs&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CodeInterpreterMiddleware&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;tavily&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TavilyClient&lt;/span&gt;


&lt;span class="nf"&gt;load_dotenv&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="nd"&gt;@tool&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;web_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Search the web and return a compact text summary of the results.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="c1"&gt;# Create the Tavily search client.
&lt;/span&gt;    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TavilyClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TAVILY_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Search the web and limit the response to three results.
&lt;/span&gt;    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;max_results&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Convert the search results into compact text.
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&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="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;- &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; (&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;results&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;build_agent&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Create an agent with programmatic access to web_search.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="c1"&gt;# Create the language model used by the agent.
&lt;/span&gt;    &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ChatNVIDIA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NVIDIA_MODEL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nvidia/nemotron-3-super-120b-a12b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NVIDIA_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;max_completion_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Create the Deep Agent and enable the interpreter.
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;create_deep_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;web_search&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;middleware&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="nc"&gt;CodeInterpreterMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="c1"&gt;# Allow JavaScript to call the web_search tool.
&lt;/span&gt;                &lt;span class="n"&gt;ptc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;web_search&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;

                &lt;span class="c1"&gt;# Disable dynamic subagents for this example.
&lt;/span&gt;                &lt;span class="n"&gt;subagents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;system_prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
You are a research assistant demonstrating programmatic tool calling.

For research questions, make exactly one eval tool call. Inside that one call,
write JavaScript that calls tools.webSearch({query}) rather than calling
web_search directly.

When there are several independent topics, use Promise.all to search them
in parallel. Combine the results in JavaScript and return only the combined
research notes before writing a concise answer for the user.

Never issue separate web_search calls or multiple eval calls for the same
request.
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="p"&gt;,&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;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Build the configured agent.
&lt;/span&gt;    &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;build_agent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Send a research request to the agent.
&lt;/span&gt;    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Compare current best practices for retrieval, memory, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;and evaluation in LLM applications. Search each topic &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;in parallel with the interpreter, then summarize the &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;three most useful practices and include source URLs.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Print the final response produced by the agent.
&lt;/span&gt;    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How the code works
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. The search tool
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;web_search&lt;/code&gt; function is a regular Python tool:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@tool&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;web_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It sends the query to Tavily and returns three compact search results.&lt;/p&gt;

&lt;p&gt;By itself, the agent can call this tool through normal tool calling. However, we also want the interpreter’s JavaScript code to be able to use it.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The interpreter middleware
&lt;/h3&gt;

&lt;p&gt;The interpreter is added through &lt;code&gt;CodeInterpreterMiddleware&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;middleware&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nc"&gt;CodeInterpreterMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;ptc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;web_search&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;subagents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This middleware adds an &lt;code&gt;eval&lt;/code&gt; tool to the agent. The model uses that tool to execute JavaScript inside QuickJS.&lt;/p&gt;

&lt;p&gt;You do not call &lt;code&gt;eval&lt;/code&gt; manually in the Python code. The agent decides when to use it based on the request and system prompt.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Programmatic Tool Calling
&lt;/h3&gt;

&lt;p&gt;The following option enables Programmatic Tool Calling, or PTC:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;ptc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;web_search&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is an explicit allowlist. It means the JavaScript interpreter can call &lt;code&gt;web_search&lt;/code&gt;, but it cannot automatically access every Python tool or system capability.&lt;/p&gt;

&lt;p&gt;Inside JavaScript, Python tool names are converted to camel case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;web_search → tools.webSearch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tool can therefore be called like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;webSearch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;retrieval best practices&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. The system prompt
&lt;/h3&gt;

&lt;p&gt;The system prompt tells the model to make one &lt;code&gt;eval&lt;/code&gt; call and perform the searches inside it.&lt;/p&gt;

&lt;p&gt;It also instructs the model to use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is important because retrieval, memory, and evaluation are independent topics. There is no reason to wait for one search to finish before starting the next one.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. The agent request
&lt;/h3&gt;

&lt;p&gt;The user asks the agent to research three topics:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Compare current best practices for retrieval, memory, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;and evaluation in LLM applications.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent can respond by generating JavaScript similar to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;topics&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;retrieval&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;memory&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;evaluation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;topics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;webSearch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;query&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="nx"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; best practices`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;results&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="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;QuickJS executes the JavaScript, calls the Python search tool three times, and combines the results.&lt;/p&gt;

&lt;p&gt;The model receives the combined research notes rather than three separate intermediate tool responses.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the interpreter cannot do by default
&lt;/h2&gt;

&lt;p&gt;The interpreter is an in-memory JavaScript runtime, not a complete operating-system environment.&lt;/p&gt;

&lt;p&gt;By default, it cannot directly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Access the network&lt;/li&gt;
&lt;li&gt;Read or write files&lt;/li&gt;
&lt;li&gt;Run shell commands&lt;/li&gt;
&lt;li&gt;Install packages&lt;/li&gt;
&lt;li&gt;Access system resources&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Network access in this example comes only from the allowlisted &lt;code&gt;web_search&lt;/code&gt; tool.&lt;/p&gt;

&lt;p&gt;If you need shell commands, package installation, testing, or filesystem access, a sandbox is the more appropriate option.&lt;/p&gt;

&lt;h2&gt;
  
  
  When should you use an interpreter?
&lt;/h2&gt;

&lt;p&gt;Use an interpreter when an agent needs to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Call a tool for many items&lt;/li&gt;
&lt;li&gt;Run independent calls in parallel&lt;/li&gt;
&lt;li&gt;Retry failed calls&lt;/li&gt;
&lt;li&gt;Branch based on tool results&lt;/li&gt;
&lt;li&gt;Filter or aggregate structured data&lt;/li&gt;
&lt;li&gt;Keep intermediate results out of the model context&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For one or two simple tool calls, normal tool calling is usually enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final takeaway
&lt;/h2&gt;

&lt;p&gt;The Deep Agents interpreter moves repetitive orchestration from the model into JavaScript.&lt;/p&gt;

&lt;p&gt;Without it, the model must manage more intermediate tool calls and results. With it, the agent can make one &lt;code&gt;eval&lt;/code&gt; call, execute a complete workflow, and receive only the combined result.&lt;/p&gt;

&lt;p&gt;The main pattern is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Model
→ One eval call
→ JavaScript orchestration
→ Approved Python tools
→ Combined result
→ Final answer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is especially useful for research, batch processing, data transformation, and other workflows that involve many related tool calls.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>langchain</category>
      <category>javascript</category>
    </item>
    <item>
      <title>I Built an AI Agent That Thinks Before It Answers — And Loops Back When It Doesn't Know Enough</title>
      <dc:creator>Ayush Singh Tomar</dc:creator>
      <pubDate>Mon, 10 Aug 2026 03:30:04 +0000</pubDate>
      <link>https://dev.to/ayushsinghtomar/i-built-an-ai-agent-that-thinks-before-it-answers-and-loops-back-when-it-doesnt-know-enough-39o</link>
      <guid>https://dev.to/ayushsinghtomar/i-built-an-ai-agent-that-thinks-before-it-answers-and-loops-back-when-it-doesnt-know-enough-39o</guid>
      <description>&lt;p&gt;Most AI projects look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Input → LLM → Output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's not an agent. That's autocomplete with a UI.&lt;/p&gt;

&lt;p&gt;AgentLoop is different. Give it a research topic and it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Checks if it already researched something similar (long-term memory)&lt;/li&gt;
&lt;li&gt;Breaks the topic into targeted sub-questions&lt;/li&gt;
&lt;li&gt;Decides per sub-question whether to call a live web search tool&lt;/li&gt;
&lt;li&gt;Re-reads its own notes and routes itself back into research if it finds gaps&lt;/li&gt;
&lt;li&gt;Only then writes a structured, sourced report&lt;/li&gt;
&lt;li&gt;Saves the run to memory for next time
The loop in the middle — where the agent judges its own output and decides to keep going — that's what makes it genuinely agentic. Not the LLM. The decision-making around it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Live demo:&lt;/strong&gt; &lt;a href="https://agentloop.streamlit.app" rel="noopener noreferrer"&gt;agentloop.streamlit.app&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/ayush-s-tomar/agentloop" rel="noopener noreferrer"&gt;github.com/ayush-s-tomar/agentloop&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  What It Does
&lt;/h2&gt;

&lt;p&gt;You type a research topic. The agent runs a 6-node pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Recall] → [Plan] → [Research] → [Reflect] → [Synthesize] → [Persist]
                                      ↑               |
                                      └───────────────┘
                                    (loops back if gaps found)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Recall&lt;/strong&gt; — checks SQLite long-term memory for related past research. If it finds something relevant, it loads those notes as context before planning. Avoids re-researching the same ground twice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Plan&lt;/strong&gt; — the LLM breaks the topic into 3–5 specific sub-questions. Not "tell me about X" — actual targeted questions like "what companies are deploying X in production?" and "what are the failure modes of X?"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Research&lt;/strong&gt; — for each sub-question, the LLM decides whether to call the Tavily web search tool. Not every sub-question needs a search — sometimes the answer follows from earlier notes. This is genuine tool-use, not hardcoded search-every-time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reflect&lt;/strong&gt; — the node I'm most proud of. The agent re-reads everything it's gathered and asks: &lt;em&gt;is this complete? Are there gaps?&lt;/em&gt; If yes, it routes back into Research for another loop. If no, it moves forward. Bounded at 3 iterations so it can't loop forever.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Synthesize&lt;/strong&gt; — writes a structured markdown report from all gathered notes and search results. Citations included.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Persist&lt;/strong&gt; — saves the full run to SQLite: topic, sub-questions, sources, report. Available for recall on future runs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3eo36t4ihhg3f77tw145.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3eo36t4ihhg3f77tw145.png" alt="AgentLoop LangGraph pipeline diagram — recall, plan, research, reflect, synthesize, persist" width="800" height="918"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The 6-node graph, including the reflect → research loop-back.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyy57m9i5g1n8hd89eyno.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyy57m9i5g1n8hd89eyno.png" alt="AgentLoop Streamlit UI — topic input, live trace, and generated report" width="800" height="530"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Topic input, live trace, and the generated report — all in one Streamlit view.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stack:&lt;/strong&gt; LangGraph · Streamlit · Groq (llama-3.1-8b-instant) · Tavily · SQLite · Streamlit Cloud&lt;/p&gt;


&lt;h2&gt;
  
  
  How Each Part Works
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. The Reflect Node — Conditional Loop-Back
&lt;/h3&gt;

&lt;p&gt;This is the decision that separates AgentLoop from a linear pipeline.&lt;/p&gt;

&lt;p&gt;After Research runs, instead of immediately synthesizing, the agent hits the Reflect node:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;reflect_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;notes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&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="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;notes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;sub_questions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&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="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sub_questions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;You researched these questions:
&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;sub_questions&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;

Here are your notes so far:
&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;notes&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;

Are there significant gaps? Answer YES or NO, then explain.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;([{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt; &lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Be critical.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;has_gaps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YES&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;iterations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reflect_iterations&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;needs_more_research&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;has_gaps&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;iterations&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reflect_iterations&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;iterations&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The LangGraph conditional edge routes based on &lt;code&gt;needs_more_research&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_conditional_edges&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reflect&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;research&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;needs_more_research&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;synthesize&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The iteration cap (&lt;code&gt;iterations &amp;lt; 3&lt;/code&gt;) is non-negotiable. Without it, a loop-happy LLM spins forever on ambiguous topics. With it, the worst case is 3 research passes — still far more thorough than one.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Two-Layer Memory
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Short-term (within a run):&lt;/strong&gt; &lt;code&gt;state["notes"]&lt;/code&gt; — a list that accumulates across all Research iterations. Each tool call appends its findings. The Reflect and Synthesize nodes see the full accumulated picture, not just the last search.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Long-term (across runs):&lt;/strong&gt; SQLite with a simple schema — topic, sub-questions, notes, report, timestamp. The Recall node queries this by keyword similarity at the start of every run. Not vector search (that's the next step) — just SQL LIKE matching, which is good enough for a portfolio project and dead simple to reason about.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;recall_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;topic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;topic&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;past_runs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;  &lt;span class="c1"&gt;# top 3 keywords
&lt;/span&gt;        &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search_by_keyword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;past_runs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;format_past_runs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;past_runs&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;  &lt;span class="c1"&gt;# most recent 2 matches
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory_context&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Tool-Calling — Decision Per Sub-Question
&lt;/h3&gt;

&lt;p&gt;The LLM doesn't call web search blindly. It receives the tool schema and decides per sub-question:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;TOOLS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;web_search&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Search the live web for current information&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;parameters&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;object&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;properties&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;string&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Search query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;required&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For factual sub-questions about current events, it calls the tool. For sub-questions it can reason about from existing notes, it doesn't. That's the distinction between a real agent and a search wrapper.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Broke (The Honest Part)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Render Kept Suspending the Live Demo — So I Moved to Streamlit
&lt;/h3&gt;

&lt;p&gt;The original architecture was FastAPI + React, streaming the live trace to the frontend via Server-Sent Events — each node completion fired an SSE event, the UI updated in real time.&lt;/p&gt;

&lt;p&gt;It worked perfectly locally. On Render's free tier, SSE died after 30 seconds — Render closes long-lived HTTP connections on the free plan, and a 6-node agent with multiple web searches takes longer than that. I patched around it with background tasks + polling (the frontend polling &lt;code&gt;/api/research/status/{job_id}&lt;/code&gt; every 2 seconds instead of holding a stream open), and that solved the timeout.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But the deeper problem was the platform itself.&lt;/strong&gt; Render's free web services spin down on inactivity and get suspended monthly, so the live demo link kept going cold between visitors regardless of the polling fix. That's not something you patch — it's the tier's actual model. So I migrated off FastAPI + React entirely onto a single-file Streamlit app, reusing the &lt;code&gt;agent/&lt;/code&gt; and &lt;code&gt;memory/&lt;/code&gt; modules unchanged, deployed to Streamlit Community Cloud. No backend process to suspend, no SSE-vs-polling tradeoff to manage — Streamlit re-runs the script and renders state directly on each interaction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt; design for the deployment environment, not just localhost — and sometimes the right fix isn't a smarter workaround, it's picking a host whose free-tier model actually matches how the project gets used (an occasional demo click-through, not a service that needs to stay warm).&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Model Deprecations — Three Times
&lt;/h3&gt;

&lt;p&gt;Groq deprecated models mid-development, more than once:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;llama-3.3-70b-versatile&lt;/code&gt; → deprecated&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;llama3-70b-8192&lt;/code&gt; → decommissioned&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;llama3-groq-70b-8192-tool-use-preview&lt;/code&gt; → tool-calling broken
Each one failed silently or with a cryptic error. Ended up on &lt;code&gt;llama-3.1-8b-instant&lt;/code&gt; — smaller, but stable and actively maintained.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt; never hardcode a model string. It belongs in an environment variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;MODEL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GROQ_MODEL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llama-3.1-8b-instant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One env var change, no redeployment needed when the next deprecation hits.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Rate Limits Hit During Demo Recording
&lt;/h3&gt;

&lt;p&gt;Groq's free tier is 100k tokens/day. Between development testing, debugging, and demo runs, I exhausted the quota on the same day I tried to record the LinkedIn screenshot. Two hours lost waiting for reset.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt; keep a separate Groq API key for demos. Never use the dev key for production.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Python 3.14 Broke the Old Render Build
&lt;/h3&gt;

&lt;p&gt;Back when this was still FastAPI on Render, &lt;code&gt;pydantic-core&lt;/code&gt; had no wheel for Python 3.14 — silent build failure, no clear error, just a broken deploy. The fix was one environment variable (&lt;code&gt;PYTHON_VERSION = 3.11.9&lt;/code&gt;) pinning the runtime explicitly instead of trusting the host default.&lt;/p&gt;

&lt;p&gt;It's moot now that the app is Streamlit-only with a much smaller dependency surface, but the underlying lesson traveled with the migration: pin your Python version explicitly on any host, don't trust the default.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I'd Do Differently
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Replace SQL LIKE matching with vector search.&lt;/strong&gt; Right now the Recall node finds past runs by keyword — it misses semantically similar research with different wording. ChromaDB or Supabase pgvector would fix this. It's the most meaningful upgrade this project needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Add a second tool.&lt;/strong&gt; Right now the only tool is &lt;code&gt;web_search&lt;/code&gt;. A calculator or structured data lookup would demonstrate the LLM genuinely choosing between tools — not just "search or not." That's a stronger tool-use story.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Instrument the reflect loop.&lt;/strong&gt; I don't log how often the agent actually loops back vs. goes straight to synthesis. That metric would tell me whether the reflect node is earning its latency or just adding overhead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Define the LLM interface contract on day one.&lt;/strong&gt; Half my debugging time came from &lt;code&gt;graph.py&lt;/code&gt; and &lt;code&gt;llm.py&lt;/code&gt; making different assumptions about function signatures and return types. One typed contract file written before any agent logic would have caught all of it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Live demo:&lt;/strong&gt; &lt;a href="https://agentloop.streamlit.app" rel="noopener noreferrer"&gt;agentloop.streamlit.app&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/ayush-s-tomar/agentloop" rel="noopener noreferrer"&gt;github.com/ayush-s-tomar/agentloop&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(If you bookmarked the old &lt;code&gt;agentloop.onrender.com&lt;/code&gt; link, it's retired — the app now lives on Streamlit Cloud, for the reasons above.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Type any research topic and watch the pipeline run step by step — the trace panel shows every node as it executes, so you can see exactly when the agent decides to loop back.&lt;/p&gt;

&lt;p&gt;If you're building something similar or have thoughts on the memory architecture, connect with me on &lt;a href="https://linkedin.com/in/ayushsinghtomar" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>langchain</category>
      <category>agenticai</category>
    </item>
    <item>
      <title>Build a Profitable AI Agent with LangChain: A Step-by-Step Tutorial</title>
      <dc:creator>Caper B</dc:creator>
      <pubDate>Mon, 10 Aug 2026 02:22:05 +0000</pubDate>
      <link>https://dev.to/caper_dev/build-a-profitable-ai-agent-with-langchain-a-step-by-step-tutorial-4mah</link>
      <guid>https://dev.to/caper_dev/build-a-profitable-ai-agent-with-langchain-a-step-by-step-tutorial-4mah</guid>
      <description>&lt;h1&gt;
  
  
  Build a Profitable AI Agent with LangChain: A Step-by-Step Tutorial
&lt;/h1&gt;

&lt;p&gt;===========================================================&lt;/p&gt;

&lt;p&gt;As a developer, you're likely no stranger to the vast potential of artificial intelligence (AI) in revolutionizing the way we work and earn a living. One of the most exciting recent developments in the AI space is the emergence of LangChain, a powerful framework for building AI agents that can interact with the world in a more human-like way. In this tutorial, we'll walk through the process of building an AI agent with LangChain that can earn money, and explore the monetization possibilities of this technology.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Setting Up LangChain
&lt;/h2&gt;

&lt;p&gt;To get started with LangChain, you'll need to install the framework and its dependencies. You can do this by running the following command in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;langchain
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once installed, you can import LangChain into your Python script and start building your AI agent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Defining the Agent's Objective
&lt;/h2&gt;

&lt;p&gt;Before we can start building our AI agent, we need to define its objective. For the purposes of this tutorial, let's say our agent's goal is to earn money by completing tasks on a freelance platform. We can define this objective using LangChain's &lt;code&gt;Agent&lt;/code&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Agent&lt;/span&gt;

&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;objective&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;earn money by completing tasks on a freelance platform&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Choosing a Model
&lt;/h2&gt;

&lt;p&gt;LangChain supports a range of AI models, each with its own strengths and weaknesses. For this tutorial, we'll use the &lt;code&gt;LLaMA&lt;/code&gt; model, which is well-suited for natural language processing tasks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;LLaMA&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LLaMA&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Integrating with a Freelance Platform
&lt;/h2&gt;

&lt;p&gt;To earn money, our AI agent will need to interact with a freelance platform. For this tutorial, we'll use the &lt;code&gt;Upwork&lt;/code&gt; API, which provides a range of endpoints for searching and applying for jobs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;upwork_api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;upwork_api_secret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_API_SECRET&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;search_for_jobs&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.upwork.com/api/profiles/v2/search/jobs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bearer &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;upwork_api_key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;apply_for_job&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;job_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.upwork.com/api/profiles/v2/jobs/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;job_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/apply&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bearer &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;upwork_api_key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Training the Agent
&lt;/h2&gt;

&lt;p&gt;With our model and freelance platform integration in place, we can start training our AI agent to earn money. We'll use a simple reinforcement learning approach, where the agent is rewarded for successfully completing tasks and penalized for failing:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
python
def train_agent():
    # Initialize the agent's reward and penalty
    reward = 0
    penalty = 0

    # Loop through a range of tasks
    for task in search_for_jobs():
        # Apply for the task
        application_response = apply_for_job(task["id"])

        # Check if the application was successful
        if application_response["status"] == "accepted":
            # Reward the agent
            reward += 1
        else:
            # Penalize the agent
            penalty += 1

    # Update the agent's objective based on the reward and penalty
    agent.objective = f"earn money by completing tasks on a freelance platform (reward: {reward}, penalty: {penalty})"

# Train the agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>ai</category>
      <category>langchain</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
