<?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: Rocking Eval</title>
    <description>The latest articles on DEV Community by Rocking Eval (@6e2baa41a8b2856).</description>
    <link>https://dev.to/6e2baa41a8b2856</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%2F3995009%2F56084a7e-f46e-416f-bf30-ac68c3fb493f.png</url>
      <title>DEV Community: Rocking Eval</title>
      <link>https://dev.to/6e2baa41a8b2856</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/6e2baa41a8b2856"/>
    <language>en</language>
    <item>
      <title>Coding Agents: Moving From "Bash Mimics" to "AST Manipulators"</title>
      <dc:creator>Rocking Eval</dc:creator>
      <pubDate>Sun, 21 Jun 2026 11:27:11 +0000</pubDate>
      <link>https://dev.to/6e2baa41a8b2856/coding-agents-moving-from-bash-mimics-to-ast-manipulators-1fc6</link>
      <guid>https://dev.to/6e2baa41a8b2856/coding-agents-moving-from-bash-mimics-to-ast-manipulators-1fc6</guid>
      <description>&lt;p&gt;In the last post, we killed the "Tool Abstraction" layer. By replacing 50 brittle JSON-RPC wrappers with a single eeva process (Elixir on the BEAM).&lt;/p&gt;

&lt;p&gt;Here is how we moved our agent from text-based hacking to actual AST-aware refactoring.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: The "Diff" Illusion
&lt;/h2&gt;

&lt;p&gt;Standard agents "edit" files by outputting search blocks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Plaintext
&amp;lt;&amp;lt;&amp;lt;&amp;lt; SEARCH
def hello_world, do: "hi"
==== REPLACE
def hello_world, do: "hello elixir"
&amp;gt;&amp;gt;&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is fundamentally broken. It relies on the model perfectly hallucinating the exact state of the file, including indentation, hidden newlines, and context. If the file has changed by one space since the last read, the entire operation fails. It is brittle, state-blind, and expensive. Coding agents are trying to work this out by introducing not so easy algorithms for multi-edits. Each time model changes a file, for the next edit it needs to read the file again. If this would be standard flow, it would cost you a huge amount of tokens to make it right. Coding agents try to fix it with a few ninja tricks by keeping last edits in memory and shifting next edits. But model doesnt know about this. Eventually, the simple operation of editing files becomes a guessing game both for model and for the harness. &lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: Pure Functional Piping
&lt;/h2&gt;

&lt;p&gt;We didn't solve this by introducing custom "edit primitives" or specialized editing tools. Writing unique tool APIs just forces you back into prompt engineering hell.&lt;/p&gt;

&lt;p&gt;Instead, we give the model full Elixir execution to edit files directly. Because the code is the tool, the model can execute a complete chain of multi-edits across multiple files in a single, atomic operation using standard language features.&lt;/p&gt;

&lt;p&gt;The model doesn't output raw diff blocks; it pipes the files through pure functional transformations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;elixir&lt;/span&gt;
&lt;span class="n"&gt;config_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"config/config.exs"&lt;/span&gt;

&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;":old_port, 4000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;":new_port, 8080"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="s2"&gt;"lib/workspace/"&lt;/span&gt;
&lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ls!&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ends_with?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"_worker.ex"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"lib/workspace/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"get_port(:old_port)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"get_port(:new_port)"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why This Breaks the Loop
&lt;/h2&gt;

&lt;p&gt;By using the raw programming language as the editing engine, we unlock a few massive architectural advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Zero Context Re-Reads&lt;br&gt;
The model does not need to execute an edit, wait for the harness to update, read the file again, and format a second diff. The state lives inside the Elixir evaluation stream. It can pipe the output of one file read directly into the modification of another, completing complex refactors in a single API call.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Localized Logic, Less Hallucinations&lt;br&gt;
The model doesn't need to guess line numbers or spaces. It writes native Elixir filters, regex matches, or map functions to locate exactly what it wants to change. The search logic is executed live by the BEAM runtime, completely removing the brittle dependency on matching precise whitespace layouts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Native Multitasking&lt;br&gt;
Because eeva executes inside a supervisor tree, this entire multi-edit code runs inside an isolated, transient BEAM process. If the model makes a logic error mid-stream, the process crashes safely, and the compiler drops the exact structural failure back into the context. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dynamic Introspection&lt;br&gt;
In a standard text-based setup, the model edits a file, hopes for the best, and then has to call a separate tool to run tests or verify syntax. If the edit broke a dependency three folders over, the agent is blind to it until the entire run crashes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With pure Elixir execution, the model can introspect its edits inline before finishing the operation. It can pipe its file mutations directly into the live compiler to verify the changes don't break the system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;elixir&lt;/span&gt;
&lt;span class="c1"&gt;# Edit the file, then verify the module still compiles in the same pass&lt;/span&gt;
&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"lib/math.ex"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"def add(a, b), do: a + b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"def add(a, b), do: b + a"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"lib/math.ex"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;# Live validation check before the token stream concludes&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;Code&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compile_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"lib/math.ex"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_modules&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Success"&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Failed compilation inline: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try it out: &lt;a href="https://github.com/beamcore/agent" rel="noopener noreferrer"&gt;https://github.com/beamcore/agent&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>elixir</category>
      <category>agents</category>
    </item>
    <item>
      <title>Coding Agents Suck at Tools</title>
      <dc:creator>Rocking Eval</dc:creator>
      <pubDate>Sun, 21 Jun 2026 08:18:29 +0000</pubDate>
      <link>https://dev.to/6e2baa41a8b2856/coding-agents-suck-at-tools-3jon</link>
      <guid>https://dev.to/6e2baa41a8b2856/coding-agents-suck-at-tools-3jon</guid>
      <description>&lt;p&gt;Open up the source code of any agent framework, harness, etc. Hermes, Copilot, Pi, Opencode  or whatever. &lt;br&gt;
