<?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: Murali Gour</title>
    <description>The latest articles on DEV Community by Murali Gour (@murali_gour_13cd7a6a6db2c).</description>
    <link>https://dev.to/murali_gour_13cd7a6a6db2c</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3907811%2F5fdeae3c-ecdb-494d-9ed1-55af1ca265e3.png</url>
      <title>DEV Community: Murali Gour</title>
      <link>https://dev.to/murali_gour_13cd7a6a6db2c</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/murali_gour_13cd7a6a6db2c"/>
    <language>en</language>
    <item>
      <title>Talking to Salesforce Through MCP: How We Solved the Context Bloat Problem</title>
      <dc:creator>Murali Gour</dc:creator>
      <pubDate>Tue, 11 Aug 2026 12:56:20 +0000</pubDate>
      <link>https://dev.to/murali_gour_13cd7a6a6db2c/talking-to-salesforce-through-mcp-how-we-solved-the-context-bloat-problem-1n7a</link>
      <guid>https://dev.to/murali_gour_13cd7a6a6db2c/talking-to-salesforce-through-mcp-how-we-solved-the-context-bloat-problem-1n7a</guid>
      <description>&lt;p&gt;Salesforce has a huge API surface. Objects, fields, flows, custom actions — it goes deep. When we started building our &lt;a href="https://datagrout.ai/integrations/salesforce-mcp-server" rel="noopener noreferrer"&gt;Salesforce MCP integration&lt;/a&gt; on top of it, we ran into a design conundrum.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option A:&lt;/strong&gt; Expose a handful of generic tools.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pro: The agent avoids context bloat.&lt;/li&gt;
&lt;li&gt;Con: You lose the granular control, predictable outputs, and security enforcement that enterprise workflows actually need.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Option B:&lt;/strong&gt; Expose 100s of specific tools, one per object and one per action.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pro: You get the precision and auditability you need.&lt;/li&gt;
&lt;li&gt;Con: The agent's context window fills up with schemas before it has done any real work.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We built DataGrout’s Conduit SDK around the idea that you shouldn’t have to pick one or the other. This post walks through the design we used and what tradeoffs you still need to account for.&lt;/p&gt;

&lt;h2&gt;
  
  
  The trade-off: granularity vs. context efficiency
&lt;/h2&gt;

&lt;p&gt;A standard MCP call to tools/list gets back every tool the server exposes, and the model reasons over all of it before deciding what to call. That’s not an issue if your server has 10 tools. But if you’re running multi-system enterprise workflows where Salesforce, QuickBooks, and other connected systems are all wired to the same agent, you’re looking at a combined tool catalog with 100s of schemas that load into context on every single turn.&lt;/p&gt;

&lt;p&gt;Our answer in Conduit was to collapse the entire tool surface into two entry points:&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;datagrout.conduit&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://gateway.datagrout.ai/servers/{uuid}/mcp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;client&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="k"&gt;await&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;list_tools&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# -&amp;gt; [discovery.discover, discovery.perform]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of the model scanning 100s of schemas, it describes what it wants in plain language and a server-side discovery step resolves that to the right 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="n"&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="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;discover&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;find leads created this week with no owner&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This moves tool selection out of the LLM's context entirely. The upside is smaller prompts and cheaper calls. The tradeoff is that you’re now trusting a semantic matching step to pick the right tool. For read operations that’s fine. For anything destructive, test your edge cases before relying on it in production.&lt;/p&gt;

&lt;p&gt;The granular tools still exist underneath. They give you the control and governance layer. Conduit's intelligence layer just makes sure they don’t all land in context at once.&lt;/p&gt;

&lt;h2&gt;
  
  
  Calling Salesforce tools directly
&lt;/h2&gt;

&lt;p&gt;If you already know which tool you need, skip discovery and call it directly. Tools are namespaced by integration and version:&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="k"&gt;await&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;call_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;salesforce@1/get_lead@1&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;id&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;00Q5f000003abcXYZ&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;We expose the same call shape across all five SDKs: Python, TypeScript, Rust, Elixir, and Ruby. The choice of language comes down to whatever your agent runtime already uses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Chaining actions across systems
&lt;/h2&gt;

