<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Sebastian Cajamarca on Medium]]></title>
        <description><![CDATA[Stories by Sebastian Cajamarca on Medium]]></description>
        <link>https://medium.com/@sebastiancajamarca?source=rss-16da43fa2618------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*YD0XSCsZGUU43CGaytFeQg@2x.jpeg</url>
            <title>Stories by Sebastian Cajamarca on Medium</title>
            <link>https://medium.com/@sebastiancajamarca?source=rss-16da43fa2618------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 00:08:53 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@sebastiancajamarca/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[How We Cut Agent Costs 10× by Turning Traces into Tools]]></title>
            <link>https://medium.com/@sebastiancajamarca/how-we-cut-agent-costs-10-by-turning-traces-into-tools-189a6ab8ce0f?source=rss-16da43fa2618------2</link>
            <guid isPermaLink="false">https://medium.com/p/189a6ab8ce0f</guid>
            <dc:creator><![CDATA[Sebastian Cajamarca]]></dc:creator>
            <pubDate>Sat, 22 Aug 2026 22:40:47 GMT</pubDate>
            <atom:updated>2026-08-22T22:43:09.243Z</atom:updated>
            <content:encoded><![CDATA[<p>A few years ago, two friends and I started an artisanal brewery in Bogotá called <a href="https://jabato.com.co/"><strong>Jabato</strong></a>. Five years in, we’ve learned a lot about beer and even more about what it takes to run a consumer-goods company.</p><p>All three of us are engineers, so we did what engineers do: we documented everything, tried a few CRMs, and eventually decided to build an agent to handle our commercial pipeline.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*t5uCaWqHmSwy39VS1ZlG5A.png" /><figcaption><a href="https://jabato.com.co/">https://jabato.com.co/</a></figcaption></figure><h3>The job we were automating</h3><p>Selling craft beer to bars and restaurants is a grind of small, sequential steps:</p><ol><li>Find candidate venues in strategic parts of the city</li><li>Verify each one is a real prospect a place that <strong>sells</strong> beer, not a brewery that makes it (that’s a competitor)</li><li>Check it isn’t already in our leads database, or worse, already an active client</li><li>Research the venue enough to write something that isn’t a template</li><li>Reach out via Instagram DM, WhatsApp, or email</li><li>Log everything and, eventually, book a meeting</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/983/1*gsDtESqUImKHSr9ijj8g6Q.png" /></figure><h3>Attempt 1: the cheapest model that benchmarked well</h3><p>We’re a young company. Most of our capital goes to production and point-of-sale material, not to an AI budget. So we started with the cheapest model that looked good on benchmarks.</p><p>It was fine at reasoning about a lead and drafting a message. It was <strong>unreliable at using tools</strong>. The failure mode wasn’t refusal, it was worse. It would announce the action and never take it:</p><p><em>“Perfect. I’m going to write the handle in the search bar now”</em></p><p>And then nothing. No tool call at all. Four times in a row, on the same lead. In a browser-driven task with a dozen fragile steps, “almost” is indistinguishable from “no.”</p><h3>Attempt 2: frontier models</h3><p>We moved to stronger models <a href="https://platform.kimi.ai/docs/guide/kimi-k3-quickstart">Kimi K3</a>, then <a href="https://x.ai/news/grok-4-5">Grok 4.5</a>. The difference was immediate. They completed the full loop at a natural pace, produced genuinely personalized messages, and handled several leads a day.</p><p>Then we looked at the bill.</p><p>Two real days from our logs, same agent, same job:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/643/1*DMQVk9j01bnNUrl7knyf1Q.png" /></figure><p><strong>Eleven times the cost, for roughly half the calls.</strong></p><p>The unit economics explain it. Compared to what we run today, the frontier model charged ~5× more per input token, ~8× more per output token, and the one that actually hur t <strong>~14× more per cached input token</strong>.</p><p>That last number is the trap. Our agent’s system prompt is large: operating manual, tool documentation, business rules, memory. It gets re-read on <strong>every single turn</strong>. On the expensive model, that cache re-read alone was <strong>~$1.60/day</strong>. Same tokens, on our current setup: about twelve cents.</p><p>We also found we were paying for nothing. Of those 177 daily calls, <strong>48 were idle heartbeats </strong>the agent waking up every 30 minutes to check whether anything needed attention, thinking at full depth to conclude “no.” That was 27% of the day’s spend on doing literally nothing.</p><h3>The idea: use the expensive model as a teacher, not as the operator</h3><p>We initially used an expensive frontier model because it was much better at completing our browser-based sales workflow. But it cost roughly <strong>10× more</strong> than a cheaper model.</p><p>Instead of treating the expensive model as the final solution, we realized it could be used as an <strong>exploration and data-collection tool</strong>.</p><h3>What are traces?</h3><p>A <strong>trace is the complete record of an agent’s execution</strong>: what it tried to do, which tools it called, what happened, where it failed, and how it recovered. By reviewing these traces, we could see the actual procedure required to complete the task not just the final answer.</p><p>The frontier model tried to complete the job, made mistakes, recovered from failures, and discovered what actually worked in our environment. All of this was captured in its <strong>execution traces</strong>.</p><p>We reviewed those traces and turned what we learned into three things:</p><ol><li><strong>Deterministic tools</strong>: Successful browser workflows became reusable tools instead of something the model had to recreate every time.</li><li><strong>Playbooks: </strong>Important lessons and constraints became explicit instructions and documentation.</li><li><strong>Verification gates</strong> : Actions only count as successful when there is explicit proof that they actually happened.</li></ol><p>This changed the cheap model’s job. It no longer needs to <strong>figure out how to perform the task</strong>. It only needs to <strong>follow a known procedure and verify each step</strong>.</p><p>We didn’t fine-tune or retrain the cheap model. The knowledge was moved from the model into <strong>tools, documentation, and verification</strong>.</p><p>The result: we could run the same workflow with a much cheaper model while maintaining reliable execution.</p><h3>The key takeaway</h3><p><strong>Don’t think of an expensive model as your permanent operator. Use it to discover the procedure, then turn what it learned into tools, rules, and verification. Once the process is deterministic and checkable, a much cheaper model can execute it.</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=189a6ab8ce0f" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[From SQL to Shared Insights: Building a Multi-Agent Analytics System with Metabase and Slack]]></title>
            <link>https://medium.com/@sebastiancajamarca/from-sql-to-shared-insights-building-a-multi-agent-analytics-system-with-metabase-and-slack-cab89fe79939?source=rss-16da43fa2618------2</link>
            <guid isPermaLink="false">https://medium.com/p/cab89fe79939</guid>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[slack]]></category>
            <category><![CDATA[metabase]]></category>
            <category><![CDATA[ai-agent]]></category>
            <category><![CDATA[context-engineering]]></category>
            <dc:creator><![CDATA[Sebastian Cajamarca]]></dc:creator>
            <pubDate>Sat, 31 Jan 2026 19:31:29 GMT</pubDate>
            <atom:updated>2026-01-31T19:31:29.615Z</atom:updated>
            <content:encoded><![CDATA[<p>For most people inside a data-driven organization, accessing information still feels harder than it should. Teams usually know <em>what</em> they want to ask: how revenue changed, where churn is coming from, which users are most active. But they get blocked almost immediately. They don’t know SQL syntax, they don’t understand the structure of the database, and they’re not fluent enough in their BI tool to translate a question into a meaningful visualization.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*kK0yJh6-sHP6hfQD.png" /></figure><p>I’ve been living in that gap for years. As a data scientist working with startups and growing companies, I kept finding myself acting as the bridge between business questions and data reality. That experience is what pushed me to start building an analytics agent: something that could help anyone in an organization access information without needing to become a SQL expert, a database archaeologist, or a BI power user.</p><p>At first, the goal was simple. Help people turn questions into SQL. Over time, the goal evolved into something much bigger.</p><h3>Getting to “Good Enough” at SQL</h3><p>Through multiple iterations : <a href="https://medium.com/@sebastiancajamarca/from-rag-to-agentic-how-i-built-a-smarter-sql-ai-agent-for-metabase-415b0446de73">moving from RAG to agentic workflows</a>, introducing memory, <a href="https://medium.com/@sebastiancajamarca/beyond-agentic-building-a-human-in-the-loop-sql-assistant-that-scales-a276dfa20f60">adding human-in-the-loop clarification</a>, and <a href="https://medium.com/@sebastiancajamarca/ai-agent-evaluation-how-we-improved-metaagent-for-faster-and-more-accurate-sql-generation-1a2f503ffaa1">building proper evaluation frameworks</a>. The agent reached an important milestone. Thanks to feedback from real users and systematic evals, we arrived at the same conclusion from different angles: the agent was finally good enough at understanding business questions and reliably generating SQL that answered them.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/532/1*w_XTs68h95CvhYg8OZ4GGQ.png" /><figcaption>AI Text to SQL Benchmark</figcaption></figure><p>That moment was both satisfying and uncomfortable. Satisfying because it validated a lot of engineering decisions. Uncomfortable because it immediately exposed the next limitation.</p><p>Once users trusted the SQL, they started asking a different class of questions.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BklZ56X3Wb0LBEmt79h_kQ.png" /><figcaption>Agent UI</figcaption></figure><pre>-- Agents SQL<br>sql<br>SELECT count(*) AS total_orders,<br>       count(DISTINCT date_trunc(&#39;week&#39;, orderdate)) AS total_weeks,<br>       ROUND( COUNT(*)::numeric / NULLIF(count(DISTINCT date_trunc(&#39;week&#39;, orderdate)),0),2) AS avg_orders_per_week<br>FROM public.orders<br>WHERE orderdate IS NOT NULL;</pre><p>They didn’t just want queries. They wanted to <em>see patterns</em>. They wanted visualizations. They wanted reports they could share with their teams. And they wanted all of this to happen in the tools they already used every day.</p><h3>The Shift from Answers to Insights</h3><p>Two problems became obvious very quickly.</p><p>First, a correct SQL query is rarely the final artifact. Most decisions are made by looking at charts, trends, comparisons, and cohorts. A table of numbers is useful, but a well-designed visualization is what actually drives understanding.</p><p>Second, an agent that lives in isolation does not scale inside a company. If insights stay trapped inside a one-on-one chat interface, they never become part of the organization’s shared knowledge. Real collaboration happens in places like Slack, not inside a private agent session.</p><p>This is where the problem stopped being about text-to-SQL and became about <strong>how insights are created, refined, and shared</strong>.</p><h3>When a Single Agent Was No Longer Enough</h3><p>For a long time, a single agent with good tools and careful context management worked surprisingly well. It could explore schemas, test assumptions, fix SQL errors, and generate accurate queries. For the task of translating business questions into SQL, this approach scaled further than I initially expected.</p><p>But once visualization and reporting entered the picture, cracks started to show.</p><p>Designing visualizations is not just an extension of query generation. It introduces a different kind of reasoning. The agent now has to think in terms of aggregations, trends, comparisons, and cohorts. It has to validate whether a chart actually makes sense, not just whether the SQL runs. And on top of that, it must explain results clearly and distribute them inside collaboration tools like Slack.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/795/1*7omEcT2WEr4FfyXNa1NGxQ.png" /><figcaption>Cohorts analysis</figcaption></figure><p>Trying to make a single agent handle all of this quickly became problematic. Not because the model was incapable, but because the <strong>responsibilities were fundamentally different</strong>. The agent was constantly juggling database reasoning, visualization logic, and communication concerns, all while fighting an ever-growing context window. The more capable it became, the more overloaded its context grew.</p><p>This is where context engineering stopped being an abstract concept and became a practical necessity.</p><p>While researching long-horizon agent systems, I came across work from <a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents">Anthropic on effective context engineering.</a> One idea immediately resonated with what I was seeing in practice: complex agent systems tend to fail not because models lack intelligence, but because context becomes overloaded, misaligned, or poorly shared across tasks.</p><p>That insight reframed the problem. The issue wasn’t that the agent needed to be smarter. It needed to be <strong>more focused</strong>.</p><h3><strong>From One Overloaded Agent to Focused Collaboration</strong></h3><p>This realization led directly to a multi-agent design, but specialization introduced a new challenge: collaboration. The query agent needs to explain why a query was written a certain way so the visualization agent can adapt it safely. The visualization agent must surface failures or inconsistencies so assumptions can be corrected. At the same time, a communication agent needs to extract business intent from Slack conversations and present queries and visual results in a way humans can trust and act on.</p><p>To make this work, we designed a shared memory layer where context lives in one place but is selectively accessed by each agent. Instead of passing raw conversation history around, agents exchange distilled knowledge — queries, field summaries, visualization specs, and reasoning steps. This allows information to flow across agents without overwhelming any single one of them, turning collaboration into a structured process and context into a shared asset rather than a bottleneck.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YRYHJWBumj-LZiA6T0FGBA.png" /><figcaption>Context management</figcaption></figure><h3>Solution</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/998/1*LF6lUB_2iRsEkBTpzU14yA.png" /><figcaption>Slack integration</figcaption></figure><p>The end result is a platform where <a href="https://metagent.app/"><strong>Metagent</strong></a> connects directly to <strong>Metabase</strong> and <strong>Slack</strong> to turn business questions into shared insights, end to end. The system now generates queries, builds visualizations using Metabase’s native tools for filtering, aggregation, and chart definition, and publishes those results directly into Slack channels and group conversations. So insights show up where teams already work and discuss decisions.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MJYcG72yyGqckCMWVah8HQ.png" /><figcaption>Visualization Generated</figcaption></figure><p>If you’d like to try it, you can join for free at <a href="https://metagent.app/">https://metagent.app/</a> , and if you’re interested in following the journey or diving deeper into the architecture, feel free to connect with me on <a href="https://x.com/sebas88caja">X</a> or <a href="https://www.linkedin.com/in/sebastiancajamarca/">LinkedIn</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=cab89fe79939" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building the Analytics Agent on Metabase: A Progress Report]]></title>
            <link>https://medium.com/@sebastiancajamarca/building-the-analytics-agent-on-metabase-a-progress-report-44192f2d4468?source=rss-16da43fa2618------2</link>
            <guid isPermaLink="false">https://medium.com/p/44192f2d4468</guid>
            <category><![CDATA[metabase]]></category>
            <category><![CDATA[text-to-sql]]></category>
            <category><![CDATA[sql]]></category>
            <category><![CDATA[analytics]]></category>
            <category><![CDATA[agents]]></category>
            <dc:creator><![CDATA[Sebastian Cajamarca]]></dc:creator>
            <pubDate>Thu, 30 Oct 2025 01:28:40 GMT</pubDate>
            <atom:updated>2025-11-04T14:16:43.722Z</atom:updated>
            <content:encoded><![CDATA[<p>in the world of data-driven organizations, a recurring theme keeps coming up: <strong>great questions</strong>, <strong>opaque databases</strong>, and <strong>scarce SQL expertise</strong>. At many companies, business teams can think of the questions, but struggle with the mechanics of writing joins, filters, aggregations and visualizations. Working in data science over the years I found myself repeatedly bridging that gap. That led me to build an analytics agent on Metabase and the journey has been far from trivial.</p><p>Here’s a snapshot of where we started, what we’ve learned, and how the <a href="https://www.metagent.app/">Metagent</a> is evolving.</p><h3>Why Metabase?</h3><p>I selected Metabase for several pragmatic reasons:</p><ul><li>It offers a comprehensive metadata API (tables, columns, relationships, data catalogue) which helps in building an assistant that “knows” the schema.</li><li>Because it supports self-hosting, users retain data security and control rather than shipping the data to any SaaS.</li><li>The UI is already familiar for many analysts/BI teams, so we can layer intelligence rather than re-invent the entire UI experience.</li></ul><p>In short: we’re not replacing Metabase, we’re <strong>augmenting</strong> it.</p><h3>The First Version: RAG (Retrieval-Augmented-Generation)</h3><p>The earliest iteration focused on a simple architecture:</p><ul><li>Metadata (schema, table descriptions) is extracted from Metabase.</li><li>A vector store (e.g., Pinecone) stores indexed documentation for retrieval.</li><li>A large-language model takes the user’s natural-language question + retrieved context and generates SQL.</li></ul><p>That got us off the ground: users could type “Show total sales by region” (for example) and get an SQL query which could then be executed in Metabase to render a chart. But we quickly hit limitations:</p><ul><li>The generated SQL was often correct <em>technically</em>, but missed business nuance (e.g., “approved” status vs “confirmed” status) or real-world data quirks.</li><li>There was little exploration — the agent didn’t run test queries or inspect distinct values to validate its assumptions.</li><li>Performance and context-window issues surfaced quickly as schemas grew.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*4hJQFgpnSVb8sALBKbLiwQ.gif" /><figcaption>Agent feature in metabase</figcaption></figure><h3>From RAG to Agentic: Tool-Based Workflow</h3><p>To address those limitations I shifted to an agentic architecture where the assistant has <strong>tools</strong> it can call (just like an analyst):</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/720/1*M54ClENlH5PwjxTHjBP69g.jpeg" /></figure><ul><li><em>Database Overview Tool</em>: fetch schema, tables, relationships.</li><li><em>Relationship Explorer</em>: dig into table relationships and join paths.</li><li><em>Table Inspector</em>: show field types, domain values, sample rows.</li><li><em>Query Tester</em>: run exploratory SQL (read-only) to inspect actual data (e.g., SELECT DISTINCT status FROM invoices) before committing to a final query.</li></ul><p>The agent’s thought process became more like:</p><ol><li>Understand the business question</li><li>Explore relevant tables &amp; relationships</li><li>Run small queries to probe the data</li><li>Construct and refine the final SQL</li></ol><p>This led to better results: more accurate SQL, more aligned with real business logic, and fewer surprises when the query ran on actual data.</p><p>But as we onboarded larger clients (hundreds of tables, many schemas) new challenges surfaced.</p><h3>Scaling Up: Memory, Human-in-the-Loop, and Large Databases</h3><p>As the complexity and size of client databases increased, the agentic workflow by itself started to struggle:</p><ul><li>Massive schemas meant enormous context windows; the agent could lose focus on what the user really asked.</li><li>Business logic ambiguity (what “revenue” means, what “active user” means) became a blocker. The agent could guess but incorrect guesses erode trust.</li></ul><p>To overcome this, I implemented two major innovations:</p><h3>Memory Management</h3><ul><li>Short-term memory: holds the current context for one interaction (recent findings, test query results) so the agent doesn’t re explore everything from scratch.</li><li>Long-term memory: stores persistent insights across queries (e.g., “the status field uses values ‘active’, ‘inactive’, ‘pending’”; “table X join table Y on key Z”) so future queries can reuse knowledge.</li></ul><p>This dramatically improved performance in large schema environments: fewer redundant explorations, faster query generation, better accuracy.</p><h3>Human-in-the-Loop Clarification</h3><p>Rather than forcing the agent to guess ambiguous business logic, we built a conversational interface where the agent can ask clarifying questions:</p><p><em>“When you say ‘active users’, do you mean users with </em><em>status = ‘active’ in table A, or those with </em><em>last_login &gt; 30d in table B?”</em></p><p>This ensures the final SQL aligns with how the business defines key metrics not just what the database happens to call them.</p><h3>Performance &amp; Metrics</h3><p>In the latest version (as of October 2025), some results have been promising:</p><ul><li>Accuracy improvement: for one benchmark we increased the success rate (first-try correct SQL) by ~50 %. <a href="https://medium.com/@sebastiancajamarca/ai-agent-evaluation-how-we-improved-metaagent-for-faster-and-more-accurate-sql-generation-1a2f503ffaa1">Read more.</a></li><li>Response time: reduced from ~65 seconds to ~58 seconds on average.</li><li>Token consumption: with better context management, we reduced token usage by ~75 % in trials.</li></ul><p>Those numbers still don’t hit elite human-expert performance, but they’re moving in the right direction. For reference, a standard text-to-SQL benchmark reports ~82 % accuracy for AI models and ~92 % for humans.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*YkuXcjXeZ4G_Gz0keKcyNg.gif" /></figure><h3>Lessons Learned</h3><p>Some takeaways from this journey:</p><ul><li>Having a large LLM + schema context is <strong>necessary</strong>, but <em>not sufficient</em>. The agent must behave like an analyst: exploratory, adaptive, and iterative.</li><li>Providing tools (inspection, query testing) significantly improves results letting the agent <strong>test its assumptions</strong> instead of trusting documentation alone.</li><li>Memory matters. Real-world databases are big, changes accumulate, patterns repeat. Without remembering past findings, you waste time rediscovering.</li><li>Transparent questioning (human-in-the-loop) builds trust. Users must feel in control, not like they’re handing over keys to a black box.</li><li>Metrics are important. Without tracking accuracy, time, token cost, tool usage and user feedback, you don’t know whether your agent is improving.</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=44192f2d4468" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[AI Agent Evaluation: How We Improved MetaAgent for Faster and More Accurate SQL Generation]]></title>
            <link>https://medium.com/@sebastiancajamarca/ai-agent-evaluation-how-we-improved-metaagent-for-faster-and-more-accurate-sql-generation-1a2f503ffaa1?source=rss-16da43fa2618------2</link>
            <guid isPermaLink="false">https://medium.com/p/1a2f503ffaa1</guid>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[metabase]]></category>
            <category><![CDATA[agents]]></category>
            <category><![CDATA[sql]]></category>
            <category><![CDATA[text-to-sql]]></category>
            <dc:creator><![CDATA[Sebastian Cajamarca]]></dc:creator>
            <pubDate>Sat, 25 Oct 2025 01:00:32 GMT</pubDate>
            <atom:updated>2025-10-25T16:39:19.895Z</atom:updated>
            <content:encoded><![CDATA[<p><a href="https://metagent.app/">MetaAgent</a> is an analytics agent that works on top of the <a href="https://www.metabase.com/">Metabase</a> environment, leveraging its secure tools and comprehensive data catalog. Since our official <a href="https://medium.com/@sebastiancajamarca/from-rag-to-agentic-how-i-built-a-smarter-sql-ai-agent-for-metabase-415b0446de73">launch in June</a>, we’ve been working closely with users to enhance MetaAgent’s performance making it faster, more accurate, and aligned with the latest trends in agentic flow development.</p><h3>Evolution Through User Feedback</h3><p>Initial user feedback guided us to transition from a basic Retrieval-Augmented Generation (RAG) approach to a more sophisticated agentic flow with improved tools and <a href="https://medium.com/@sebastiancajamarca/beyond-agentic-building-a-human-in-the-loop-sql-assistant-that-scales-a276dfa20f60">human-in-the-loop</a> methodologies. This shift resulted in significant improvements in both accuracy and efficiency, reducing token consumption and response times.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/960/1*HPed5rHJ-d0Pz8xxDTTc1w.jpeg" /><figcaption>Agent evolution</figcaption></figure><p>After several iterations, <a href="https://metagent.app/">MetaAgent</a> achieved a 50% success rate for correct first-try answers across queries. While this was a solid foundation, it fell short of current text-to-SQL benchmarks — approximately 82% accuracy for AI models and 92% for human experts (data engineers and database students) according to the <a href="https://bird-bench.github.io/">BIRD Benchmark</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/448/1*O3Wh3Sa-3-tsbnb_ta3gbw.png" /><figcaption>AI Text to SQL Benchmark</figcaption></figure><p>This gap prompted critical questions: Should we switch models? Refine prompt engineering? Or redesign the agent flow and tool definitions? To answer these systematically, I leveraged my data science expertise to implement a comprehensive agent evaluation framework.</p><h3>Our Evaluation Process</h3><h3>Framework Design</h3><p>Agent evaluation involves tracking three core dimensions: <strong>Accuracy</strong>, <strong>Efficiency</strong>, and <strong>Security</strong>. Achieving this requires robust observability to monitor:</p><ul><li>Tool usage patterns.</li><li>Response times.</li><li>Token consumption.</li><li>Customer feedback.</li></ul><p>We initially adopted <a href="https://www.langchain.com/langsmith">LangSmith</a>, which integrates seamlessly with <a href="https://www.langchain.com/langgraph">LangGraph</a>, for observability. Open-source alternatives like <a href="https://arize.com/docs/phoenix/tracing/llm-traces">Arize Phoenix</a> are also excellent options for LLM tracing and monitoring.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OQHdgsYSs_6ADy1MocvIcQ.png" /><figcaption>Observability with LangSmith</figcaption></figure><h3>Metrics Definition</h3><p>We established clear metrics for evaluation:</p><ul><li><strong>Correctness</strong>: The SQL query must accurately answer the user’s question based on the database.</li><li><strong>Efficiency (Cost)</strong>: Measured by total tokens used (input + output).</li><li><strong>Efficiency (Time)</strong>: Shorter response times indicate optimized query generation and tool usage.</li><li><strong>Security</strong>: Leveraging Metabase API keys and encryption ensures only authorized queries execute.</li></ul><h3>Test Dataset Selection</h3><p>To rigorously evaluate MetaAgent, we needed diverse databases and complex queries requiring database expertise. We adopted the <a href="https://bird-bench.github.io/">BIRD Dataset</a></p><p>(Big Bench for Large-Scale Database Grounded Text-to-SQLs), which provides:</p><ul><li>12,751+ unique question-SQL pairs.</li><li>95 large databases (33.4 GB total).</li><li>37+ professional domains (blockchain, healthcare, education, etc.).</li></ul><h3>Example</h3><p>Question: Mention the first name of employee who took care the order id 10250</p><p>Human SQL</p><pre>SELECT T1.FirstName, T1.LastName <br>FROM Employees AS T1 <br>INNER JOIN Orders AS T2 ON T1.EmployeeID = T2.EmployeeID <br>WHERE T2.OrderID = 10250</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/476/1*x7nK1mJAOIjRQQ0dc9ecvg.png" /><figcaption>Real answer</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*YkuXcjXeZ4G_Gz0keKcyNg.gif" /><figcaption>Agent response</figcaption></figure><h3>Optimization Environment</h3><p>With observability, metrics, and test data in place, we began systematic optimization to reduce tokens and time while improving accuracy. We experimented with:</p><ul><li>AI model selection.</li><li>System prompt engineering.</li><li>Tool definitions.</li><li>Agentic flow design.</li></ul><p>After hundreds of experiments, three key insights emerged:</p><ol><li><strong>Simplicity is Best</strong>: We simplified our complex graph-based agent architecture to a streamlined experimentation flow.</li><li><strong>Context Management Matters</strong>: We optimized context by including only relevant facts, re-contextualizing when needed, or asking clarifying questions when context grew too large.</li><li><strong>Model Selection Impact</strong>: Models with stronger coding capabilities improved accuracy, while smaller, faster models handled simpler steps efficiently.</li></ol><h3>Results</h3><p>These improvements yielded remarkable outcomes:</p><ul><li><strong>50% accuracy improvement</strong>, bringing MetaAgent close to current benchmarks.</li><li><strong>Response time optimization</strong>: From ~65 seconds to ~58 seconds.</li><li><strong>Token reduction</strong>: 75% decrease through improved context management.</li></ul><h3>Get Involved</h3><p>We’d love to hear about your experience with AI agents and SQL generation. Connect with us:</p><ul><li>Create and test your account at <a href="https://metagent.app/">MetaAgent.app</a></li><li>Reach out via <a href="https://x.com/sebas88caja">X (Twitter)</a> or <a href="https://www.linkedin.com/in/sebastiancajamarca/">LinkedIn</a></li><li>If you don’t have Metabase but want to try MetaAgent, we now offer setup services for your analytics environment.</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1a2f503ffaa1" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Beyond agentic: Building a Human-in-the-Loop SQL assistant that scales]]></title>
            <link>https://medium.com/@sebastiancajamarca/beyond-agentic-building-a-human-in-the-loop-sql-assistant-that-scales-a276dfa20f60?source=rss-16da43fa2618------2</link>
            <guid isPermaLink="false">https://medium.com/p/a276dfa20f60</guid>
            <category><![CDATA[ai-agent]]></category>
            <category><![CDATA[text-to-sql]]></category>
            <category><![CDATA[sql]]></category>
            <category><![CDATA[ai]]></category>
            <dc:creator><![CDATA[Sebastian Cajamarca]]></dc:creator>
            <pubDate>Sun, 10 Aug 2025 22:53:12 GMT</pubDate>
            <atom:updated>2025-08-10T22:53:12.301Z</atom:updated>
            <content:encoded><![CDATA[<p><em>How I evolved MetAgent from a static fork to a SaaS platform that handles massive databases and ambiguous business logic through intelligent memory management and conversational AI</em></p><h3>The Journey from Fork to Platform</h3><p>MetAgent began in February 2025 as a personal mission. As a data scientist who had helped found several startups, I’d spent countless hours fielding “quick” SQL requests from business teams. The pattern was always the same: talented people with great questions but limited SQL expertise, trying to extract insights from increasingly complex databases.</p><p>My initial <a href="https://medium.com/@sebastiancajamarca/building-an-ai-powered-sql-assistant-with-metabase-2443105fe3a3">solution</a> was straightforward: fork Metabase and integrate AI directly into it. While the concept proved valuable, deployment was a nightmare. Users struggled to install my fork alongside their existing Metabase instances, and many worried about missing critical upstream updates. The RAG-based approach, though functional, was too rigid for real-world complexity.</p><p>That’s when I decided to pivot from a fork to a standalone platform: <a href="https://www.metagent.app/login">MetAgent</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8nPlbtB62W-q1Ti-34nfjg.png" /><figcaption>MetAgent</figcaption></figure><h3>The Agentic Evolution</h3><p>My first MetAgent release introduced an agentic workflow using LangGraph, giving the AI tools to think like a data analyst rather than a translation service. The agent followed a structured approach:</p><ol><li><strong>Understanding business needs: </strong>Parsing the intent behind questions</li><li><strong>Exploring database schemas and relationships: </strong>Mapping the data landscape</li><li><strong>Building and running exploratory queries</strong> : Testing assumptions with real data</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vaCZf0b5gFQIHonhyONVcg.png" /></figure><p><a href="https://medium.com/@sebastiancajamarca/from-rag-to-agentic-how-i-built-a-smarter-sql-ai-agent-for-metabase-415b0446de73">This approach</a> delivered significantly better results than my RAG implementation. The agent made intelligent decisions, managed context effectively, and produced accurate queries for moderately complex databases.</p><p>But then we hit a wall.</p><h3>The Scale Challenge</h3><p>When enterprise customers started testing MetAgent on their production databases with hundreds of tables across multiple schemas , the system began to struggle. The context window became massive, causing the agent to lose focus on critical details. It was like asking someone to memorize an entire encyclopedia while answering a specific question.</p><p>I needed a more sophisticated approach, which led to two major innovations:</p><h3>1. Memory Management: Teaching AI to Remember Like Humans</h3><p>I implemented a dual-memory system inspired by human cognition:</p><p><strong>Short-term Memory</strong>: Holds current context for single interactions, enabling quick recall of recent discoveries. After each tool use, the agent summarizes key findings, keeping only what’s relevant for the immediate task.</p><p><strong>Long-term Memory</strong>: Stores persistent information across multiple queries. When the agent discovers important patterns through exploratory queries like specific status values or common join patterns it saves these insights for future use.</p><p>This approach dramatically improved performance on large databases. The agent could now handle complex schemas while maintaining focus on the specific question at hand.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KZKIZ6JfqbRUu0_He-fBmQ.png" /><figcaption>Memory management</figcaption></figure><h3>2. Human-in-the-Loop: Embracing Ambiguity</h3><p>Even with improved memory management, we encountered a fundamental challenge: ambiguous business logic. In the messy reality of startup databases, concepts like “revenue,” “GMV,” or “profit” might have multiple interpretations depending on the table or context.</p><p>Rather than guess, we built a conversational interface where the agent can ask for clarification:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/882/1*WWg5Z5qpMqapKdHQQiIZ9Q.png" /></figure><p>This collaborative approach transforms MetAgent from a black box into a transparent partner that learns your business logic through interaction.</p><h3>Try MetAgent Today</h3><p><a href="https://www.metagent.app/">MetAgent.app</a> is now available as a SaaS platform that connects securely to your Metabase instance. Your data never leaves your infrastructure , we only access schema information and run read-only test queries that you explicitly approve.</p><p>Key features:</p><ul><li><strong>Secure API Integration</strong>: Works with any Metabase instance (self-hosted or cloud)</li><li><strong>Intelligent Memory</strong>: Handles databases of any size efficiently</li><li><strong>Conversational Interface</strong>: Clarifies ambiguities through natural dialogue</li><li><strong>Full Transparency</strong>: Shows exactly what queries will run before execution</li></ul><h3>What’s Next?</h3><p>Building MetAgent has taught me that the future of data accessibility isn’t about replacing analysts , it’s about augmenting everyone’s analytical capabilities. By combining agentic workflows, intelligent memory management, and human collaboration, we’re making data truly accessible to entire organizations.</p><p>I’d love to hear about your data accessibility challenges. Are you struggling with complex queries? Is your team bottlenecked on SQL expertise?</p><p>Reach out on <a href="https://x.com/sebas88caja">X/Twitter</a> or <a href="https://www.linkedin.com/in/sebastiancajamarca/">LinkedIn</a>, or try MetAgent yourself at <a href="https://www.metagent.app/">metagent.app</a>.</p><p>For more information go to our website <a href="https://churnless.ai/">https://churnless.ai/</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a276dfa20f60" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[From RAG to Agentic: How I Built a Smarter SQL AI Agent for Metabase]]></title>
            <link>https://medium.com/@sebastiancajamarca/from-rag-to-agentic-how-i-built-a-smarter-sql-ai-agent-for-metabase-415b0446de73?source=rss-16da43fa2618------2</link>
            <guid isPermaLink="false">https://medium.com/p/415b0446de73</guid>
            <category><![CDATA[langgraph]]></category>
            <category><![CDATA[metabase]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[agents]]></category>
            <dc:creator><![CDATA[Sebastian Cajamarca]]></dc:creator>
            <pubDate>Sun, 29 Jun 2025 15:43:05 GMT</pubDate>
            <atom:updated>2025-08-10T23:09:17.584Z</atom:updated>
            <content:encoded><![CDATA[<p>How I turned my first “text-to-SQL” proof-of-concept into a multi-tool agent that thinks, explores, and debugs using Metabase API.</p><h3>The Evolution of My SQL Assistant</h3><p>In my <a href="https://medium.com/@sebastiancajamarca/building-an-ai-powered-sql-assistant-with-metabase-2443105fe3a3">previous article</a>, I showed how I built an AI-powered SQL assistant for Metabase using RAG architecture. After testing it with several customers, I learned something crucial: <strong>my agent was thinking like a machine, not like a data analyst</strong>.</p><p>Real analysts don’t just translate questions to SQL. They explore, validate, and iterate. They run quick queries to understand the data structure. They check what values actually exist in a status column before filtering on them.</p><p>So I rebuilt my assistant to work the way analysts actually work.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*QxU70f1GO1KGk_YxHRCSfw.gif" /></figure><h3>The Problem with My First Approach</h3><p>My original RAG based agent had access to database schemas and documentation, but it was limited. It would often generate SQL that was <em>technically</em> correct but missed business nuances:</p><ul><li>It didn’t know that “approved” invoices might be marked as “success” in one database but “confirmed” in another</li><li>It couldn’t explore the data to understand edge cases</li><li>It had no way to validate its assumptions before presenting results</li></ul><h3>Building a Tool-Based Agent</h3><p>Instead of just feeding my agent static documentation, I gave it tools to explore the database like a real analyst would:</p><h4>1. Database Overview Tool</h4><p>Provides high level schema information tables.</p><h4>2. Relationship Explorer</h4><p>Maps table relationships, even those nested 3+ levels deep. Essential for complex joins.</p><h4>3. Table Inspector</h4><p>Deep dives into specific tables, showing field types, constraints, and what aggregations are possible.</p><h4>4. Query Tester</h4><p>Lets the agent run exploratory queries to understand the data.</p><pre>@tool<br>def test_sql_query_tool(user_id: str, connection_id: str, database_id: str, query: str) -&gt; str:<br>    &quot;&quot;&quot;Execute a SQL query and return formatted results&quot;&quot;&quot;<br>    try:<br>        response = call_agentapp_lambda(&#39;execute_query&#39;, {<br>            &#39;userId&#39;: user_id,<br>            &#39;connectionId&#39;: connection_id,<br>            &#39;databaseId&#39;: database_id,<br>            &#39;sqlQuery&#39;: query<br>        })<br>        <br>        if not response.get(&#39;success&#39;, False):<br>            error_msg = response.get(&#39;error&#39;, &#39;Unknown error&#39;)<br>            return f&quot;❌ Query Failed Error: {error_msg}&quot;</pre><h3>The Agent’s Thought Process</h3><p>Using LangGraph, I structured the agent to think like an analyst:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uI2CJYZqZi2pUcAiDYjNCg.png" /></figure><ol><li>Understands the business question</li><li>Explores relevant tables and relationships</li><li>Runs test queries (like SELECT DISTINCT status FROM invoices) to understand data patterns</li><li>Iteratively refines its approach based on actual data</li><li>Handles errors intelligently, retrying with new strategies</li><li>Metabase’s REST API lets it run read-only SQL from a Lambda.</li><li>Results flow back as a markdown table the LLM can inspect.</li></ol><h3>Try It Yourself</h3><p>We’ve just launched <a href="http://www.metagent.app/">www.metagent.app</a> where Metabase users can try the new agent with 10 free credits. It works with any Metabase instance (self-hosted or cloud) through secure API keys.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/936/1*TfBdNnMgHLo-FPKhi0J60g.png" /></figure><h3>What’s Next?</h3><p>This journey taught me that the key to better AI agents isn’t just better prompts or more data. It’s giving them the right tools and teaching them to think like the humans they’re meant to help.</p><p>Have you tried building agents that mimic human problem-solving? I’d love to hear about your approach. Reach out on <a href="https://x.com/sebas88caja">X/Twitter</a> and let’s discuss!</p><p><strong>Update August 2025:</strong> <a href="https://www.metagent.app/login">MetAgent</a> has evolved again! I’ve solved the context window challenges for large databases through intelligent memory management and added human-in-the-loop collaboration for handling ambiguous queries. Learn about these improvements in my new article: <a href="https://medium.com/@sebastiancajamarca/beyond-agentic-building-a-human-in-the-loop-sql-assistant-that-scales-a276dfa20f60">https://medium.com/@sebastiancajamarca/beyond-agentic-building-a-human-in-the-loop-sql-assistant-that-scales-a276dfa20f60</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=415b0446de73" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building an AI-Powered SQL Assistant with Metabase]]></title>
            <link>https://medium.com/@sebastiancajamarca/building-an-ai-powered-sql-assistant-with-metabase-2443105fe3a3?source=rss-16da43fa2618------2</link>
            <guid isPermaLink="false">https://medium.com/p/2443105fe3a3</guid>
            <category><![CDATA[text-to-sql]]></category>
            <category><![CDATA[metabase]]></category>
            <category><![CDATA[rags]]></category>
            <category><![CDATA[sql]]></category>
            <category><![CDATA[ai]]></category>
            <dc:creator><![CDATA[Sebastian Cajamarca]]></dc:creator>
            <pubDate>Sat, 22 Feb 2025 19:15:09 GMT</pubDate>
            <atom:updated>2025-11-04T14:15:57.720Z</atom:updated>
            <content:encoded><![CDATA[<blockquote>Built an AI-powered SQL assistant for Metabase that lets anyone query databases using natural language — no SQL expertise needed</blockquote><p>As a data scientist, I’ve worked across multiple companies, leveraging databases to extract insights for machine learning models. Over time, I found myself frequently assisting BI and BA teams in solving complex SQL queries, especially when launching new projects or defining new metrics. These teams often struggled with limited knowledge of database structures and SQL syntax, leading me to wonder: <em>Is there a better way to make data accessible to everyone, regardless of their technical background?</em></p><p>Inspired by <a href="https://medium.com/pinterest-engineering/how-we-built-text-to-sql-at-pinterest-30bad30dabff">Pinterest’s</a> <strong>text-to-SQL</strong> approach and <a href="https://www.uber.com/blog/query-gpt/">Uber’s QueryGPT</a>, I decided to build an AI-powered SQL assistant — an accessible tool that enables users to query databases using natural language.</p><h3>Why Metabase?</h3><p>To build this tool, I chose <a href="https://www.metabase.com/"><strong>Metabase</strong></a>, an open-source data visualization platform I had years of experience working with. Metabase offers several advantages:</p><ul><li><strong>Comprehensive API</strong>: Extracts metadata from databases, including tables, columns, and relationships.</li><li><strong>Self-hosting</strong>: Ensures data security and control without requiring external access.</li></ul><p>By leveraging Metabase, I could focus on designing an AI-driven query assistant without worrying about security, access control, or user interface development.</p><h3>Implementation Overview</h3><p>To enable AI-driven SQL generation, I designed a <strong>two-step agentic process</strong> within Metabase:</p><ol><li><strong>QueryDesigner Agent</strong>: Processes the user’s natural language question, leveraging a complete database schema to determine the necessary tables and query structure.</li><li><strong>QueryArchitect Agent</strong>: Retrieves detailed table documentation from a vector database, generating a refined SQL query that users can execute within Metabase.</li></ol><h4>Architecture Breakdown</h4><ul><li><strong>Vector Database (</strong><a href="https://www.pinecone.io/"><strong>Pinecone</strong></a><strong>)</strong>: Stores indexed metadata and table descriptions for retrieval-augmented generation (RAG).</li><li><strong>LLM Service (</strong><a href="https://openai.com/"><strong>OpenAI</strong></a><strong>)</strong>: Translates natural language queries into SQL, using database metadata as context.</li><li><strong>Metabase UI Integration</strong>: Seamlessly integrates into Metabase’s query builder, allowing users to enter plain-language queries and receive executable SQL statements.</li></ul><h3>Designing the AI Query Agent Flow</h3><p>To build an AI agent that delivers meaningful insights from data regardless of a user’s SQL expertise or familiarity with database structures I needed to start with a foundational approach. My goal was to create the simplest possible architecture that could function within Metabase while maintaining efficiency and ease of use. The following illustration provides an overview of this process.</p><figure><img alt="Agent flow for text to sql" src="https://cdn-images-1.medium.com/max/611/1*J9lpFEfkcUWS4_G7km7L4Q.png" /><figcaption>Agents flow</figcaption></figure><p>This AI-powered querying system operates in two steps:</p><ol><li><strong>QueryDesigner Agent:</strong> When a user submits a question, this agent processes the full database documentation, including schema details and an overview of the tables. Based on this information, it determines the relevant tables, extracts the necessary data, and outlines the SQL query structure.</li><li><strong>QueryArchitect Agent:</strong> Using the information from the QueryDesigner Agent, this second agent retrieves detailed table documentation from the vector database. The vector database contains structured documentation for every table and field, including relationships and user-provided descriptions. With this enriched context, the QueryArchitect Agent generates an optimized SQL query. The final query is then presented in the Metabase interface, allowing users to execute it within their database and select their preferred visualization format.</li></ol><h3>Setting Up the AI Configuration</h3><p>Before processing queries, the system requires initial configuration:</p><p><strong>1. Database Documentation Storage</strong></p><ul><li>Users select tables to index and provide a high-level database description.</li><li>Metabase’s metadata service extracts schema details, including field types and relationships.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MraV9xZLo491JPcG2hhDFw.png" /></figure><p><strong>2. AI Service Integration</strong></p><ul><li>Admins securely add API keys for Pinecone (vector database) and OpenAI (LLM processing).</li><li>A new <strong>AI Configuration</strong> section in Metabase’s settings allows easy management.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*CWq0ZRO2IJZjOpExpwWdgA.png" /><figcaption>New setting panel for Ai configuration</figcaption></figure><p><strong>3. Indexing Process</strong></p><ul><li>Once API keys are added, users click a <strong>Create Index</strong> button.</li><li>The system generates structured documentation, providing a comprehensive database overview.</li><li>This documentation enhances the AI’s ability to infer relationships (e.g., linking orders to addresses and cities for location-based queries).</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UdLZf6Sj_mmdmC6dxOZUQQ.png" /><figcaption>Index generation</figcaption></figure><h3>User Experience: Querying with AI</h3><p>To keep the workflow simple, I integrated the AI assistant directly into Metabase’s query builder:</p><ol><li><strong>User inputs a natural language question</strong> (e.g., <em>“Show total sales per city”</em>).</li><li><strong>QueryDesigner Agent</strong> determines required tables and relationships.</li><li><strong>QueryArchitect Agent</strong> fetches metadata from the vector database and constructs an SQL query.</li><li><strong>SQL query is displayed in Metabase</strong>, allowing users to review, modify, and run it.</li><li><strong>Users select visualizations</strong> based on the retrieved data.</li></ol><p>This approach minimizes disruptions while making data queries accessible to non-technical users.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*4hJQFgpnSVb8sALBKbLiwQ.gif" /></figure><h3>Future Enhancements</h3><p>This is just the first iteration of the AI-powered SQL assistant. Future improvements include:</p><p><strong>Leveraging Pre-stored Queries &amp; User Logs</strong></p><ul><li>Identifying commonly used queries as authoritative examples.</li><li>Enhancing AI accuracy by learning from past queries.</li></ul><p><strong>Adding Feedback Loops</strong></p><ul><li>Automatically validating generated SQL queries before presenting them to users.</li><li>Iteratively refining queries based on detected errors.</li></ul><p><strong>Expanding Use Cases</strong></p><ul><li>Exploring additional AI-powered features based on user feedback.</li></ul><h3>Get Involved</h3><p>I’m actively looking for companies interested in testing this platform. If you’d like to try it for free, feel free to DM me on X (<a href="https://x.com/sebas88caja">https://x.com/sebas88caja</a>)!</p><p>Git: <a href="https://github.com/sazboxai/metabase_scg">https://github.com/sazboxai/metabase_scg</a></p><h3>Conclusion</h3><p>By integrating AI with Metabase, I aim to democratize data access, allowing anyone, regardless of technical expertise, to extract insights effortlessly. This is just the beginning, and I’m excited to refine and expand this tool with real-world feedback. Let’s make data truly accessible!</p><p><strong>Update August 2025:</strong> The journey continues! After evolving from RAG to agentic architecture, I’ve taken <a href="https://www.metagent.app/login">MetAgent</a> even further. No more fork installations, it’s now a full SaaS platform with memory management for massive databases and human-in-the-loop collaboration. Read how MetAgent transformed from a Metabase fork to a scalable platform in my latest article: <a href="https://medium.com/@sebastiancajamarca/beyond-agentic-building-a-human-in-the-loop-sql-assistant-that-scales-a276dfa20f60">https://medium.com/@sebastiancajamarca/beyond-agentic-building-a-human-in-the-loop-sql-assistant-that-scales-a276dfa20f60</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2443105fe3a3" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Air K Nearest Neighbors]]></title>
            <link>https://medium.com/@sebastiancajamarca/air-k-nearest-neighbors-d9ce281ab66e?source=rss-16da43fa2618------2</link>
            <guid isPermaLink="false">https://medium.com/p/d9ce281ab66e</guid>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[web-scraping]]></category>
            <category><![CDATA[programing]]></category>
            <category><![CDATA[real-estate-investments]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[Sebastian Cajamarca]]></dc:creator>
            <pubDate>Sun, 27 Oct 2024 01:00:48 GMT</pubDate>
            <atom:updated>2024-10-28T13:34:48.552Z</atom:updated>
            <content:encoded><![CDATA[<p>As a Data Scientist, my daily life revolves around bytes, insights, algorithms, and other digital pursuits. Despite this, I’ve always been drawn to invest in something more tangible. For quite some time, I had my sights set on investing in an Airbnb property in Medellín, widely recognized as one of the most innovative cities globally (source:<a href="https://www.bbc.com/news/world-latin-america-21638308"> BBC News</a>).</p><p>After much research and anticipation, last year we discovered a fantastic investment opportunity in Laureles, a neighborhood recently named one of the coolest in the world (source:<a href="https://www.timeout.com/news/its-official-this-is-the-worlds-coolest-neighbourhood-right-now-101723"> Time Out</a>).</p><p>Leveraging my fiancée’s expertise in civil engineering and home décor, we transformed the property into an extraordinary space. It’s now beautifully designed to comfortably accommodate up to five guests, ready to welcome any type of traveler.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*OwZ7rIbiYli0wsiv" /><figcaption>Example listing</figcaption></figure><p>Before renting out our property, we needed to make sure our investment would be profitable, especially with the current high interest rates. We wanted to see if this was a smart move given the opportunity cost.</p><p>To do this, I tapped into my data science skills to collect Airbnb listing data. I focused on key details like location, number of guests, price per night, ratings, and reviews. Using this data, I aimed to estimate a good nightly price that would keep occupancy high and ensure profitability.</p><p>This guide explains my process. I hope it helps other data-driven entrepreneurs considering similar investments. You can also experiment with the data using this tool: [<a href="https://churnless.ai/air_knn/">Air_knn</a>].</p><h3>Gathering the data</h3><p>Scraping data from Airbnb is no simple task, especially when you’re aiming to gather precise geolocated information. I discovered that by supplying two coordinate points to the Airbnb search <a href="https://www.airbnb.com/s/Conquistadores--Medellin--Antioquia/homes?tab_id=home_tab&amp;refinement_paths%5B%5D=%2Fhomes&amp;flexible_trip_lengths%5B%5D=one_week&amp;monthly_start_date=2024-11-01&amp;monthly_length=3&amp;monthly_end_date=2025-02-01&amp;price_filter_input_type=0&amp;date_picker_type=calendar&amp;source=structured_search_input_header&amp;search_type=user_map_move&amp;search_mode=regular_search&amp;price_filter_num_nights=5&amp;ne_lat=6.242358&amp;ne_lng=-75.5678&amp;sw_lat=6.2380977&amp;sw_lng=-75.573948&amp;zoom=16.63209180780258&amp;zoom_level=16.63209180780258&amp;search_by_map=true">URL</a>, you can retrieve listings within that specific rectangular area. By providing the northeast and southwest points like this :</p><pre>ne_lat={ne_lat}&amp;ne_lng={ne_lon}&amp;sw_lat={sw_lat}&amp;sw_lng={sw_lon}</pre><p>Airbnb generates a map view where each listing is accompanied by its exact coordinates. This method ensures you know the precise location of each listing and can accurately capture their coordinates.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*gtENGM1z6T47wyXg" /></figure><p>Thanks to H3 library from Uber I get to divide Medellin main Neighborhoods (<a href="https://files-nuproxa.nyc3.digitaloceanspaces.com/Public/laureles_map.html">Laureles</a> and <a href="https://files-nuproxa.nyc3.digitaloceanspaces.com/Public/poblado_map.html">Poblado</a> ).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*p5m-gMioYu7E-Yf1RO8tiw.png" /><figcaption>Laureles hexs</figcaption></figure><p>By using this approach, I was able to efficiently optimize the search for listings and extract their coordinates and features. As a result, I successfully gathered data from 2,380 listings, complete with all relevant characteristics. Now, it’s time to move on to creating the estimation model and suggesting optimal prices.</p><h3>Pricing model</h3><p>With all this data in hand, my next step was to develop a generalized model to explore the relationship between occupancy and price per night. The aim was to estimate the optimal price that would maximize revenue by balancing price and occupancy.</p><p>Airbnb listings come with a wide variety of amenities, but for this initial model, I chose to focus on a few key features to clearly understand the relationship between price and occupancy. Therefore, the model considered factors like the number of beds, guests, baths, location, and price.</p><p>As I ran the first model, I noticed collinearity between the price per night and the number of guests. To address this, I opted to use the price per guest per night instead.</p><h3>Beta regression</h3><p>The initial model I tested was a beta regression model, which is similar to linear regression but restricted to producing outcomes (Y) between 0 and 1. By evaluating the Mean Absolute Percentage Error (MAPE) through cross-validation, I found that this straightforward model achieved an error rate below 23%. While not perfect, this level of accuracy is sufficient to begin testing some hypotheses.</p><pre># Step 3: Set up K-Fold cross-validation<br>kf = KFold(n_splits=5, shuffle=True, random_state=42)<br>mae_scores = []<br>test_df = test_df[[&#39;occupancy&#39; , &#39;price_per_guest&#39; , &#39;number_of_beds&#39; , &#39;number_of_bathrooms&#39; ]]<br># Step 4: Perform manual cross-validation<br>for train_index, test_index in kf.split(test_df):<br>    # Split data<br>    train_data, test_data = test_df.iloc[train_index], test_df.iloc[test_index]<br><br>    # Fit a Beta regression model (using GLM with logit link for Beta distribution)<br>    model = glm(formula=&#39;occupancy ~ price_per_guest + number_of_beds + number_of_bathrooms  &#39;, <br>                data=test_df, <br>                family=Binomial()).fit()<br>    <br>    # Predict on test data<br>    predictions = model.predict(test_data)<br><br>    # Clip predictions to avoid values outside (0, 1)<br>    predictions = np.clip(predictions, 1e-5, 1 - 1e-5)<br><br>    # Step 5: Calculate MAE for this fold<br>    mae = mean_absolute_error(test_data[&#39;occupancy&#39;], predictions)<br>    mae_scores.append(mae)<br><br><br>print(f&quot;Mean MAE across 5 folds: {np.mean(mae_scores)}&quot;)<br>print(f&quot;Standard Deviation of MAE: {np.std(mae_scores)}&quot;)</pre><p>I aimed to use the estimated coefficient for price per guest to determine the demand elasticity. However, since the model assumes linearity, it didn’t accurately capture the diminishing returns associated with marginal price changes. As a result, the elasticity estimation wasn’t reliable.</p><h3>Random forest regression</h3><p>The next step involved using Random Forest Regression to explore how different pricing scenarios affect occupancy. By adjusting the price input and observing the changes in occupancy, I could calculate the percentage change in occupancy relative to price changes to estimate price elasticity. This approach captures complex, non-linear interactions, helping me understand how occupancy varies with different prices to create effective pricing strategies. However, it didn’t work as well as expected because I initially overlooked important features that influence price, such as amenities and image quality (with models like Vision language models or captioning models ), which reflect the apartment’s luxury and decor. I’ll address these factors in the next model, but for now, I needed something simple and effective to deploy quickly.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*epi5a0YtOBYkE2cbIFnvng.png" /><figcaption>Partial Dependence of Occupancy on Price</figcaption></figure><h3>K nearest Neighbors</h3><p>Ultimately, the best approach for analyzing price versus occupancy for similar listings was to use the K-Nearest Neighbors (KNN) method. By identifying the most similar listings in the area, I could estimate their revenue based on their price per guest and occupancy rates. This allowed me to pinpoint the optimal balance where price and occupancy levels maximize revenue. Consequently, this method provided a suggested price per night, a revenue estimate, and a list of comparable nearby listings.</p><h3><strong>Conclusions</strong></h3><p>While this model isn’t perfect, it offers a starting point for Airbnb entrepreneurs to estimate occupancy and pricing. Although it’s missing a lot of information, it helped us gauge how competitive our listing is and set expectations for our investment.</p><p>For future models, I plan to incorporate several improvements:</p><ul><li>Add amenities to the features, which will require more data to enhance prediction accuracy.</li><li>Schedule the scraper to continuously update occupancy metrics, providing more accurate insights over time.</li><li>Use vision and captioning models to analyze images and extract features related to home decor, luxury, and other amenities.</li><li>Expand the model to include more cities, allowing more users to make well-informed decisions.</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d9ce281ab66e" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Optimizing our delivery process with Data Science]]></title>
            <link>https://medium.com/mercadoni-tech/optimizing-our-delivery-process-with-data-science-82b657621bd1?source=rss-16da43fa2618------2</link>
            <guid isPermaLink="false">https://medium.com/p/82b657621bd1</guid>
            <category><![CDATA[mercadoni]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[Sebastian Cajamarca]]></dc:creator>
            <pubDate>Sat, 25 Aug 2018 01:21:15 GMT</pubDate>
            <atom:updated>2018-08-27T11:18:50.315Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/600/0*f4h1LBIPeUEAat8F" /></figure><p>At Mercadoni we are changing how customers buy groceries in Latin America. Currently, we have partnered with more than 80% of the biggest retailers in Colombia, Mexico, and Argentina, giving us the possibility of delivering groceries from +200 different locations in Latam. In a weekly basis, our +3k shoppers are buying and delivering +100k different products from our retailers all over Latam. Failing on doing this process on time implies not only missing a customer expectation but also delaying the following scheduled orders and messing up our operations.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/780/1*WZG8CYMDCRoE52B2EjExQg.png" /><figcaption><strong>Fig. 1:</strong> Our delivery process — Shoppers drive to the store and pick the products. When the picking is done, we transfer them money to a debit card. Then, they are able to pay to the cashier to purchase the order, and finally deliver it.</figcaption></figure><p>As simple as our delivery process may seem (see Fig. 1), we were having a huge problem at the moment we used to transfer money to the debit cards of our shoppers when they were about to pay at the supermarket cashier: In about 40% of our daily orders, we were sending less money than the shopper needed. This turned out in huge delays of our process since our shoppers had to wait for someone to manually transfer them the missing money (with thousands of orders per day, this process could take up to hours) and, on top of that, retailers were really pissed off since our shoppers were blocking their cashiers and their customers were unhappy about it.</p><p>To give you guys some context, the nature of this problem derives from data inconsistencies between the time our customers make an order and the moment our shoppers pick the products: (1) Prices vary daily in supermarkets, thus a price that you saw in our app may change with a given probability. (2) Prices of products that are charged by weight such as fruits and vegetables are very difficult to predict since shoppers may choose approximate amounts of the products when picking them. (3) Customers may ask for special products that are not shown in the app or change products when the shopper is picking. The total at the cashier will be for sure different in these cases.</p><p>The first solution that we tried was driven by our mythical entrepreneur common sense: A “quick win” fixed percentage increase to every money transfer. A simple excel analysis showed that a linear 25% increase would ensure 70% of the orders could be paid in the cashier… However, as our provider charges us per any amount transfer to debit cards, this cost increased by more than 25% the month we did it. In addition, giving more money to our shoppers increased fraud. Some of them used to accumulate money in their debit cards, then they bought things for them at supermarkets, and then they disappeared. At the end, the solution was generating more problems than the original problem :(</p><p>Frustrated by our common sense, we decided to use data science to solve this situation. To be honest, at the beginning it was difficult to convince the team. In startups like ours, we are obsessed with speed. And an exploratory data analysis with no clear deadlines is like Voldemort in this environment. This article is the first of many that we want to publish to change this wrong belief. Data Science and Machine Learning should not be confused with complexity. On the contrary, it is a synonym of scalability and optimization. At the end, we solved the problem in less time, and with better results than expected.</p><h4>1. A mathematical problem</h4><p>The first thing we did was to define our problem in mathematical terms. Particularly, we can see it as an<em> optimization problem</em> where <em>the objective value</em> is the money we transfer. In other words, we must find a<em> function</em> in terms of <em>several dimensions</em> such as order price, number of products, retailer, type of products, country, etc., such that we can <em>optimize the money we transfer</em> considering <em>2 major costs</em>: transaction fees and time (See Fig. 2).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KRfk9qY0h-oTl72eTERmAg.png" /><figcaption><strong>Fig. 2. </strong>Definition of the problem. If we transfer less money than the order price, we sacrifice time. If we transfer more we sacrifice transaction costs.</figcaption></figure><h4>2. Our baseline</h4><p>As Peter Drucker once wrote “<em>what gets measured, gets managed</em>”, in data we like to say “<em>what gets measured, gets improved</em>”. The second thing we did was to measure the <em>baseline of our major costs (transaction fees and time delay per underestimating)</em>. The objective of this is to keep track of given metrics in order to discern whether our decisions incrementally optimize our function or not. In the case of <em>time delay</em>, we chose to measure the number of manual transfers as it is directly correlated with time, and it was easier to track. In fact, one order with manual transfer increases its delivery time in +25 minutes.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*AJ4GpODFck8w8r9j" /><figcaption><strong>Fig 3.</strong> Manual transfers to shoppers’ debit cards</figcaption></figure><p>When we started this project, <em>manual transfers</em> were around 35–40% (See Fig. 3). We set our goal aggressively in 5%. In the case of <em>transactional fees</em>, we set a goal of a 40% decrease.</p><h4>3. Exploratory data analysis</h4><p>With our goals set and a clearly defined problem scope, now it is the time for exploring data. The idea behind this is to find the features of our model. That means, the inputs that generate the most impact to the function we are optimizing. Choosing these features well improves the prediction accuracy of the function model we are going to implement. Throughout this process, we found more than 20 features.</p><p>Just to mention a couple of examples in this step, we started by exploring the differences between the real price for the orders and our predictions depending on the supermarket.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/920/0*ur4bIwh_EujCCMjK" /><figcaption><strong>Fig 4.</strong> Price difference box plot</figcaption></figure><ul><li>We found that retailers that are specialized in fruits and vegetables registered more differences between our prediction and the real price of our orders. So, we defined the <em>retailer type</em> as one of the features.</li><li>We also discerned that retailers that update stock frequently in Mercadoni registered the least amount of differences between our prediction and the real price of our orders. Thus, an important feature for our model is the <em>stock update frequency</em>.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/653/1*7ks_9Jpj4bZOqp1nitG48g.png" /><figcaption><strong>Fig 5.</strong> Number of products reported as <em>not found</em> vs price differences box plot and density plot</figcaption></figure><p>We also explored correlations between the orders in which our shoppers do not find some of the products customer ordered and the price difference of our predictions (See Fig. 5). The more they report products as <em>not found </em>or replace, the more variation we have. Consequently, another feature was the <em>number of not found products in a given retailer</em>.</p><h3>Model definition and testing</h3><p>The last part of this process is to create our data model. This is to implement a function that, depending on the features we defined in step 2, is going to predict an optimized value for the money we transfer. We also have to consider that this function is going to be used many times per day, even per minute. Thus, we chose to clean some of our features and implement a not so complex function using <strong>regressions. </strong>In particular, we minimized the mean square error (<strong>MSE</strong>) with an extra constraint in mind: ensure that 90% of our estimation was above the real value.</p><p>But a simple linear regression wasn’t enough. It will tend to centralize the error and we need to ensure 90% of the estimation to be above the value avoiding increasing fees in transaction. For this case in particular, <strong>quantile regression</strong> was the best solution because it ensures the estimation for a quintile.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/588/0*3G3yUEMD7s0XTJ-Z" /><figcaption><strong>Fig 6.</strong> The red line represent a quantile regression q = 90 and the blue line is a linear regression</figcaption></figure><p>As we tested, we saw that it slightly increase the <strong>MSE</strong> but it ensures that almost all of our shoppers will have their money on time. For those transactions we have doubts they will be assigned to manual support.</p><h3>Conclusions</h3><p>The main things we learnt with this project were :</p><ol><li>With a good problem definition you will have key metrics to validate and a baseline</li><li>Data visualization allows you to test your hypothesis fast and build better features for your model</li><li>You are not seeking the best MSE or accuracy. You are seeking business metrics instead. Cost reduction, automation and process on time</li><li>Simple and fast data science service let you scale and validate at a good pace</li></ol><p>The services had been up for almost 2 months. We reduced almost 70% of our expenditure on fees and reduced in about 80% the amount of manual transfers.</p><p>Many other data science processes have to be leveraged with manual processes such as data labeling, and for that reason we are now launching a game that will help us labeling products and prices. We are just scratching the surface of Data Science. Come, <a href="/service/mailto:sebastian.cajamarca@mercadoni.com">join us</a> and help us shape the future of groceries in Latam.</p><p><em>Special thanks to David Camargo and Camilo Jiménez</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=82b657621bd1" width="1" height="1" alt=""><hr><p><a href="https://medium.com/mercadoni-tech/optimizing-our-delivery-process-with-data-science-82b657621bd1">Optimizing our delivery process with Data Science</a> was originally published in <a href="https://medium.com/mercadoni-tech">Mercadoni Tech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>