<?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: Rom Matetzky</title>
    <description>The latest articles on DEV Community by Rom Matetzky (@rom_matetzky_436dce893285).</description>
    <link>https://dev.to/rom_matetzky_436dce893285</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%2F4244618%2F4e230546-69a7-43ef-a6fd-526795482a8d.png</url>
      <title>DEV Community: Rom Matetzky</title>
      <link>https://dev.to/rom_matetzky_436dce893285</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rom_matetzky_436dce893285"/>
    <language>en</language>
    <item>
      <title>Running coding agents on a task graph instead of one long chat</title>
      <dc:creator>Rom Matetzky</dc:creator>
      <pubDate>Sat, 14 Nov 2026 14:31:41 +0000</pubDate>
      <link>https://dev.to/rom_matetzky_436dce893285/running-coding-agents-on-a-task-graph-instead-of-one-long-chat-1lcf</link>
      <guid>https://dev.to/rom_matetzky_436dce893285/running-coding-agents-on-a-task-graph-instead-of-one-long-chat-1lcf</guid>
      <description>&lt;h2&gt;
  
  
  The idea
&lt;/h2&gt;

&lt;p&gt;A feature usually breaks down into slices like this:&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;graph LR
  T1[1. Data model] --&amp;gt; T2[2. API endpoint]
  T1 --&amp;gt; T3[3. Background job]
  T2 --&amp;gt; T4[4. UI page]
  T3 --&amp;gt; T4
  T4 --&amp;gt; V[Validate merged result]
  V --&amp;gt; R[Code reviewer + live tester]
  R --&amp;gt; F[Fixer]&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Tasks 2 and 3 don't depend on each other, so there is no reason for them to wait. Task 4 needs both. Once everything is merged, the result as a whole gets checked.&lt;/p&gt;

&lt;p&gt;Each task is a small JSON file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"## Export endpoint\n\nImplement `GET /export` ...\n\n## Acceptance criteria\n- ..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"3"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;content&lt;/code&gt; is meant to be a full, self-contained issue, because the agent working on it doesn't get to ask you questions mid-run.&lt;/p&gt;

&lt;h2&gt;
  
  
  How a run works
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Spec first.&lt;/strong&gt; You start from a PRD. graph-execution ships agent skills for this: &lt;code&gt;to-spec&lt;/code&gt; writes the spec and asks you every question that would otherwise need a human during the run, then waits for your approval. &lt;code&gt;to-tasks&lt;/code&gt; turns the approved spec into the task folder and a test plan.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parallel agents.&lt;/strong&gt; Independent tasks run at the same time, each agent in its own git worktree. When a task finishes it merges into an integration branch, &lt;code&gt;graph/&amp;lt;run-id&amp;gt;&lt;/code&gt;, and only then do the tasks that depend on it start. Concurrency defaults to 3.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A validation check on every task.&lt;/strong&gt; By default, each task has to pass your gate (whatever you put in &lt;code&gt;validate&lt;/code&gt;: build, lint, tests) before it merges.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One review of the whole result.&lt;/strong&gt; After &lt;em&gt;all&lt;/em&gt; tasks have merged, the gate runs again on the merged branch, because tasks that pass on their own can still break together. Then one code reviewer and one live tester run in parallel, each in a fresh throwaway worktree. They get the full spec. The reviewer also gets the diff, and the tester gets the changed files and the test plan. This happens once for the merged graph, not on each task.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fixer.&lt;/strong&gt; If there are open blockers or majors, a fixer agent gets both reports and the spec, commits fixes, validation runs again, and the reviewers re-check. That repeats for up to 3 fix passes by default. Minor findings go into the summary and never trigger a fix.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The run is resumable. If something dies halfway, &lt;code&gt;graph-execution --resume&lt;/code&gt; picks it up, with git as the source of truth: a task counts as merged only if its merge commit is still on the branch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Any agent
&lt;/h2&gt;

