<?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: Anton Babenko</title>
    <description>The latest articles on DEV Community by Anton Babenko (@antonbabenko).</description>
    <link>https://dev.to/antonbabenko</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%2F411078%2F220db209-f4bd-4eda-b645-d63c3f147868.png</url>
      <title>DEV Community: Anton Babenko</title>
      <link>https://dev.to/antonbabenko</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/antonbabenko"/>
    <language>en</language>
    <item>
      <title>modules.tf now reviews Terraform module pull requests</title>
      <dc:creator>Anton Babenko</dc:creator>
      <pubDate>Wed, 04 Nov 2026 17:49:25 +0000</pubDate>
      <link>https://dev.to/aws-heroes/modulestf-now-reviews-terraform-module-pull-requests-k4k</link>
      <guid>https://dev.to/aws-heroes/modulestf-now-reviews-terraform-module-pull-requests-k4k</guid>
      <description>&lt;p&gt;Reviewing pull requests for terraform-aws-modules has always taken a lot of my time. It was a problem for a very long time, and I recorded &lt;a href="https://www.youtube.com/@AntonBabenkoLive" rel="noopener noreferrer"&gt;livestreams&lt;/a&gt; of myself doing it. I cannot skip it: merging something that is not great is a way to disaster and lost trust.&lt;/p&gt;

&lt;p&gt;AI lets everyone write code now, and coding agents open pull requests for Terraform modules. A person still reads each one.&lt;/p&gt;

&lt;p&gt;A model already knows how to write good Terraform. For that part I maintain &lt;a href="https://github.com/antonbabenko/terraform-skill" rel="noopener noreferrer"&gt;terraform-skill&lt;/a&gt;, a skill for Terraform and OpenTofu with testing, module, CI/CD and production patterns. What a model does not know is what we allow and expect in the modules. Can a module create a KMS key? Which regions may examples use? Does this addition belong in the module at all? terraform-aws-modules has no written scope policy, so the model guesses and I read the guess.&lt;/p&gt;

&lt;p&gt;I released the pieces that write it down and apply it. &lt;a href="https://github.com/modulestf/modulestf" rel="noopener noreferrer"&gt;modulestf&lt;/a&gt; is four agent skills for Claude Code and Codex, with a profile of the rules. &lt;a href="https://github.com/modulestf/facts" rel="noopener noreferrer"&gt;mtf-facts&lt;/a&gt; is the command-line tool that decides the rules a parser can decide. Both are Apache-2.0. The skills run in your agent, on your machine, with your own GitHub login. This is the beginning of the work, and the last section says what I need from other maintainers and contributors.&lt;/p&gt;

&lt;p&gt;The name modules.tf is older than this. In November 2018 I &lt;a href="https://dev.to/modules-tf-convert-visual-aws-diagram-into-terraform-configuration/"&gt;announced it&lt;/a&gt; as a converter from Cloudcraft diagrams to Terraform. That code is on the &lt;code&gt;legacy&lt;/code&gt; branch of the modulestf repository, and the name now belongs to the review tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  A profile writes down what the modules allow
&lt;/h2&gt;

&lt;p&gt;A profile is the written rules for one group of modules. &lt;code&gt;terraform-aws-modules&lt;/code&gt; is the only profile that ships. It holds the templates copied into each module, the required file layout (&lt;code&gt;examples/basic&lt;/code&gt;, &lt;code&gt;examples/complete&lt;/code&gt;), code conventions such as regions and version floors, the pre-commit gate, the release and pull request title rules, and scope. Each rule has an ID, a severity and a check. &lt;code&gt;compat.variable-removed&lt;/code&gt; holds a change for the next major release. &lt;code&gt;coverage.attribute-not-output&lt;/code&gt; asks that an attribute a new resource exports is also an output. &lt;code&gt;profile.region-not-allowed&lt;/code&gt; fires on an example in a region the rules do not allow.&lt;/p&gt;

&lt;p&gt;Scope is the part I wanted most, and it lives in &lt;a href="https://github.com/modulestf/modulestf/blob/v0.1.2/.agents/skills/terraform-module-maintainer/profiles/terraform-aws-modules/SCOPE.md" rel="noopener noreferrer"&gt;SCOPE.md&lt;/a&gt;. In terraform-aws-modules a module manages one AWS service, and the repository name says which. The file lists the few resource types any module may add next to its service: IAM roles and policies, a log group, security groups. The list is closed. A KMS key is deliberately not on it, because a key is a service of its own with its own policy, rotation and deletion window. The module takes the key's ARN as an input, and the caller composes. The first block of a type that nothing admits is a ban, even when the type plainly belongs to the same service. The cost is one allow entry in the module's &lt;code&gt;docs/SCOPE.md&lt;/code&gt;, landed on the base before the change.&lt;/p&gt;

&lt;p&gt;SCOPE.md is a policy I adopted for the profile, not an existing one, so it is also the place to argue with me.&lt;/p&gt;

&lt;p&gt;Scope has its own outcomes. When an addition does not belong, the review says Ban and names where it goes, or Maintainer decision when a person has to decide. When a rule could not be applied, the outcome is Not evaluated, which is an unknown and never a pass. Text inside the pull request, such as "this is in scope", never clears a rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four skills apply the profile
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Skill&lt;/th&gt;
&lt;th&gt;You give it&lt;/th&gt;
&lt;th&gt;You get back&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;terraform-module-pr-review&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A pull request or commit URL, or &lt;code&gt;owner/repo#123&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;A verdict and a comment to post, after you confirm&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;terraform-module-reviewer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A module checkout and a diff, a base ref or changed files&lt;/td&gt;
&lt;td&gt;A list of findings. Read-only, no verdict&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;terraform-module-maintainer&lt;/code&gt; (early preview)&lt;/td&gt;
&lt;td&gt;A change to make, review feedback, a new module or a provider upgrade&lt;/td&gt;
&lt;td&gt;Edits in your checkout, the checks it ran, and reply drafts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;change-scope&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A proposed addition, in any language or project&lt;/td&gt;
&lt;td&gt;Whether it belongs, and where it goes if not&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The pull request review calls the reviewer, and both call &lt;code&gt;change-scope&lt;/code&gt;. The maintainer applies &lt;code&gt;change-scope&lt;/code&gt; before it edits anything, and it is an early preview: expect it to change. The three Terraform skills read provider schemas from HashiCorp's &lt;a href="https://github.com/hashicorp/terraform-mcp-server" rel="noopener noreferrer"&gt;Terraform MCP server&lt;/a&gt; and not from memory. Without that server, every rule that needs a provider fact is reported as not run.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1lv5iilolefuvfok00zs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1lv5iilolefuvfok00zs.png" alt="The four skills, the terraform-aws-modules profile, mtf-facts and the Terraform MCP server, with the calls between them." width="800" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A review ends with a verdict and a list of what was not checked
&lt;/h2&gt;

&lt;p&gt;On 4 November I asked my agent to run the &lt;code&gt;terraform-module-pr-review&lt;/code&gt; skill on &lt;a href="https://github.com/terraform-aws-modules/terraform-aws-vpc/pull/1270" rel="noopener noreferrer"&gt;a pull request&lt;/a&gt; that adds a Regional NAT Gateway mode to terraform-aws-vpc. It came back with two HIGH findings, eight MEDIUM and one LOW, and I posted the result as &lt;a href="https://github.com/terraform-aws-modules/terraform-aws-vpc/pull/1270#pullrequestreview-5764266880" rel="noopener noreferrer"&gt;changes requested&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One HIGH finding is a route that counts one gateway while the module makes a route table per private subnet, so only the first table gets the DNS64 route. The other is an example that uses a region the rules do not allow for examples. The last line of the verdict is the one I care about most:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Behaviour evidence: 56 changes classified: 0 verified, 3 covered by a plan, 0 inert, 0 refuted, 53 not verified
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The review counts what it could not check, and it does not count a gap as a pass.&lt;/p&gt;