&lt;p&gt;Single tool calls are easy. Where Conduit makes the biggest difference is multi-step workflows that span systems. The flow.run() primitive lets you chain tool calls and pass output from one step directly into the next:&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;outcome&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flow&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="n"&gt;plan&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;tool&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;salesforce@1/get_lead@1&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;args&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;id&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;00Q5f000003abcXYZ&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;tool&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;quickbooks@1/create_invoice@1&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;args&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;$prev.result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&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 step's output is in the next step's args. For example, you can look up a lead in Salesforce, which can then feed directly into an invoice creation in QuickBooks. Two completely separate systems in one agent call.&lt;/p&gt;

&lt;p&gt;For anything with financial or irreversible side effects, insert an approval gate before the write happens:&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;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;request_approval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;create invoice from lead 00Q5f000003abcXYZ&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;First invoice for this account, needs manual sign-off&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;We built this because giving an agent the keys to take financial actions unsupervised introduces risks that aren’t worth taking for enterprise teams. At least not yet. The approval gate keeps a human in the loop without breaking the workflow entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authentication: built for agents that run unattended
&lt;/h2&gt;

&lt;p&gt;Conduit supports bearer tokens, OAuth 2.1 client credentials, and mTLS across all five SDKs. The tool calls look identical regardless of which auth method you pick.&lt;/p&gt;

&lt;p&gt;The mTLS path is the one we recommend for production agents that run unattended for extended periods:&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;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&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;bootstrap_identity&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://gateway.datagrout.ai/servers/{uuid}/mcp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

&lt;span class="n"&gt;auth_token&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-access-token&lt;/span&gt;&lt;span class="sh"&gt;"&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;my-agent&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;# subsequent runs auto-discover the cert from ~/.conduit/
&lt;/span&gt;
&lt;span class="c1"&gt;# no token refresh logic needed
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The private key is generated locally and never leaves your machine. Our CA signs a certificate binding the public key to a named agent identity. This matters in practice because bearer tokens in env vars are the thing that gets rotated incorrectly at 2 am and takes down your production agent. With mTLS, you don’t have to maintain refresh logic and you’re not leaving a long-lived secret sitting in an environment variable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it yourself
&lt;/h2&gt;

&lt;p&gt;Check out &lt;a href="https://github.com/DataGrout/conduit-sdk" rel="noopener noreferrer"&gt;Conduit SDK on GitHub&lt;/a&gt; and share any feedback. There are installation instructions for all five languages, and the quick start gets you to a working Salesforce tool call in under five minutes. If it’s useful, give it a star so others can discover it.&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>salesforce</category>
      <category>contextbloat</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Why your AI agent should never do its own math</title>
      <dc:creator>Murali Gour</dc:creator>
      <pubDate>Thu, 06 Aug 2026 14:23:33 +0000</pubDate>
      <link>https://dev.to/murali_gour_13cd7a6a6db2c/why-your-ai-agent-should-never-do-its-own-math-3258</link>
      <guid>https://dev.to/murali_gour_13cd7a6a6db2c/why-your-ai-agent-should-never-do-its-own-math-3258</guid>
      <description>&lt;p&gt;I want to talk about a problem that comes up constantly in production AI agent systems, and gets far less attention than it deserves.&lt;/p&gt;

&lt;p&gt;LLMs are bad at math. Not always, not catastrophically, but unreliably enough that you should not be betting your agent's output on it.&lt;/p&gt;

&lt;p&gt;This is not a hot take. It is a well-documented limitation. Models drift on floating point operations, produce plausible-but-wrong statistical summaries, and give you different answers to the same calculation across runs. For exploratory work, this is fine. For agents making decisions based on numeric data, it is a real problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  The usual answer and why it is incomplete
&lt;/h3&gt;

&lt;p&gt;Most teams reach for a code execution tool. You give the agent access to a Python sandbox, and it writes and runs the calculation itself.&lt;/p&gt;