&lt;p&gt;It works with Claude Code, Codex, OpenCode or Qwen Code, chosen per run with &lt;code&gt;--provider claude|codex|opencode|qwen&lt;/code&gt;. The provider CLI just needs to be on your &lt;code&gt;PATH&lt;/code&gt; and already logged in. graph-execution stores no credentials.&lt;/p&gt;

&lt;h2&gt;
  
  
  The web app
&lt;/h2&gt;

&lt;p&gt;The CLI is the engine, but most of the time I use the web app that comes in the same package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm install -g graph-execution &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; graph-execution manager
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It listens on &lt;code&gt;http://127.0.0.1:7420&lt;/code&gt;, prints a generated password and opens the browser. From there you connect GitHub or GitLab with a personal access token, clone a repo into a workspace, and open a terminal in it (Claude Code, Codex, OpenCode, Qwen Code or a plain shell). You plan the tasks from a PRD in that terminal while the spec file opens next to it as it's written.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Start run&lt;/strong&gt; takes the spec and the tasks folder. Then you watch the run live: the graph draws every task plus the validate, reviewer and tester, fixer and apply steps as nodes. When the run is applied, &lt;strong&gt;Create PR&lt;/strong&gt; (or &lt;strong&gt;Create MR&lt;/strong&gt; on GitLab) opens the pull request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Human review, if you want it
&lt;/h2&gt;

&lt;p&gt;Human review is off by default. Turn it on with &lt;code&gt;--human-review&lt;/code&gt;, &lt;code&gt;"humanReview": true&lt;/code&gt; in the config, or the human review option in Start run. The run then pauses before applying anything and shows the final diff in a Review tab.&lt;/p&gt;

&lt;p&gt;You don't edit the result yourself. You leave comments: line comments, file comments, general comments, even GitHub-style suggestions. Then you press &lt;strong&gt;Request changes&lt;/strong&gt;. Your comments become blocker findings, the fixer works on them first, and validation, the code reviewer and the live tester run again. The next pause shows how each comment was handled: the fixer's note and the reviewer's verdict with evidence. You decide whether to resolve or reopen.&lt;/p&gt;

&lt;p&gt;If you know what you care about up front, put it in a &lt;code&gt;REVIEW.md&lt;/code&gt; at the repo root. The code reviewer reads it in its prompt, along with &lt;code&gt;TESTING.md&lt;/code&gt; for the tester.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick start with the CLI
&lt;/h2&gt;

&lt;p&gt;You need Node.js 20+, git with a commit identity, and one logged-in provider CLI. In the repo you want to change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mkdir -p tasks
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'# Hello\n\nThe repo has a hello.txt file that says "Hello, world".\n'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; PRD.md
cat &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; tasks/1.json &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="s1"&gt;'JSON'&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"id"&lt;/span&gt;: &lt;span class="s2"&gt;"1"&lt;/span&gt;, &lt;span class="s2"&gt;"content"&lt;/span&gt;: &lt;span class="s2"&gt;"Create hello.txt containing exactly: Hello, world"&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
JSON

npx graph-execution ./tasks --spec PRD.md --provider claude
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For real work, let your agent write the spec and tasks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;graph-execution install skills --target claude
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then add &lt;code&gt;--web&lt;/code&gt; to a run to follow it in the browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  Built with itself
&lt;/h2&gt;

&lt;p&gt;graph-execution is developed with graph-execution. Every feature started as a spec and shipped as a run. The specs are in &lt;code&gt;docs/prd/done/&lt;/code&gt; and the task graphs in &lt;code&gt;.agents/tasks/&lt;/code&gt; in the repo, if you want to see what real inputs look like.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feedback welcome
&lt;/h2&gt;

&lt;p&gt;I'd really like to hear from people running agents on bigger features. How do you split the work today? Where would a graph like this get in your way? Bug reports and "this didn't work on my repo" are just as useful.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;npm: &lt;a href="https://www.npmjs.com/package/graph-execution" rel="noopener noreferrer"&gt;graph-execution&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/romm0109/graph-execution" rel="noopener noreferrer"&gt;romm0109/graph-execution&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>typescript</category>
      <category>opensource</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