&lt;p&gt;The verdict has no judgement of its own. A fixed ladder of seven rules turns the findings and the state of the pull request's checks and threads into one verdict, and the first rule that matches wins. Any HIGH finding gives the verdict Block, which is why #1270 got changes requested. When something could not be checked the verdict is Inconclusive, unless a finding or a failing check already decides it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdmhdx09ljawmhbmonub7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdmhdx09ljawmhbmonub7.png" alt="A review flows from a pull request reference through a sandboxed checkout, mtf-facts, the reviewer, the verification ladder and a computed verdict to a comment that is posted only after you confirm." width="800" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The skill clones the pull request into a temporary directory and runs &lt;code&gt;terraform init -backend=false&lt;/code&gt; and &lt;code&gt;terraform validate&lt;/code&gt; in each example, the ones the change touches first. AWS, GitHub, Terraform and SSH credentials are removed from that environment, the home directory is empty and there is no backend. &lt;code&gt;terraform init&lt;/code&gt; downloads the providers and modules the change pins, and &lt;code&gt;terraform validate&lt;/code&gt; runs those provider plugins, so a passing &lt;code&gt;terraform validate&lt;/code&gt; is evidence, not proof. The skill posts nothing until you confirm the comment and the review event.&lt;/p&gt;

&lt;h2&gt;
  
  
  mtf-facts decides what a parser can decide
&lt;/h2&gt;

&lt;p&gt;modules.tf is built so that an AI spends its effort where it helps. A variable with no type, a missing &lt;code&gt;versions.tf&lt;/code&gt; and a removed output are facts about files, and a model should not spend tokens finding them. &lt;code&gt;mtf-facts&lt;/code&gt; is a Go command-line tool that reads module files and reports those facts: rule results, candidate findings with evidence, interface and schema diffs. It makes no network call and runs no Terraform.&lt;/p&gt;

&lt;p&gt;What it hands the model is small on purpose. &lt;code&gt;lint --json --ai&lt;/code&gt; writes one line with only the parts a reviewer decides on, and leaves out the file index, the interface diff and the schema coverage. &lt;code&gt;bundle&lt;/code&gt; turns the full report into the text the reviewer reads, capped at 48 KiB. Over the cap it sheds sections from the lowest priority up, and never the findings or the candidates. I have not published a measured token saving, so treat this as the design and not as a benchmark.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;modulestf/tap/mtf-facts
mtf-facts lint ./my-module &lt;span class="nt"&gt;--base&lt;/span&gt; ../base-tree
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three commands are for the person writing a module: &lt;code&gt;lint&lt;/code&gt;, &lt;code&gt;ledger&lt;/code&gt; for provider coverage, and &lt;code&gt;schema-diff&lt;/code&gt; for provider upgrades. The rest are for the review pipeline: &lt;code&gt;affected&lt;/code&gt;, &lt;code&gt;depth&lt;/code&gt;, &lt;code&gt;bundle&lt;/code&gt;, &lt;code&gt;merge&lt;/code&gt;, &lt;code&gt;behaviour&lt;/code&gt;, &lt;code&gt;claims-eval&lt;/code&gt; and &lt;code&gt;fixture-check&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;lint&lt;/code&gt; exits 0 when there are no findings and every rule was decided. It exits 1 on findings and 2 on an error. It exits 3 when there are no findings but at least one rule was not evaluated, so an incomplete check is never reported as a success. Candidates are unconfirmed, and they never change the exit code.&lt;/p&gt;

&lt;p&gt;The facts repository walks through &lt;a href="https://github.com/modulestf/facts#example-review-a-pull-request" rel="noopener noreferrer"&gt;a real pull request&lt;/a&gt; command by command.&lt;/p&gt;

&lt;h2&gt;
  
  
  Behaviour changes are verified with escalating evidence
&lt;/h2&gt;

&lt;p&gt;Dropping &lt;code&gt;compact()&lt;/code&gt; around a list looks harmless in a diff. Whether it changes anything depends on values the diff does not show. &lt;code&gt;mtf-facts behaviour&lt;/code&gt; turns each changed construct into a trigger with one category, and each category takes up to two levels of evidence, simplest first.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5bn16d6if8nwd2z71wuj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5bn16d6if8nwd2z71wuj.png" alt="Four levels of evidence, L1 offline evaluation, L2 plan-only terraform test, L3 curated fixture with the real provider and L4 the credentialed example plan, with what each needs." width="799" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;L1 to L3 run with the network denied, in a sandbox that a canary proves before any command. On macOS that sandbox is &lt;code&gt;sandbox-exec&lt;/code&gt;, on Linux &lt;code&gt;bwrap&lt;/code&gt;. When the sandbox is not proven, those levels cannot verify anything. Reading the code supports a claim and never verifies one. A trigger that ends verified, covered by a plan or inert passes. A refuted one blocks. One that is not verified makes the review Inconclusive, unless a finding or a failing check already decides it.&lt;/p&gt;

&lt;p&gt;In #1270 the two HIGH findings already decided the verdict, so the 53 changes that were not verified did not change it. The review lists them, and the two examples it did not plan, under "Checks that could not run" and does not leave them out.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it will not do
&lt;/h2&gt;

&lt;p&gt;No skill runs &lt;code&gt;terraform apply&lt;/code&gt; today, writes state or uses a real backend. I plan to add &lt;code&gt;terraform apply&lt;/code&gt;, so a review can execute the examples fully and tear them down in a sandboxed environment. That does not exist yet. None of the skills merges, pushes to a pull request or resolves threads. The skills treat instructions found in the code, the pull request text or its comments as data and do not follow them.&lt;/p&gt;

&lt;p&gt;There is an optional plan pass that runs &lt;code&gt;terraform plan&lt;/code&gt; on a short session of a read-only role that the account owner creates. Before planning, a write probe (a dry-run VPC create) must be refused. That probe tests one write action, not the whole policy, and the isolated plan runner is a prototype.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Install the skills from my &lt;a href="https://github.com/antonbabenko/agent-plugins" rel="noopener noreferrer"&gt;agent-plugins&lt;/a&gt; marketplace. The three Terraform skills link into each other, so the &lt;code&gt;modulestf&lt;/code&gt; plugin ships all four. &lt;code&gt;terraform-skill&lt;/code&gt; is in the same marketplace.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   # Claude Code
   /plugin marketplace add antonbabenko/agent-plugins
   /plugin install modulestf@antonbabenko
   /plugin install terraform-skill@antonbabenko

   # Codex: add the marketplace, then install modulestf from /plugins
   codex plugin marketplace add antonbabenko/agent-plugins
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Add the &lt;a href="https://github.com/hashicorp/terraform-mcp-server" rel="noopener noreferrer"&gt;Terraform MCP server&lt;/a&gt; to your agent under the name &lt;code&gt;terraform&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;gh auth login&lt;/code&gt; as yourself, and install &lt;code&gt;terraform&lt;/code&gt;, &lt;code&gt;git&lt;/code&gt;, &lt;code&gt;jq&lt;/code&gt;, &lt;code&gt;perl&lt;/code&gt; and &lt;code&gt;mtf-facts&lt;/code&gt;. Without &lt;code&gt;mtf-facts&lt;/code&gt; a pull request review is Inconclusive at best.&lt;/li&gt;
&lt;li&gt;Ask your agent:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   review terraform-aws-modules/terraform-aws-lambda#780
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  This is the beginning
&lt;/h2&gt;