&lt;p&gt;This works for simple cases. It gets messy when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need reproducible results across agent runs (different seeds, non-deterministic execution)&lt;/li&gt;
&lt;li&gt;The math is part of a longer pipeline where output shape matters (the regression result needs to go directly into a chart tool)&lt;/li&gt;
&lt;li&gt;You are working with large arrays that you do not want to re-send through the model context on every step&lt;/li&gt;
&lt;li&gt;You need the operation to be verifiable, not just correct-looking&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What we built
&lt;/h3&gt;

&lt;p&gt;DataGrout Math is a set of MCP tools that cover the numeric operations agents actually need. Twelve tools across three categories.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Generation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;math.range&lt;/code&gt; — evenly-spaced sequences from start to stop with exact step computation to avoid cumulative float drift. Up to 10,000 values per call.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;math.linspace&lt;/code&gt; — generate exactly N points between two bounds, equivalent to NumPy's linspace.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;math.sequence&lt;/code&gt; — named mathematical sequences: arithmetic, geometric, Fibonacci, triangular, square, prime, and powers.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;math.sample&lt;/code&gt; — draw samples from uniform, normal, or exponential distributions. Pass a &lt;code&gt;seed&lt;/code&gt; for reproducible output across runs.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;math.interpolate&lt;/code&gt; — apply lerp, inverse lerp, clamp, remap, smoothstep, smootherstep, and with 12 easings + 6 modes (lerp, inverse_lerp, clamp, remap, smoothstep, smootherstep) = 18 modes&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analysis&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;math.describe&lt;/code&gt; — full descriptive statistics: count, mean, median, standard deviation, variance, min, max, sum, range, skewness, percentiles (p5 through p95), and a binned histogram. Up to 100,000 values per call.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;math.window&lt;/code&gt; — sliding window operations: moving average, moving sum, cumulative sum, first differences, percent change, lag, and EWMA with configurable alpha.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;math.normalize&lt;/code&gt; — z-score, min-max, and percentile rank normalization. Returns both normalized values and original values in records for comparison charting.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;math.outliers&lt;/code&gt; — IQR and z-score outlier detection. Returns outlier indices, threshold bounds, a clean array with outliers removed, and per-value boolean flags.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;math.rank&lt;/code&gt; — ordinal, dense, average, and percentile ranking with ascending or descending order.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Modeling&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;math.correlate&lt;/code&gt; — Pearson and Spearman correlation with r-squared, interpretation labels (strong positive, weak negative, etc.), and paired records for scatter plot visualization.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;math.trend&lt;/code&gt; — fit linear, polynomial (degree 2 through 5), exponential, and logarithmic regressions. Returns coefficients, r-squared, direction label, equation string, fitted values for overlay charting, and optional forward forecast points.&lt;/p&gt;

&lt;h3&gt;
  
  
  How it fits into an agent pipeline
&lt;/h3&gt;

&lt;p&gt;Every tool returns two output shapes: a &lt;code&gt;values&lt;/code&gt; array and a &lt;code&gt;records&lt;/code&gt; array. This is intentional.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;values&lt;/code&gt; feeds into other math tools. &lt;code&gt;records&lt;/code&gt; feeds directly into &lt;code&gt;prism.chart&lt;/code&gt; for visualization, no reshaping required.&lt;/p&gt;

&lt;p&gt;Tools also accept a &lt;code&gt;cache_ref&lt;/code&gt; parameter. If you ran a Data or Frame tool in a previous step and got a cache reference back, you pass that reference directly to a math tool. The array never goes back through the LLM context. This matters when you are working with datasets of any real size.&lt;/p&gt;

&lt;p&gt;Every response includes a deterministic receipt under &lt;code&gt;_meta.datagrout&lt;/code&gt;. The gateway verifies the result is reproducible. Same inputs always produce same outputs.&lt;/p&gt;

&lt;p&gt;All tools are versioned at &lt;code&gt;data-grout@1/math.*@1&lt;/code&gt;. You can pin your agent instructions to a specific version and they will not break when we ship updates.&lt;/p&gt;

&lt;h3&gt;
  
  
  A concrete example