You will find tools, tools everywhere.  &lt;br&gt;
Examples:  &lt;br&gt;
&lt;a href="https://github.com/NousResearch/hermes-agent/tree/main/tools%E2%80%A8https://github.com/anomalyco/opencode/tree/dev/packages/opencode/src/tool" rel="noopener noreferrer"&gt;https://github.com/NousResearch/hermes-agent/tree/main/tools https://github.com/anomalyco/opencode/tree/dev/packages/opencode/src/tool&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These are bash hooks, file viewers, file editors, greps, questions, tasks, web search.&lt;/p&gt;

&lt;p&gt;Your harness is a loop, and on each loop, all these tools and their individual instructions are injected in the context. That is why initial request using opencode is 10k tokens for no reason. &lt;/p&gt;

&lt;p&gt;Do we have problems with tools? Yes, and a lot.&lt;br&gt;
&lt;strong&gt;S&lt;/strong&gt;ome tools just don’t work properly, there are bugs there in these tools. Some don't count lines properly, some truncate files in order to save some tokens. Some invalidate cache, making your token/$ ratio worse. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;T&lt;/strong&gt;ool signatures differ from one harness to the other. And models absolutely suck at this. The longer session goes, the more model “forgets” and shifts its attention from this noisy tool descriptions. Harness starts failing on basic operations like finding files. Poor models drop into endless loops, eating your budget with no output at all. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;W&lt;/strong&gt;hen you force a model to context-switch between writing clean JavaScript and formatting a deviant, rigid JSON payload just to view a file, it all breaks down, and if not, its just not efficient. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;M&lt;/strong&gt;odels are not trained on every harness available, they are trained on bash and coding. That’s what they need to do, and that’s why Pi is so good. But it could be better! &lt;/p&gt;

&lt;p&gt;The failure peak is always file editing. Writing a file from scratch is a forward-flowing token stream, quite easy we guess. Editing an existing file requires the model to hold an exact mental map of the code's Abstract Syntax Tree (AST), match white-space indentation perfectly (tabs vs. spaces), and calculate precise line diffs.&lt;br&gt;
When poor models attempt a search-and-replace edit, it almost always misses a newline or a trailing brace. The harness rejects the edit. The model gets confused by the raw bash or parser error, loses its place in the file, and begins modifying the wrong lines entirely - corrupting the codebase until the context window is nothing but garbage. Tools produce garbage and pollute your context. The more tools harness has, the more unrelated garbage is in your context. &lt;/p&gt;

&lt;p&gt;We think we solved it. What if harness will just build code to edit other code? It’s already trained on doing that, kind of. So we decided to build a harness with only 1 “tool”, which is Elixir Eval. We call it eeva. &lt;/p&gt;

&lt;p&gt;Elixir is a perfect language for models. It both looks similar to bash, has the same “piping” behavior like bash, has very similar out of the box functions like File.ls or File.read. And it’s a clean functional language, models are very good at this. They are good both with bash, and with Elixir. They combine the knowledge and attention to solve tasks. Every time model fails to make an operation, harness feeds the model with always similar Elixir error traces. &lt;/p&gt;

&lt;p&gt;This seems like a small change, but it really flips the game a bit. The longer your agent is working, the longer the context, the more precise are the edits and operations. Instead of feeding the context with junk errors of random tools, we feed it with elixir compile errors, forcing model into elixir, basically “fine-tuning” it on the fly with high quality outputs and results.&lt;/p&gt;

&lt;p&gt;With bigger context all coding agents are failing eventually, even ours. But the ceiling is much higher this time.&lt;/p&gt;

&lt;p&gt;So if you wanna try this approach, take a shot: &lt;a href="https://github.com/beamcore/agent" rel="noopener noreferrer"&gt;https://github.com/beamcore/agent&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>elixir</category>
    </item>
  </channel>
</rss>