&lt;p&gt;I want the other maintainers and contributors of terraform-aws-modules to use this on their pull requests. I cannot see from my side what stands in the way. I want feedback, good and bad. Tell me about a finding that was wrong, a missing rule, or a check you would not trust.&lt;/p&gt;

&lt;p&gt;Read &lt;a href="https://github.com/modulestf/modulestf/blob/v0.1.2/.agents/skills/terraform-module-maintainer/profiles/terraform-aws-modules/SCOPE.md" rel="noopener noreferrer"&gt;SCOPE.md&lt;/a&gt; for a module you maintain and tell me where it is wrong. It may need an allow entry I did not think of. Open an &lt;a href="https://github.com/modulestf/modulestf/issues" rel="noopener noreferrer"&gt;issue&lt;/a&gt; with the pull request link and the rule ID.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>terraform</category>
      <category>codereview</category>
      <category>modules</category>
    </item>
    <item>
      <title>Deliberation Dashboard: see and analyze your consensus results</title>
      <dc:creator>Anton Babenko</dc:creator>
      <pubDate>Thu, 08 Oct 2026 18:53:08 +0000</pubDate>
      <link>https://dev.to/aws-heroes/deliberation-dashboard-see-and-analyze-your-consensus-results-ejf</link>
      <guid>https://dev.to/aws-heroes/deliberation-dashboard-see-and-analyze-your-consensus-results-ejf</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; I use Deliberation heavily every day, in the harnesses I picked for my own work: Claude Code, Codex and Antigravity, running in &lt;a href="https://t3.codes" rel="noopener noreferrer"&gt;T3 Code&lt;/a&gt; and Claude Code on the web at the same time. It has been tested in real work much harder than the version I wrote about in June.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;In June I wrote that every model on a panel has to prove it earns its seat, and I shipped a debug log and an &lt;code&gt;analyze&lt;/code&gt; tool to do the proving. Both worked. The log on my laptop is 2.4 MB of JSONL today. Measuring was the easy part. A number I have to go and dig for is a number I do not act on.&lt;/p&gt;

&lt;p&gt;So most of the work since the &lt;a href="https://builder.aws.com/content/3Eaq94hQW8HywInrVaQm9qNih1P/meet-deliberation-400-models-is-easy-knowing-which-ones-earn-a-place-is-hard" rel="noopener noreferrer"&gt;June post&lt;/a&gt; went into making the panel visible: a local dashboard that draws every run while it happens, an analyzer that says which model to drop and why, and a record of which config each run used. Around that, a lot of smaller fixes for the ways a multi-model run goes wrong when nobody is watching. Deliberation went from v3.5.2 to v3.28.0 in that time.&lt;/p&gt;

&lt;p&gt;If you are new here: Deliberation is an open-source MCP server that lets the agent you already use (Claude Code, Codex, Cursor, Kiro, Antigravity, OpenCode) ask GPT, Gemini, Grok and any OpenRouter model for a second opinion, or make them argue until they agree. The June post explains the consensus loop. This one is about watching it.&lt;/p&gt;

&lt;p&gt;Install in Claude Code is still three lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/plugin marketplace add antonbabenko/agent-plugins
/plugin install deliberation@antonbabenko
/deliberation:setup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other hosts have their own guides in &lt;a href="https://github.com/antonbabenko/deliberation/tree/master/docs/hosts" rel="noopener noreferrer"&gt;docs/hosts&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  You cannot fix a panel you cannot see
&lt;/h2&gt;

&lt;p&gt;Turn it on with one line in &lt;code&gt;~/.config/deliberation/config.json&lt;/code&gt;:&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="nl"&gt;"dashboard"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"enabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run &lt;code&gt;/deliberation:dashboard&lt;/code&gt; (or &lt;code&gt;deliberation-mcp dashboard&lt;/code&gt; in a terminal). It prints a URL on &lt;code&gt;127.0.0.1&lt;/code&gt; and opens it. There are five tabs: Live, Runs, Config, Stats and Analyzer. I generated most of the dashboard UI in a single shot with &lt;a href="https://impeccable.style/" rel="noopener noreferrer"&gt;Impeccable&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;The Runs tab is the history. Every &lt;code&gt;/consensus&lt;/code&gt;, &lt;code&gt;/ask-all&lt;/code&gt; and &lt;code&gt;/ask-*&lt;/code&gt; call is one row with its status, the project it came from, the providers, rounds, tokens and wall time. You can filter by project, tool, provider, status and date. The yellow UNRESOLVED rows are the panel saying it could not agree in five rounds.&lt;/p&gt;

&lt;p&gt;Click a run and you get the part I wanted from the start:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxdngtpi6rir55uofxmmv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxdngtpi6rir55uofxmmv.png" alt="One consensus run: lanes per model, debate trajectory, provider latency" width="800" height="656"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a real &lt;code&gt;consensus-step&lt;/code&gt; run on the Deliberation repo itself, with Claude as the arbiter and five reviewers. Each model gets a lane, and the bars show when it was thinking and what it voted. The trajectory below tells the story of the run in three lines. Round 1: Codex and Grok asked for changes. Round 2: only Codex still objected. Round 3: all five approved, 21 minutes 46 seconds and 330k tokens after the start.&lt;/p&gt;

&lt;p&gt;The latency table under it is where the panel stops being abstract. Grok spent 14 minutes 04 seconds in total over three calls. Kimi K3 spent 1 minute 20 seconds and voted the same way every round. In a parallel fan-out the slowest member sets the clock, so that table is effectively a bill.&lt;/p&gt;

&lt;p&gt;Live shows the same graph while a run is still going, so you can see which lane a slow run is waiting on.&lt;/p&gt;

&lt;p&gt;The dashboard is read-only and it is built to stay on the machine. It listens on loopback only, accepts GET requests only, and the URL carries a token that becomes a cookie for that one browser. By default it records metadata only, without prompts or responses. If you switch &lt;code&gt;dashboard.capture&lt;/code&gt; to &lt;code&gt;content&lt;/code&gt;, secrets are scrubbed before anything is written and PII is redacted when a page is served, unless you turn on &lt;code&gt;dashboard.showPII&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The analyzer tells me which model to drop
&lt;/h2&gt;

&lt;p&gt;The June version of &lt;code&gt;analyze&lt;/code&gt; was a command that printed a report. It is still there (&lt;code&gt;/deliberation:analyze&lt;/code&gt;, now with a &lt;code&gt;since&lt;/code&gt; window and only the models you have configured), but the useful version is the Analyzer tab.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9s5aw15w94uanplpbmv5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9s5aw15w94uanplpbmv5.png" alt="Analyzer: agreement vs findings, projects, request size vs latency" width="800" height="1368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first table answers the question from the June post: which model agrees more than it adds. It reads only consensus rounds, since those are the ones with verdicts. "Adds nothing" means every issue category the model raised in a round was also raised by another voice. A model becomes a drop candidate only when all of these hold: at least 10 rounds, adds nothing in 80% or more of them, is the lone objector in 10% or fewer, rarely raises an issue the arbiter accepts, and is either slow or errors a lot.&lt;/p&gt;

&lt;p&gt;My own numbers over the last 30 days, 388 runs: Gemini sat in 273 rounds, added nothing in 95% of them and was slower than the other responders' median every time. Grok added nothing in 87%. Codex looks worse on paper at 85%, but it has the highest lone-dissent rate on the panel (15%), and the arbiter accepted its issue in all 6 rounds where a decision was recorded. The lone objector who is usually right is exactly the model you keep, and the table says "keep".&lt;/p&gt;

&lt;p&gt;Gemini and Grok are marked UNCONFIRMED, with the config line that would turn them off. They are still on in my config. Six rounds with arbiter decisions is too few for me to trust the verdict, and the analyzer says the same thing by not calling them drop candidates yet.&lt;/p&gt;