&lt;/h3&gt;

&lt;p&gt;Here is a workflow that shows how these tools chain together.&lt;/p&gt;

&lt;p&gt;An agent pulls revenue records from a Salesforce integration. It passes the &lt;code&gt;cache_ref&lt;/code&gt; to &lt;code&gt;math.outliers&lt;/code&gt; to detect anomalous months using IQR. It takes the &lt;code&gt;clean_values&lt;/code&gt; output and passes it to &lt;code&gt;math.trend&lt;/code&gt; with a 3-step forecast. It pipes the &lt;code&gt;fitted&lt;/code&gt; records from trend into &lt;code&gt;prism.chart&lt;/code&gt; with the original values overlaid. The entire numeric pipeline runs without a single LLM token spent on arithmetic.&lt;/p&gt;

&lt;p&gt;That is the point. The agent's cognition is reserved for reasoning about the results, not computing them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting started
&lt;/h3&gt;

&lt;p&gt;DataGrout Math is available through the DataGrout MCP gateway. Connect your agent and call any tool at DataGrout.&lt;/p&gt;

&lt;p&gt;Full parameter reference and examples are in the documentation at library.datagrout.ai/math-tools.&lt;/p&gt;

&lt;p&gt;We launched on Product Hunt today if you want to follow along or leave feedback.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>llm</category>
      <category>devtools</category>
    </item>
    <item>
      <title>We Built Deterministic JSON Ops for AI Agents — The Problem It Solves</title>
      <dc:creator>Murali Gour</dc:creator>
      <pubDate>Thu, 18 Jun 2026 11:37:06 +0000</pubDate>
      <link>https://dev.to/murali_gour_13cd7a6a6db2c/we-built-deterministic-json-ops-for-ai-agents-the-problem-it-solves-1202</link>
      <guid>https://dev.to/murali_gour_13cd7a6a6db2c/we-built-deterministic-json-ops-for-ai-agents-the-problem-it-solves-1202</guid>
      <description>&lt;p&gt;Every AI agent that calls an external API hits the same wall.&lt;/p&gt;

&lt;p&gt;The response comes back as raw JSON, deeply nested, verbose, full of fields the agent doesn't need. Before the agent can reason over it or take any action, someone has to filter it, reshape it, maybe merge it with another payload.&lt;/p&gt;

&lt;p&gt;Most teams solve this one of three ways. They dump the raw JSON into the context window and let the LLM figure it out. They spin up a Python sidecar. Or they make an extra round-trip to a data service. None of these scale.&lt;/p&gt;

&lt;p&gt;We built DataGrout Data to eliminate all three.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Data does&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Data is a suite of deterministic JSON manipulation tools exposed as MCP tools, callable directly by any AI agent:&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="err"&gt;→&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;status&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;op&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eq&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;active&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;span class="err"&gt;→&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$prev.records&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;by&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;created_at&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;desc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;take&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$prev.records&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No Python. No extra runtime. Pure deterministic output the agent can immediately act on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The full operation set&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;data.filter — declarative filtering with 10+ operators (eq, neq, gte, lte, contains, starts_with, is_null...)&lt;br&gt;
data.sort — multi-field sorting with per-field direction control&lt;br&gt;
data.aggregate — reduce a field to a sum / mean / min / max / count.&lt;br&gt;
data.merge — combine two JSON datasets on a shared field&lt;br&gt;
data.flatten — simplify deeply nested payloads in one pass&lt;br&gt;
data.map — split large arrays into individual items for parallel processing&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why deterministic matters&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every Data operation is pure, no AI generation touches the transformation layer. The agent decides what to do, Data executes it exactly. This eliminates token waste and hallucination risk on the data layer entirely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it handles large datasets&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Data accepts cache_ref outputs, so agents can chain operations on large payloads without retransmitting the full dataset at each step. The output of data.filter passes as a ref into data.sort — not as raw JSON.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where it fits in the DataGrout suite&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Data handles raw JSON payloads from API responses. Frame handles columnar tabular data. Together they cover the two most common data shapes agents encounter in enterprise workflows.&lt;/p&gt;

&lt;p&gt;Launched on Product Hunt today, would love your support and feedback!&lt;/p&gt;

&lt;p&gt;👉 datagrout.ai/tools/data&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>agents</category>
      <category>devtools</category>
    </item>
    <item>
      <title>We built columnar data ops for AI agents — here's why and how</title>
      <dc:creator>Murali Gour</dc:creator>
      <pubDate>Thu, 04 Jun 2026 09:04:23 +0000</pubDate>
      <link>https://dev.to/murali_gour_13cd7a6a6db2c/we-built-columnar-data-ops-for-ai-agents-heres-why-and-how-2ff2</link>
      <guid>https://dev.to/murali_gour_13cd7a6a6db2c/we-built-columnar-data-ops-for-ai-agents-heres-why-and-how-2ff2</guid>
      <description>&lt;p&gt;If you've built an AI agent that touches real enterprise data, you've probably hit this wall.&lt;/p&gt;

&lt;p&gt;Your agent pulls 2,000 records from Salesforce. Now what? The model can't reliably filter, sort, or group 2,000 rows inside its context window. You don't want to dump all of it as raw JSON. And spinning up a Python runtime just to run a pandas filter feels like overkill for what should be a simple operation.&lt;/p&gt;

&lt;p&gt;This is the problem we kept running into at DataGrout. So we built Frame.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is Frame?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Frame is a suite of columnar data operations exposed as MCP tools — callable directly by any AI agent without a Python runtime, extra infrastructure, or round-trips to an analytics API.&lt;/p&gt;

&lt;p&gt;Here's what it looks like in practice. An agent receiving tabular records from a CRM can do this in a single workflow step:&lt;/p&gt;

&lt;p&gt;frame.filter({ payload, where: [{ field: "status", op: "eq", value: "active" }] })&lt;br&gt;
→ frame.sort({ payload: "$filter.records", by: [{ field: "revenue", dir: "desc" }] })&lt;br&gt;
→ frame.slice({ payload: "$sort.records", offset: 0, limit: 50 })&lt;/p&gt;

&lt;p&gt;No Python. No pandas. No external call. Pure deterministic output the agent can immediately act on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The full operation set&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;frame.filter — declarative row filtering with 10+ operators (eq, neq, gte, lte, contains, starts_with, is_null...)&lt;br&gt;
frame.sort — multi-column sorting with per-field direction control&lt;br&gt;
frame.group — aggregate by key, compute counts, sums, averages&lt;br&gt;
frame.pivot — reshape rows into columns for cross-tab analysis&lt;br&gt;
frame.join — merge two datasets on a shared key field&lt;br&gt;
frame.slice — page or window over large records&lt;br&gt;
frame.select — keep, drop, or rename columns in one pass&lt;br&gt;
Frame.pluck —extract one column into a flat array, dot-notation supported&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why deterministic matters&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One of the core design decisions with Frame was making every operation pure and deterministic. No AI generation touches the data transformation layer. The agent decides what to do, Frame executes it exactly. This eliminates a whole class of hallucination risk that comes with asking an LLM to reshape data directly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Handling large datasets&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Frame accepts cache_ref outputs from previous tool calls, so agents can operate on large paginated datasets without retransmitting the full payload each time. This was critical for production workflows where data sets run into tens of thousands of rows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it composes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Frame tools chain together natively via flow.into inside DataGrout workflows. The output of frame.filter feeds directly into frame.sort without any manual wiring. This composability is what makes it genuinely useful in multi-step agent workflows rather than just as a standalone utility.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where we are today&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Frame is live at datagrout.ai/tools/frame and We launched on &lt;a href="https://www.producthunt.com/products/datagrout-ai/launches/datagrout-frame" rel="noopener noreferrer"&gt;Product Hunt&lt;/a&gt; today — would appreciate your support if this is useful to you!&lt;br&gt;
We're actively building out the operation set. What data operations are you missing in your agent workflows? Drop them in the comments — we're reading everything.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>agents</category>
      <category>devtools</category>
    </item>
  </channel>
</rss>