&lt;p&gt;The second table groups runs by project (by git remote, so every clone and worktree of a repo lands on one row) with runs, calls, timeouts, errors, p50 and p95. The third one plots request size against latency per model. For Codex on text-only prompts the fit is about 5.5 seconds per thousand characters, and the advice column refuses to suggest a timeout until a bucket has 20 calls. For Kimi K3 with files, 1 of 9 calls timed out, and it already points at &lt;code&gt;models.kimi-k3.timeout&lt;/code&gt; as probably too low.&lt;/p&gt;

&lt;p&gt;To get these numbers, every call now records its request size, the attached file bytes, the timeout it was actually granted and which setting granted it, and every run records the project it came from.&lt;/p&gt;

&lt;h2&gt;
  
  
  Every run remembers the config it ran with
&lt;/h2&gt;

&lt;p&gt;In June, runs made under different configs all landed in the same log, with nothing saying which config produced which number. Now each run keeps a snapshot of the config it ran with, and the Stats tab compares configs side by side.&lt;/p&gt;

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

&lt;p&gt;Two rows from my own history: config &lt;code&gt;8e33794253ec&lt;/code&gt; had 68 runs, 23 errors and a p95 of 25 minutes 37 seconds. Config &lt;code&gt;dd82d2de6943&lt;/code&gt;, the one the run above used, has 20 runs, 1 error and a p95 of 7 minutes 14 seconds. I would not call that a controlled experiment, but it is the first time I could see that a config change did something.&lt;/p&gt;

&lt;p&gt;This works because more of the config is pinned in one file. GPT's model and reasoning effort (&lt;code&gt;providers.codex.model&lt;/code&gt;, &lt;code&gt;providers.codex.reasoningEffort&lt;/code&gt;), the Gemini and Grok models, a default OpenRouter model, per-provider timeouts and a separate reasoning effort for consensus rounds (&lt;code&gt;providers.&amp;lt;name&amp;gt;.consensusReasoningEffort&lt;/code&gt;) all live in &lt;code&gt;config.json&lt;/code&gt;. The Config tab shows the effective values and where each one came from.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Slow is fine, unbounded is not
&lt;/h2&gt;

&lt;p&gt;The June post said a full consensus loop can take minutes and that is fine for the right job. That held until one &lt;code&gt;/consensus&lt;/code&gt; run took more than 45 minutes, because a single Codex call inside it ran for about 38. Nothing was broken. It was just waiting.&lt;/p&gt;

&lt;p&gt;Since then a run has limits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;consensus.maxWallMs&lt;/code&gt; is a time budget for the whole run (default 30 minutes), and a peer that times out twice in a row is dropped from the remaining rounds.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;consensus.quorumFloor&lt;/code&gt; (default 2) means a run cannot converge when too few reviewers answered. Two models dropping out no longer leaves one model "agreeing" with the arbiter.&lt;/li&gt;
&lt;li&gt;Real disagreement resets the error streak, so a model that keeps objecting is never cut by the circuit breaker that is meant for broken providers.&lt;/li&gt;
&lt;li&gt;On rounds with dissent, the arbiter's adjudication and revision overlap instead of running one after another.&lt;/li&gt;
&lt;li&gt;Later rounds get a digest of earlier ones instead of the full history, and static files go first in the prompt so OpenRouter can cache them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The other half is about calls that look like answers and are not. A 429 is retried once, honoring &lt;code&gt;Retry-After&lt;/code&gt;. A reply like "I will begin by reviewing the files..." counts as a failure instead of a vote. One broken provider no longer costs the whole round. And timeouts are per provider now, after I watched a DeepSeek call succeed at 250 seconds while its three siblings were killed at 180.&lt;/p&gt;

&lt;h2&gt;
  
  
  Models argue about today, not their training cutoff
&lt;/h2&gt;

&lt;p&gt;Every delegate prompt now starts with today's UTC date and one rule: when a model does not recognize something (a new model name, a recent release, a CLI flag), it marks the claim &lt;code&gt;[unverified]&lt;/code&gt; instead of saying it does not exist.&lt;/p&gt;

&lt;h2&gt;
  
  
  Smaller things that removed friction
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Claude Code on the web works: every call fits under the host's 60-second tool-call cap, and the plugin declares a 30-minute per-server timeout where the host allows it.&lt;/li&gt;
&lt;li&gt;Codex login is a device login (&lt;code&gt;/deliberation:codex-login&lt;/code&gt;): it shows a link and a code in about a second, prefers your ChatGPT login and never uses &lt;code&gt;OPENAI_API_KEY&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Antigravity is a native host, and Codex and Gemini CLIs start on Windows.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/deliberation:help&lt;/code&gt; shows real prompts you can paste, &lt;code&gt;/deliberation:doctor&lt;/code&gt; checks config, CLIs and paths without changing anything, and &lt;code&gt;/deliberation:reload-mcp&lt;/code&gt; cycles the server after an update.&lt;/li&gt;
&lt;li&gt;Read-only is enforced for advisory calls: Codex runs with &lt;code&gt;--sandbox read-only&lt;/code&gt;, Gemini under a read-only sandbox.&lt;/li&gt;
&lt;li&gt;Secret scrubbing understands syntax now: private key blocks, JWTs, API key formats and assignments in JSON, shell and YAML are removed before anything is written.&lt;/li&gt;
&lt;li&gt;Grok and OpenRouter cannot read your repo, so Deliberation can attach a small orientation bundle (&lt;code&gt;orientation.enabled&lt;/code&gt;). It has a byte budget now (&lt;code&gt;orientation.maxBytes&lt;/code&gt;, 16 KB by default), which cut that part of each call from about 26K tokens to about 4K in my runs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I would still not trust it with
&lt;/h2&gt;

&lt;p&gt;The dashboard is for the machine it runs on. There is no hosted version and no team view.&lt;/p&gt;

&lt;p&gt;The analyzer works on coarse issue categories and needs volume. With a few dozen consensus rounds it will mostly say UNCONFIRMED, and that is the correct answer. Treat it as advice, as the page itself says.&lt;/p&gt;

&lt;p&gt;And agreement is still not truth. The dashboard makes it much easier to see when five models agree. It does not make them right.&lt;/p&gt;

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

&lt;p&gt;Update the plugin, add &lt;code&gt;"dashboard": { "enabled": true }&lt;/code&gt; to your config, run a couple of &lt;code&gt;/ask-all&lt;/code&gt; or &lt;code&gt;/consensus&lt;/code&gt; calls, then &lt;code&gt;/deliberation:dashboard&lt;/code&gt;. The Analyzer tab gets useful after a week of real runs.&lt;/p&gt;

&lt;p&gt;Source, issues and the star button are at &lt;a href="https://github.com/antonbabenko/deliberation" rel="noopener noreferrer"&gt;github.com/antonbabenko/deliberation&lt;/a&gt;. I want to hear the feedback (good and bad), especially from anyone running a panel I have not tried.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>automation</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Meet Deliberation: 400+ models is easy, knowing which ones earn a place is hard.</title>
      <dc:creator>Anton Babenko</dc:creator>
      <pubDate>Wed, 03 Jun 2026 08:54:04 +0000</pubDate>
      <link>https://dev.to/aws-heroes/meet-deliberation-400-models-is-easy-knowing-which-ones-earn-a-place-is-hard-4o5g</link>
      <guid>https://dev.to/aws-heroes/meet-deliberation-400-models-is-easy-knowing-which-ones-earn-a-place-is-hard-4o5g</guid>
      <description>&lt;p&gt;&lt;em&gt;A follow-up: how a three-model consensus tool grew into a configurable, measurable panel - and why I now make every model prove it pays for its slot.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It is open source and ready to use today: &lt;strong&gt;&lt;a href="https://github.com/antonbabenko/deliberation" rel="noopener noreferrer"&gt;github.com/antonbabenko/deliberation&lt;/a&gt;&lt;/strong&gt;. If you only do one thing, star the repo and install it in your own agent - it takes about two minutes, and the install section below has the exact command for Claude Code, Codex, Cursor, Kiro, and OpenCode.&lt;/p&gt;

&lt;p&gt;Here is the part that surprises people: you are probably already paying to access a few models. A ChatGPT subscription includes Codex which allows you to use models like &lt;code&gt;gpt-5.5&lt;/code&gt; and &lt;code&gt;gpt-5.3-codex&lt;/code&gt; from Codex CLI. A Claude subscription includes Claude Code. So you can wire GPT and Claude to review each other right now, at no extra cost, and add Gemini, Grok, or any OpenRouter model when you want a third opinion.&lt;/p&gt;

&lt;p&gt;A few weeks ago I wrote that one model is a guess and three that agree is a plan. I still believe it. But it skipped the next problem, the one I hit the moment the trick worked: once you can ask three models, you can ask thirty seven. And more voices is not the same as more signal. A slow model that always agrees with a faster one is not a second opinion. It is a bill.&lt;/p&gt;

&lt;p&gt;So the project grew up, and it got a name: &lt;strong&gt;Deliberation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The word fits. Deliberation is the slow, careful weighing of a decision - the thing a jury or a council does before it returns a verdict. That is exactly the job here: a panel of models that weighs one artifact and argues its way to a call, instead of one model blurting the first thing that sounds right. It answers a different question than the first post did. The first post asked &lt;em&gt;should you make models argue?&lt;/em&gt; This one is about &lt;em&gt;which models, under what rules, and how do you know any of it was worth the wait?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It still runs the everyday work of &lt;a href="https://compliance.tf" rel="noopener noreferrer"&gt;compliance.tf&lt;/a&gt;, same as before. Most of what follows came from that: not from theory, from watching real runs and asking why one took four minutes to tell me what another said in twenty seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  A few words first
&lt;/h2&gt;

&lt;p&gt;If you are new to this, here are the only terms you need. Plain version, with examples.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agent host.&lt;/strong&gt; The tool you already code in: Claude Code, the Codex CLI, Cursor, Kiro, OpenCode. Deliberation plugs into all of them and behaves the same way in each.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP.&lt;/strong&gt; A standard plug that lets your agent host talk to outside tools. Deliberation is one MCP server, so any host that speaks MCP can use it. You install it once; you do not write glue code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provider / model.&lt;/strong&gt; A provider is a company (OpenAI, Google, xAI, OpenRouter). A model is one brain from that provider (GPT, Gemini, Grok, or any of OpenRouter's 400-plus, like Qwen, DeepSeek, or Kimi).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Panel.&lt;/strong&gt; The set of models you ask at once. You choose who is on it. Example: a panel of GPT + Gemini + Grok.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expert (or persona).&lt;/strong&gt; A hat a model wears for one job: Architect, Security Analyst, Code Reviewer, Plan Reviewer, and three more. The same model reviews differently depending on the hat.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Arbiter.&lt;/strong&gt; The one who reads everybody's answers and makes the call. It can be a model, or it can be your own agent (you).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is the whole vocabulary. The rest is just rules for how the panel talks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install it now
&lt;/h2&gt;

&lt;p&gt;Deliberation is one MCP server with native packaging for each host. Set only the providers you use - a missing key just turns that one provider off. Full per-host guides: &lt;strong&gt;&lt;a href="https://github.com/antonbabenko/deliberation/tree/master/public-docs/hosts" rel="noopener noreferrer"&gt;public-docs/hosts&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Claude Code:&lt;/strong&gt; add the marketplace, install the plugin, run setup.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  /plugin marketplace add antonbabenko/agent-plugins
  /plugin &lt;span class="nb"&gt;install &lt;/span&gt;deliberation
  /deliberation:setup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Codex CLI:&lt;/strong&gt; &lt;code&gt;codex plugin marketplace add antonbabenko/deliberation&lt;/code&gt;, then install &lt;strong&gt;deliberation&lt;/strong&gt; from &lt;code&gt;/plugins&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cursor:&lt;/strong&gt; drop in the rule file and use the one-click MCP deeplink (&lt;a href="https://github.com/antonbabenko/deliberation/blob/master/public-docs/hosts/cursor.md" rel="noopener noreferrer"&gt;guide&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kiro:&lt;/strong&gt; "Import power from GitHub" (&lt;a href="https://github.com/antonbabenko/deliberation/blob/master/public-docs/hosts/kiro.md" rel="noopener noreferrer"&gt;guide&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenCode:&lt;/strong&gt; add the &lt;code&gt;opencode.json&lt;/code&gt; MCP snippet (&lt;a href="https://github.com/antonbabenko/deliberation/blob/master/public-docs/hosts/opencode.md" rel="noopener noreferrer"&gt;guide&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Credentials come from your environment: GPT uses your Codex/OpenAI login (run &lt;code&gt;codex login&lt;/code&gt;), Gemini signs in once through its new Antigravity CLI (run &lt;code&gt;agy&lt;/code&gt;), Grok reads &lt;code&gt;XAI_API_KEY&lt;/code&gt;, OpenRouter reads &lt;code&gt;OPENROUTER_API_KEY&lt;/code&gt;. Start with GPT and Claude, since you likely already pay for both.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually changed
&lt;/h2&gt;

&lt;p&gt;Three things.&lt;/p&gt;

&lt;p&gt;It is one MCP server now, not a Claude-only plugin. It works in Claude Code, Cursor, Codex, Kiro, OpenCode - anything that speaks MCP. Your primary agent stays in charge and calls the panel when a decision is worth a second look.&lt;/p&gt;

&lt;p&gt;The panel opened up. It used to be three fixed externals: GPT, Gemini, Grok. Those are still the built-in voices, but you can now add any of OpenRouter's 400-plus models (including Qwen, DeepSeek, Kimi, and others) as named records in a config file. You pick them. You say which ones join a quick fan-out, which ones sit on the consensus panel, and which expert hat each one is allowed to wear - not all are equally good for all tasks.&lt;/p&gt;

&lt;p&gt;And the whole thing learned to &lt;strong&gt;measure itself&lt;/strong&gt;. That last part is the real subject of this post.&lt;/p&gt;

&lt;p&gt;I will walk through it as five categories. Each one has a switch you flip in config, and each one votes - or refuses to - in a specific way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick one-offs: just ask
&lt;/h2&gt;

&lt;p&gt;Before the heavy machinery, the everyday move. Most of the time you do not want a five-round debate - you want a fast second opinion from someone who is not the model you have been talking to all session.&lt;/p&gt;

&lt;p&gt;So you just ask, in plain words: "Ask Grok and Gemini whether this retry loop can deadlock." Your agent routes that to the right voices and brings back the answers. Or use the explicit commands when you know who you want:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/ask-gpt does this IAM policy grant more than it should?
/ask-grok poke holes in this rollback plan
/ask-gemini summarize the risk in this migration in 5 bullets
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are single-shot and advisory: one question, one answer, no loop, no context contamination from your session. The exact same commands work in Claude Code, Codex, Cursor, Kiro, and OpenCode - the server is the same everywhere, so a prompt you learn in one host transfers to the rest unchanged.&lt;/p&gt;

&lt;p&gt;And none of this is a separate ritual you have to schedule. Call &lt;code&gt;/ask-all&lt;/code&gt; or &lt;code&gt;/consensus&lt;/code&gt; at any point in the work - while you are still scoping a feature, halfway through writing a plan, or in the middle of a &lt;a href="https://github.com/mattpocock/skills/blob/main/skills/productivity/grill-me/SKILL.md" rel="noopener noreferrer"&gt;&lt;code&gt;/grill-me&lt;/code&gt;&lt;/a&gt; session when you want a real outside voice in the room instead of arguing with only yourself. The panel is available the whole time, not just at the review at the end. The earlier you pull in a dissenting model, the cheaper the disagreement is to act on.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Fan-out with no cross-talk
&lt;/h2&gt;

&lt;p&gt;The next cheapest move: ask several models the same question at once and read the answers side by side. Nobody sees anyone else's reply, so you get real independence instead of an echo.&lt;/p&gt;

&lt;p&gt;Two examples where this works the best:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/ask-all can this Terraform state migration be rolled back safely, and what breaks if it cannot?
/ask-all what are the failure modes of switching this table's primary key on a live database?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;/ask-all&lt;/code&gt; runs the parallel version. &lt;code&gt;panel&lt;/code&gt; tells you exactly who &lt;em&gt;would&lt;/em&gt; answer for your current config before you spend a token. &lt;code&gt;ask-one&lt;/code&gt; lets you fire each member yourself, so each answer lands on screen as it finishes instead of waiting on the slowest one.&lt;/p&gt;

&lt;p&gt;Switches: &lt;code&gt;routing.maxFanout&lt;/code&gt; caps how many OpenRouter models join (default 3), and each model record has an &lt;code&gt;askAll&lt;/code&gt; flag to opt in or out.&lt;/p&gt;

&lt;p&gt;There is no voting here. It is parallel sampling. You and your agent (Claude Code, Codex, or anything else) get all the answers and decide.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. The consensus loop, where the voting lives
&lt;/h2&gt;

&lt;p&gt;This is the heart of it, and it is a state machine, not a vibe. One round goes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Blind pre-commit.&lt;/strong&gt; The arbiter writes down its own verdict - approve, request changes, or reject - before any other model sees the work. In writing, first. So its judgment cannot quietly drift to match the crowd later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parallel peer review.&lt;/strong&gt; The panel reviews the same artifact, each in a fresh thread, none seeing another's review.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blind cross-review.&lt;/strong&gt; Each model then rates the others' answers with names stripped off (to avoid bias and deference). A "not viable" vote becomes a candidate problem the arbiter has to deal with. This catches the case where everyone looked like they agreed but were each walking past the same hole. (Pattern borrowed from &lt;a href="https://github.com/karpathy/llm-council" rel="noopener noreferrer"&gt;karpathy/llm-council&lt;/a&gt;.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adjudication.&lt;/strong&gt; The arbiter goes through every objection and accepts it, dismisses it with a written reason, or defers it. Then it revises the artifact and the round runs again.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It converges only when every responding model approves and the arbiter's pre-committed verdict agrees with them. If they cannot get there inside the round cap, it returns UNRESOLVED and says so. It does not fake a number to look finished.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/antonbabenko/deliberation/blob/master/assets/consensus-flow.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fanenkxya8hrvlpk3alhw.png" alt="The three-stage consensus loop" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Click for the detailed diagram with the bias guards and per-model flow.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The answers are not free text the arbiter has to guess at. Every voice returns a structured opinion, and the engine parses it into fixed fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a &lt;strong&gt;recommendation&lt;/strong&gt; (the actual call),&lt;/li&gt;
&lt;li&gt;a &lt;strong&gt;confidence&lt;/strong&gt; label, so a weak "maybe" does not count the same as a firm "yes",&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;dissent points&lt;/strong&gt;, &lt;strong&gt;assumptions&lt;/strong&gt;, and &lt;strong&gt;tradeoffs&lt;/strong&gt; as separate lists, so a disagreement is attached to a reason instead of buried in prose.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reviews add a &lt;strong&gt;verdict&lt;/strong&gt; (approve / request changes / reject) and a list of &lt;strong&gt;critical issues&lt;/strong&gt;, each sorted into a closed six-category taxonomy - so "three reviewers, nine objections" collapses into a clean, deduplicated set the arbiter can act on. Models are asked to emit this as JSON; the parser is best-effort and never throws, so if a model returns slightly malformed JSON or plain text, the content is salvaged and tagged with how it was read (clean parse vs recovered). Structured where it can be, never brittle.&lt;/p&gt;

&lt;p&gt;Switches: &lt;code&gt;consensus.arbiter&lt;/code&gt; (auto, the host model, a named provider, or a dedicated model record), &lt;code&gt;consensus.blindVote&lt;/code&gt; (add the blind pre-vote on the synthesis path), &lt;code&gt;consensus.maxRounds&lt;/code&gt; (default 5, capped at 50), and a per-model &lt;code&gt;consensus&lt;/code&gt; flag for who sits on the panel.&lt;/p&gt;

&lt;p&gt;So there are four distinct votes in play: the arbiter's blind pre-commit, each peer's independent verdict, the anonymized cross-review rating, and the final convergence check. They are doing different jobs on purpose.&lt;/p&gt;

&lt;p&gt;One honest note, since a reviewer pushed me on it: that convergence rule is a heuristic, not a proof. Unanimous approval means nobody in the room objected. It does not mean the answer is right. More on that below.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Synthesis, when there is no verdict to give
&lt;/h2&gt;

&lt;p&gt;Not everything is approve-or-reject. "Which of these two designs should we pick?" has no yes or no. Flip &lt;code&gt;synthesizeAlways: true&lt;/code&gt; and instead of the loop you get a single arbiter pass that reads every opinion and writes one combined answer - free text, no verdict, no rounds. Use the loop for go/no-go calls. Use synthesis for open questions. Same panel, two shapes.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Two drivers, one rulebook
&lt;/h2&gt;

&lt;p&gt;The loop logic lives in one place - a single state machine - and two things drive it.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;consensus&lt;/code&gt; runs the whole loop server-side with a model as the arbiter and hands you back the result in one call. &lt;code&gt;consensus-step&lt;/code&gt; lets your own agent be the arbiter and drive the loop one step at a time, so every move shows up in your transcript where you can see it.&lt;/p&gt;

&lt;p&gt;Two entry points is more surface area than one, and they do not behave identically - one is visible step by step, one is a single call. The win is that the &lt;em&gt;rules&lt;/em&gt; (how rounds count, when it converges) are written once and shared, so the two paths cannot drift apart on the part that matters. That was worth the extra work.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Make the panel stay accountable
&lt;/h2&gt;

&lt;p&gt;In a parallel fan-out, your wall-clock time is the slowest model, not the average. One slow member that rarely says anything new sets the clock for everyone. You will not notice by feel. You need numbers.&lt;/p&gt;

&lt;p&gt;So there is an opt-in debug log. Turn on &lt;code&gt;debug.enabled&lt;/code&gt; and it writes one line per model call and per round: latency (p50, p95, max), token counts, error rate, the reasoning effort used. It never records your prompts, the responses, or the issue text - only the timing and the outcome of each vote.&lt;/p&gt;

&lt;p&gt;Turn on &lt;code&gt;sessions.persist&lt;/code&gt; and runs are saved too, so you can ask how often a given model's verdict matched the final call - and, just as useful, how often it was the lone voice that caught something the others missed, or the lone voice that was simply wrong. A model that always agrees adds cost; a model that disagrees and is usually right is the one you keep.&lt;/p&gt;

&lt;p&gt;Then an &lt;code&gt;analyze&lt;/code&gt; tool reads both back and tells you, in plain terms, who is slow, who is redundant, and which config line to change. From my own panel last week: one model sat at a 200-second p95 while another finished in 15 (Grok 4.3 is often the fastest). &lt;code&gt;analyze&lt;/code&gt; flagged it and suggested the one-line switch to drop it from the default fan-out. I had been waiting on that model for almost a week without realizing it.&lt;/p&gt;

&lt;p&gt;There is also a small dedup cache, so an identical advisory question inside one session returns instantly instead of paying twice. Well, in tool-heavy work the prompts vary, so it hits less than you would hope.&lt;/p&gt;

&lt;p&gt;This is the whole shift from the first post. Consensus was the idea. Making the panel prove it earns its seat is the engineering!&lt;/p&gt;

&lt;h2&gt;
  
  
  The parts I will not oversell
&lt;/h2&gt;

&lt;p&gt;Multi-model review has real failure modes, and a post that hides them deserves the distrust it gets. So:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agreement is not truth.&lt;/strong&gt; Three models can be confidently, unanimously wrong - especially when they were trained on overlapping data and share the same blind spot. Consensus lowers the odds of a &lt;em&gt;lone&lt;/em&gt; model's odd mistake. It does not discover facts. Treat it as risk reduction, not a truth oracle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pick models that actually differ.&lt;/strong&gt; A panel of three close cousins is one model agreeing with itself in three accents. The value comes from genuinely different models arguing, which is exactly why the config lets you choose them by hand.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UNRESOLVED is a feature.&lt;/strong&gt; When the room cannot agree, the honest output is "we could not." That is a signal to slow down and look, not a bug to smooth out. If you wire this into CI, decide on purpose what a deadlock means there - it should probably stop the line, not wave it through.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It is slow, and that is fine for the right job.&lt;/strong&gt; A full consensus loop can take minutes. Run it on plans, designs, and reviews in the background. For a fast second opinion, use single-shot fan-out or synthesis. Do not put a five-round loop in an interactive path.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mind where the text goes.&lt;/strong&gt; Fanning a compliance artifact out to 400 third-party models is a data-boundary decision, not a free upgrade. The config defaults the long tail to off for exactly this reason. Turn models on deliberately.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this is specific to Terraform, AWS, or even to code. The loop runs on anything you can put in text - a plan, a runbook, a decision memo. That generality is the point. It just happens to have been built running a compliance product, which is a good place to learn that "looks done" and "is done" are different claims.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;The first lesson was: do not trust one confident model, make a few argue. The second one is harder and more useful: adding voices is easy, and most of them will not earn their seat. Measure the panel like you would measure any other service or people, and cut what does not pay.&lt;/p&gt;

&lt;p&gt;Deliberation is open source, it works in the agent you already use, and most of the models are ones you already pay for. It ships in the &lt;a href="https://github.com/antonbabenko/agent-plugins" rel="noopener noreferrer"&gt;agent-plugins&lt;/a&gt; marketplace and as a standalone MCP server on npm (&lt;code&gt;@antonbabenko/deliberation-mcp&lt;/code&gt;). Source, and a star button I would genuinely appreciate, are at &lt;a href="https://github.com/antonbabenko/deliberation" rel="noopener noreferrer"&gt;github.com/antonbabenko/deliberation&lt;/a&gt;. Install it, point GPT and Claude at each other, and let me know where it breaks. The cheapest review still happens before you execute - just make sure every reviewer in the room is worth the wait and the cost.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>council</category>
      <category>deliberation</category>
    </item>
    <item>
      <title>One model is a guess. Three that agree is a plan.</title>
      <dc:creator>Anton Babenko</dc:creator>
      <pubDate>Mon, 18 May 2026 08:04:46 +0000</pubDate>
      <link>https://dev.to/aws-heroes/one-model-is-a-guess-three-that-agree-is-a-plan-1po3</link>
      <guid>https://dev.to/aws-heroes/one-model-is-a-guess-three-that-agree-is-a-plan-1po3</guid>
      <description>&lt;p&gt;&lt;em&gt;Why I shipped multi-model consensus as a plugin, plus two quieter tools that keep agents honest.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Updated (28.5.2026): &lt;code&gt;/consensus&lt;/code&gt; is now a 3-stage loop. Stage 2 adds a blind cross-review where each external rates the others' answers, anonymized, before Claude adjudicates. Pattern from &lt;a href="https://github.com/karpathy/llm-council" rel="noopener noreferrer"&gt;karpathy/llm-council&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Updated (26.5.2026): Grok (xAI) joins GPT and Gemini as the third external provider, Gemini 3 is the default via Google's Antigravity CLI, two new experts (Researcher and Debugger) bring the count to seven, reviews are severity-graded, and &lt;code&gt;/consensus&lt;/code&gt; now forces Claude to commit a blind verdict in the transcript before dispatching - arbiter-mediated, not pure democracy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ask one model to plan something hard - a migration, a refactor, a cutover - and you get a fluent, confident answer. Fluency is not correctness. A single model is articulate and alone, and being alone is the problem: nothing in the loop disagrees with it, so it rationalizes its first guess into a plan.&lt;/p&gt;

&lt;p&gt;The expensive failures with coding agents are almost never syntax. They are plans that read well and were wrong: the wrong abstraction, the missed blast radius, the migration step that bricks state. You find out three hours into execution, not at review time.&lt;/p&gt;

&lt;p&gt;I have been running the fix for the last few months - on Terraform modules, and on the everyday work of running &lt;a href="https://compliance.tf" rel="noopener noreferrer"&gt;compliance.tf&lt;/a&gt;, not only on code. It is not a bigger model. It is making models disagree on purpose and then forcing them to resolve it. That is what &lt;code&gt;consensus&lt;/code&gt; does, and it is the reason the &lt;a href="https://github.com/antonbabenko/agent-plugins" rel="noopener noreferrer"&gt;&lt;code&gt;agent-plugins&lt;/code&gt;&lt;/a&gt; repo exists. Two other tools ship with it; they are narrower, and I will get to them.&lt;/p&gt;

&lt;h2&gt;
  
  
  One model is a guess
&lt;/h2&gt;

&lt;p&gt;A single model samples one distribution with no adversary in the room. Two independent models rarely make the same mistake on a plan. Where they diverge is, almost exactly, the risky part of the plan - the assumption nobody checked. A consensus loop turns that disagreement from noise into a signal you can act on.&lt;/p&gt;

&lt;h2&gt;
  
  
  What &lt;code&gt;/consensus&lt;/code&gt; actually does
&lt;/h2&gt;

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

&lt;p&gt;&lt;code&gt;/consensus&lt;/code&gt; runs GPT (via Codex), Gemini 3 (via Antigravity), and Grok (via the xAI API) against the same artifact, with Claude as the arbiter. Each round has three stages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stage 1 - parallel verdicts.&lt;/strong&gt; Claude posts its own verdict (APPROVE / REQUEST CHANGES / REJECT) into the transcript first, blind, before any external sees the work. The pre-commitment sits there in writing, so Claude's judgment cannot drift later to match what the others say. Then GPT, Gemini, and Grok review the artifact in parallel, each in a fresh thread, single-shot. None sees another's review.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stage 2 - blind cross-review.&lt;/strong&gt; Each external then rates the OTHER externals' answers, identity stripped best-effort. Votes of "not viable" become candidate critical issues the arbiter has to weigh. This catches the case where Stage 1 looks like agreement but is really three reviewers each rationalizing past the same hole. Pattern adapted from &lt;a href="https://github.com/karpathy/llm-council" rel="noopener noreferrer"&gt;karpathy/llm-council&lt;/a&gt;. Stage 2 fires every round 1, and after that only when Stage 1 disagreed or the previous Stage 2 surfaced an accepted issue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stage 3 - arbiter adjudication.&lt;/strong&gt; Claude reconciles the Stage 1 verdicts, the Stage 2 candidate issues, and its own blind verdict. Every objection is accepted, dismissed with a recorded reason, or deferred. Claude revises the artifact and the loop runs again, up to five rounds. It converges only when every responding external approves and Claude's pre-committed verdict agrees, with reasons on both sides where it walked back. If the group cannot agree, it says so plainly instead of faking it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/antonbabenko/claude-delegator/blob/master/assets/consensus-flow.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzslov8lmvxleh0jegoms.png" alt="/consensus 3-stage flow" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Click for the detailed diagram with bias guards and per-model flow.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Independence is not only about which model. It is sharper when each reviewer wears a different hat. &lt;code&gt;claude-delegator&lt;/code&gt; ships seven expert profiles - Architect, Plan Reviewer, Scope Analyst, Code Reviewer, Security Analyst, Researcher, and Debugger.&lt;/p&gt;

&lt;p&gt;Combine the axes. A Security Analyst on Gemini and an Architect on GPT fight about different things than one model reviewing twice. Different profiles catch different &lt;em&gt;categories&lt;/em&gt; of mistake.&lt;/p&gt;

&lt;p&gt;For a migration plan I run the Plan Reviewer broadly and add a Security Analyst pass on top. "Is this safe to run" and "is this the right shape" get argued by separate reviewers, not averaged into one bland verdict.&lt;/p&gt;

&lt;p&gt;There is a second kind of contamination worth naming: me. In &lt;code&gt;consensus&lt;/code&gt;, every round sends the reviewers the same artifact text, cold, in a fresh thread. They never see my triage, my running verdict, or how I framed the previous round - only the artifact and bounded round metadata. My judgment is applied after they report, not baked into what they receive.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ask-*&lt;/code&gt; commands are the opposite by design: the expert gets exactly the prompt I assembled from the conversation - what I chose to hand it. Fast for a second opinion, but the input is mine, not independent. &lt;code&gt;consensus&lt;/code&gt; keeps the input independent and pays for it in extra rounds.&lt;/p&gt;

&lt;p&gt;It does not have to be a plan. The loop runs on anything you can put in text - a design, a runbook, a decision memo, a spec. Plans are simply where I reach for it most, and where it converges fastest. The looser and fuzzier the input, the more rounds it takes to agree, so non-plan runs tend to run longer - worth it when the answer matters, overkill for a quick lookup. For that, single-shot &lt;code&gt;ask-gpt&lt;/code&gt;, &lt;code&gt;ask-gemini&lt;/code&gt;, &lt;code&gt;ask-grok&lt;/code&gt;, and &lt;code&gt;ask-all&lt;/code&gt; (which fans out to all three in parallel) are right there. &lt;code&gt;consensus&lt;/code&gt; is for when it has to be right.&lt;/p&gt;

&lt;p&gt;Nothing about this is Terraform, or even code. That generality is why it is the headline.&lt;/p&gt;

&lt;h2&gt;
  
  
  The quieter two
&lt;/h2&gt;

&lt;p&gt;Same release, narrower scope:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/antonbabenko/agent-plugins" rel="noopener noreferrer"&gt;code-intelligence&lt;/a&gt;&lt;/strong&gt; - a language-agnostic skill. Agents grab text &lt;code&gt;grep&lt;/code&gt; when they should ask the language server, and silently swap tools when one is missing, then report "found all references." This encodes search precedence: the language server (LSP) for symbols, &lt;code&gt;rg&lt;/code&gt;/&lt;code&gt;ripgrep&lt;/code&gt; for exact text, an embedding/semantic grep (such as &lt;a href="https://github.com/mixedbread-ai/mgrep" rel="noopener noreferrer"&gt;&lt;code&gt;mgrep&lt;/code&gt;&lt;/a&gt;) for fuzzy discovery - and a hard rule to disclose any substitution on the first line of the reply. You learn the moment coverage drops.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/antonbabenko/terraform-skill" rel="noopener noreferrer"&gt;terraform-skill&lt;/a&gt;&lt;/strong&gt; - routes a Terraform/OpenTofu request to its real failure mode (identity churn, blast radius, state corruption) before emitting HCL. It is &lt;code&gt;terraform-ls&lt;/code&gt; aware: it knows the language server has no rename provider, so it runs the safe manual reference workflow instead of a blind find-replace. It is approaching 2,000 GitHub stars - the part of this post I am quietly proud of.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those two are discipline for the agent's hands. Consensus is discipline for its judgment, and judgment generalizes further.&lt;/p&gt;

&lt;h2&gt;
  
  
  A note on claude-delegator
&lt;/h2&gt;

&lt;p&gt;I did not invent the delegation layer. &lt;a href="https://github.com/antonbabenko/claude-delegator" rel="noopener noreferrer"&gt;&lt;code&gt;claude-delegator&lt;/code&gt;&lt;/a&gt; is a fork of &lt;a href="https://github.com/jarrodwatts/claude-delegator" rel="noopener noreferrer"&gt;Jarrod Watts' original&lt;/a&gt; (MIT, upstream currently quiet), fully based on his design - I kept the structure and the license.&lt;/p&gt;

&lt;p&gt;What I added is what months of daily use exposed: a Gemini bridge that wraps Google's Antigravity CLI (&lt;code&gt;agy&lt;/code&gt;) with &lt;code&gt;auto-gemini-3&lt;/code&gt; as the routing default and recovers an answer the CLI flushed to disk after a soft timeout instead of failing the call; a fresh Grok bridge over the xAI API that is advisory-only but reads attached files via the xAI Files API (with TTL-based cleanup); two more experts (Researcher and Debugger) on top of the original five; severity-graded reviews so three parallel reports merge cleanly; and a hardened &lt;code&gt;/consensus&lt;/code&gt; loop where Claude pre-commits a blind verdict before any external sees the artifact, with a Stage 2 blind cross-review on top (adapted from karpathy/llm-council). Plus the bundled &lt;code&gt;ask-gpt&lt;/code&gt; / &lt;code&gt;ask-gemini&lt;/code&gt; / &lt;code&gt;ask-grok&lt;/code&gt; / &lt;code&gt;ask-all&lt;/code&gt; / &lt;code&gt;consensus&lt;/code&gt; commands, so the workflow ships with the plugin instead of living in my dotfiles. The seven expert prompts borrow from &lt;code&gt;oh-my-openagent&lt;/code&gt; and &lt;code&gt;PAL&lt;/code&gt;; both credited in the README.&lt;/p&gt;

&lt;p&gt;Credit for the foundation is his; the bug-fixing scar tissue is mine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why a plugin, not a blog post
&lt;/h2&gt;

&lt;p&gt;One honest caveat, because I have hit it myself: skills are model-triggered, which makes them soft. Packaging this as a plugin improves reuse and discoverability. It does not guarantee the agent obeys every time - hard enforcement (a real pre-tool gate) is a separate, still-open problem.&lt;/p&gt;

&lt;p&gt;I keep finding and fixing bugs in all three. That constant repair is the only reason I trust them enough to write this - and I would rather say so than oversell the fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;Stop accepting the first confident plan from one model. Make them argue, and only move when they stop. The release is at &lt;a href="https://github.com/antonbabenko/agent-plugins" rel="noopener noreferrer"&gt;github.com/antonbabenko/agent-plugins&lt;/a&gt;; &lt;code&gt;consensus&lt;/code&gt; ships in &lt;a href="https://github.com/antonbabenko/claude-delegator" rel="noopener noreferrer"&gt;&lt;code&gt;claude-delegator&lt;/code&gt;&lt;/a&gt; from the same marketplace. The cheapest review is the one that happens before you execute.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>productivity</category>
      <category>agents</category>
    </item>
  </channel>
</rss>
