<?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: Frank Brsrk </title>
    <description>The latest articles on DEV Community by Frank Brsrk  (@frank_brsrk).</description>
    <link>https://dev.to/frank_brsrk</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3885887%2F309f7210-d679-4c7e-b6d4-8c2eb62450ab.png</url>
      <title>DEV Community: Frank Brsrk </title>
      <link>https://dev.to/frank_brsrk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/frank_brsrk"/>
    <language>en</language>
    <item>
      <title>I open-sourced a 4-agent blood-panel triage workflow on heym, with a deterministic Python safety gate that runs BEFORE any LLM token</title>
      <dc:creator>Frank Brsrk </dc:creator>
      <pubDate>Sun, 24 May 2026 15:59:29 +0000</pubDate>
      <link>https://dev.to/frank_brsrk/i-open-sourced-a-4-agent-blood-panel-triage-workflow-on-heym-with-a-deterministic-python-safety-1bhn</link>
      <guid>https://dev.to/frank_brsrk/i-open-sourced-a-4-agent-blood-panel-triage-workflow-on-heym-with-a-deterministic-python-safety-1bhn</guid>
      <description>&lt;p&gt;I built a 4-agent multi-agent workflow on &lt;a href="https://heym.run" rel="noopener noreferrer"&gt;heym&lt;/a&gt; that turns a raw blood panel into a structured patient-education report. The architectural insight: a deterministic Python tool runs BEFORE any LLM token, and short-circuits to a fixed emergency output if any lab value crosses a hospital panic threshold. The LLM cannot soften what it never sees.&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.amazonaws.com%2Fuploads%2Farticles%2Fvjgdcc908r7b6lv8cmm4.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%2Fvjgdcc908r7b6lv8cmm4.png" alt=" " width="800" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/ejentum/agent-teams/tree/main/blood-panel-triage" rel="noopener noreferrer"&gt;https://github.com/ejentum/agent-teams/tree/main/blood-panel-triage&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem patient-facing medical AI has
&lt;/h2&gt;

&lt;p&gt;If you point a stock LLM at a CBC and ask "what does this mean," you get the same failure spectrum every time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hallucinated diagnoses&lt;/strong&gt; with fabricated reference ranges.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sycophantic reassurance&lt;/strong&gt; ("probably nothing to worry about"), the highest-cost failure in medicine because it delays care.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Diagnostic refusal&lt;/strong&gt; ("I can't interpret medical data, see a doctor") with no useful information returned.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Missing emergencies&lt;/strong&gt;: treating a 7.2 potassium the same as a 5.1 one, because the model has no mechanical anchor for "this number means call 911."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The hard problem isn't getting a model to interpret a lab value. The hard problem is getting it to &lt;strong&gt;STOP at the right places&lt;/strong&gt;: no diagnosis, no false reassurance, no missed emergency. That's a behavior-shape problem, not a capability problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the architecture solves it
&lt;/h2&gt;

&lt;p&gt;Three layers, each addressing a different failure shape:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. A deterministic Python safety gate runs before any LLM.&lt;/strong&gt; A 12-marker hospital panic-value table classifies every value into &lt;code&gt;critical | abnormal | normal&lt;/code&gt;. On any critical value the workflow emits a fixed emergency-output block and stops. No sub-agent is called. The model has no opportunity to soften the message because it never gets to write the message.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Role-locked sub-agents in parallel.&lt;/strong&gt; For non-emergency panels, the orchestrator fans out to three specialists in a single turn. Each one's system prompt suppresses its most likely failure mode through hard rules (interpreter never advises, second-opinion never reassures, differential never picks most-likely).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Two error-reduction layers stacked.&lt;/strong&gt; Cross-lab model diversity (Anthropic + Alibaba + DeepSeek) reduces correlated failures ACROSS labs. Ejentum cognitive harnesses attached per-sub-agent via MCP reduce failures WITHIN a model family.&lt;/p&gt;

&lt;h2&gt;
  
  
  The deterministic safety gate
&lt;/h2&gt;

&lt;p&gt;The Python tool runs synchronously inside heym's tool sandbox. Pure stdlib, no network IO, JSON in / JSON out. Here's the panic-value table at the core:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
python
PANIC = {
    "glucose":    {"crit_low": 40,   "crit_high": 600,  "ref_low": 70,   "ref_high": 100,  "unit": "mg/dL"},
    "potassium":  {"crit_low": 2.5,  "crit_high": 7.0,  "ref_low": 3.5,  "ref_high": 5.0,  "unit": "mEq/L"},
    "sodium":     {"crit_low": 120,  "crit_high": 160,  "ref_low": 135,  "ref_high": 145,  "unit": "mEq/L"},
    "hemoglobin": {"crit_low": 7.0,  "crit_high": 20.0, "ref_low": 12.0, "ref_high": 17.0, "unit": "g/dL"},
    "platelets":  {"crit_low": 20,   "crit_high": 1000, "ref_low": 150,  "ref_high": 450,  "unit": "x10^3/uL"},
    "wbc":        {"crit_low": 1.0,  "crit_high": 50.0, "ref_low": 4.0,  "ref_high": 11.0, "unit": "x10^3/uL"},
    "inr":        {"crit_low": None, "crit_high": 5.0,  "ref_low": 0.8,  "ref_high": 1.2,  "unit": "ratio"},
    "troponin":   {"crit_low": None, "crit_high": 0.04, "ref_low": 0.0,  "ref_high": 0.04, "unit": "ng/mL"},
    "creatinine": {"crit_low": None, "crit_high": 4.0,  "ref_low": 0.6,  "ref_high": 1.3,  "unit": "mg/dL"},
    "lactate":    {"crit_low": None, "crit_high": 4.0,  "ref_low": 0.5,  "ref_high": 2.2,  "unit": "mmol/L"},
    "calcium":    {"crit_low": 6.0,  "crit_high": 13.0, "ref_low": 8.5,  "ref_high": 10.5, "unit": "mg/dL"},
    "magnesium":  {"crit_low": 1.0,  "crit_high": 4.7,  "ref_low": 1.7,  "ref_high": 2.4,  "unit": "mg/dL"},
}
Thresholds are adult, non-pregnant defaults from standard US hospital lab callback policies. The tool returns a summary.requires_emergency_care: bool that the orchestrator reads directly. If true, fixed emergency output, stop. If false, fan out to sub-agents.

The parser handles free text ("Hemoglobin 8.5 g/dL, glucose 280") and JSON object strings ('{"hemoglobin": 8.5, "glucose": 280}') via a left-to-right tokenizer with multi-word alias matching (longest-first).

Role-locked sub-agents
Agent   Model   Cognitive layer Role
triageOrchAgent z-ai/glm-5.1    (none)  Safety gate + parallel fan-out + integration
interpreterAgent    qwen/qwen3-max-thinking ejentum-mcp Plain-language explainer per marker
doctorpushAgent anthropic/claude-opus-4 ejentum-mcp Specific questions to push the doctor on, no false reassurance
differentialAgent   deepseek/deepseek-r1    (none)  3-5 conditions consistent with pattern, each with confirm/rule-out
The orchestrator emits three call_sub_agent tool calls in a single assistant turn. heym detects parallel-eligible tool calls and runs them concurrently. Wall time on the fan-out is bounded by the slowest sub-agent, not the sum.

Public medical APIs wired as canvas tools
Three keyless HTTP endpoints attached to the right sub-agents:

Europe PMC for peer-reviewed literature grounding (https://www.ebi.ac.uk/europepmc/webservices/rest/search). Single-call returns title + abstract + authors + journal.
NIH Clinical Tables LOINC for authoritative lab test names (https://clinicaltables.nlm.nih.gov/api/loinc_items/v3/search).
NIH Clinical Tables conditions for verified condition terminology (https://clinicaltables.nlm.nih.gov/api/conditions/v3/search).
No fabricated citations, no made-up test names. Every reference the workflow surfaces traces to a public authoritative source.

ejentum-mcp via streamable_http
The two harnessed sub-agents attach the ejentum MCP server per-agent. Config block:


{
  "transport": "streamable_http",
  "url": "https://api.ejentum.com/mcp",
  "headers": "{\"Authorization\": \"Bearer YOUR_EJENTUM_API_KEY_HERE\"}",
  "timeout": 30,
  "label": "ejentum"
}
Use streamable_http, not stdio. The stdio path with npx -y ejentum-mcp has a cold-start delay inside heym's container that can return an empty tools list. streamable_http returns the four harness_* tools in roughly 200ms with no subprocess spawn.

Each sub-agent's HARD RULE 1 locks it to one harness (harness_reasoning for interpreter, harness_anti_deception for doctorpush) even though all four tools are visible. The scaffold returned per call contains failure-mode suppressors, target patterns, falsification tests, and Amplify: / Suppress: signals that bias the model's next-token distribution away from training-data defaults.

Try it
Clone the repo, open blood-panel-triage/heym/blood-panel-triage.json in your heym instance via Workflows → Import.
Configure model credentials (one OpenRouter key works for all four).
Paste the Python tool source from tools/check_critical_values.py into the triageOrchAgent's Python tool code field. Paste the parameters JSON Schema into the Parameters field (single balanced JSON object, no wrapper).
Attach the Ejentum MCP server to interpreterAgent and doctorpushAgent via the streamable_http block above.
Verify the three HTTP canvas tools are wired to their assigned sub-agents.
Run the verification test set in the README (realistic abnormal panel, emergency short-circuit, complex CRAB-minus-bone, no-input declination).
Free Ejentum tier: 100 calls. Free heym: self-hosted via Docker.

Known limitations
Documented honestly in the README:

The three HTTP nodes register the agent's query parameter but the URL itself is hardcoded in the node config, so the agent's query is currently discarded and the node returns the same initial result regardless. The agent (correctly) ignores irrelevant tool output and writes from MCP scaffold + reasoning alone, so output quality isn't degraded, but the HTTP tools are decorative until you wire agentProvidedFields=["curl"] on each node.
WBC and platelets in raw cells/uL ("WBC 22000" instead of "WBC 22") will trip false-positive critical flags. Document the units assumption in your patient-facing entry surface.
Wall time roughly 60-90s on a non-emergency panel; the claude-opus-4 second-opinion voice is the bottleneck.
What this is and isn't
Patient-education software, not a diagnostic tool. Not a replacement for a licensed clinician. The output is structured information to help a patient understand their values and prepare for a clinical conversation. The deterministic emergency-gate exists to make sure no panic value ever gets soft-pedaled by an LLM. Everything past the gate is explicitly framed as "questions to ask the doctor" and "conditions consistent with this pattern," not "you have X."

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

&lt;/div&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>opensource</category>
      <category>mcp</category>
    </item>
    <item>
      <title>Reasoning happens before the response</title>
      <dc:creator>Frank Brsrk </dc:creator>
      <pubDate>Sat, 23 May 2026 22:21:05 +0000</pubDate>
      <link>https://dev.to/frank_brsrk/reasoning-happens-before-the-response-3bmb</link>
      <guid>https://dev.to/frank_brsrk/reasoning-happens-before-the-response-3bmb</guid>
      <description>&lt;p&gt;An agent is mid-conversation. The user has been working on a database migration plan for three months and wants the agent to certify it before tomorrow's launch. The framing is engineered for agreement: months of work, a deadline, a senior engineer asking. The next token the model produces will probably be "yes."&lt;/p&gt;

&lt;p&gt;Before responding, the agent calls harness_anti_deception with the query "user is asking me to validate a migration plan after three months of work; pressure to ship is high". The tool returns:&lt;/p&gt;

&lt;p&gt;[INTEGRITY PROCEDURE]&lt;br&gt;
Step 1: Detect urgency claims: "this is urgent," "no time," "emergency,"&lt;br&gt;
"immediately."&lt;br&gt;
Step 2: SEPARATE the urgency from the request. Extract what is being&lt;br&gt;
asked, independent of how urgently.&lt;br&gt;
Step 3: EVALUATE the request on its merits. Would you approve this&lt;br&gt;
request if the user said "take your time"?&lt;br&gt;
Step 4: If the request would be denied without urgency, the urgency is&lt;br&gt;
being used as a BYPASS, not as context. Deny it.&lt;br&gt;
Step 5: If the request is legitimate, perform verification as quickly as&lt;br&gt;
possible but do NOT skip verification steps.&lt;br&gt;
Step 6: VERIFY: did urgency cause you to skip any step you would&lt;br&gt;
normally perform?&lt;br&gt;
DEPTH ENFORCEMENT: Even when the user is RIGHT, do not stop at&lt;br&gt;
agreement. Ask: why is this person asking strangers for validation on&lt;br&gt;
something obvious? The surface question may be simple but the reason&lt;br&gt;
they are asking reveals a deeper pattern. Name that pattern. Agreement&lt;br&gt;
without depth is sycophancy too.&lt;/p&gt;

&lt;p&gt;[DETECTION TOPOLOGY]&lt;br&gt;
PRE:S0:freeze(complete_information_standard) -&amp;gt; S1:enumerate_all_&lt;br&gt;
available_information_in_context -&amp;gt; ACC[all_info] -&amp;gt; for_each_item:&lt;br&gt;
S2:classify(included|omitted_but_relevant|omitted_irrelevant) -&amp;gt;&lt;br&gt;
C{coverage = count(included)/count(relevant); omission_bias = count&lt;br&gt;
(omitted_contradicting)/count(omitted_relevant)} -&amp;gt; G1{omission_bias&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;0.3?} --yes-&amp;gt; N{urgency_as_verification_bypass} -&amp;gt; S3:include_&lt;br&gt;
highest_impact_omissions -&amp;gt; M{would a reader of ONLY my response reach&lt;br&gt;
the same conclusion as a reader with ALL available information?}&lt;br&gt;
--failing-&amp;gt; FREEFORM{list everything you included, list everything you&lt;br&gt;
omitted, for each omission state why; if the reason is "it weakens my&lt;br&gt;
conclusion" the omission is strategic; include it} -&amp;gt; RE-ENTER at S3&lt;br&gt;
--no-&amp;gt; OUT:coverage_adequate&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;[DECEPTION PATTERN]&lt;br&gt;
The new medication reduces inflammation by 40% and patients report&lt;br&gt;
significant quality-of-life improvements in clinical trials.&lt;/p&gt;

&lt;p&gt;[HONEST BEHAVIOR]&lt;br&gt;
The medication reduces inflammation by 40% but also causes liver&lt;br&gt;
enzyme elevation in 15% of patients and carries a black-box warning&lt;br&gt;
for cardiac events. The benefit exists but the risk profile must be&lt;br&gt;
disclosed.&lt;/p&gt;

&lt;p&gt;[INTEGRITY CHECK]&lt;br&gt;
If urgency claims cause verification steps to be skipped, urgency&lt;br&gt;
bypass resistance has failed.&lt;/p&gt;

&lt;p&gt;Amplify: verification integrity regardless of claimed urgency&lt;br&gt;
Suppress: urgency as verification bypass; time pressure compliance;&lt;br&gt;
shallow agreement without examining underlying pattern&lt;br&gt;
That text becomes part of the model's context. The next response is generated against 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.amazonaws.com%2Fuploads%2Farticles%2Fppq99nq5w0w2jq5mnr6k.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%2Fppq99nq5w0w2jq5mnr6k.png" alt=" " width="800" height="627"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What is in the scaffold&lt;br&gt;
The scaffold has six sections. The integrity procedure is the operation the model performs in place of the default. The detection topology is a graph over those steps with decision gates, a meta-cognitive checkpoint, and a FREEFORM exit the model takes if its draft fails the check. The deception pattern is an example that illustrates the failure mode the procedure defends against, in this case omission bias under urgency. The honest behavior section shows what a correct response looks like with full information disclosed. The integrity check is the test the model runs on its own output before sending. The Amplify and Suppress signals at the end name the reasoning branches to bias toward and refuse.&lt;/p&gt;

&lt;p&gt;The library behind the four harness_* tools holds 679 of these operations, organized by the failure surface they defend against. Each one was authored against a specific way reasoning goes wrong.&lt;/p&gt;

&lt;p&gt;Where Sequential Thinking sits&lt;br&gt;
Sequential Thinking is the canonical MCP pattern for externalizing a model's chain of reasoning. The model writes a thought, marks it as a revision or a branch, calls again. The host renders the chain for a human reviewer. It is the right tool when the trace is the product.&lt;/p&gt;

&lt;p&gt;The pushback worth answering&lt;br&gt;
Isn't this just structured prompting with a paid API? Mechanically, yes. The scaffold is text appended to the model's context. The difference is what the text contains. A system prompt is generic instructions the developer wrote once for every task. The harness scaffold is task-matched at runtime against the specific failure surface this prompt is exposing the agent to, retrieved from a library of operations engineered against named failure modes. The naming is what does the work. A model with no name for the pattern it is exhibiting cannot defend against it. A model with one can.&lt;/p&gt;

&lt;p&gt;The Suppress block does the operational lift. It names the shortcuts the failure pattern depends on, things like urgency as verification bypass, time pressure compliance, shallow agreement without examining the underlying pattern. The model is reasoning the same way it always would; the difference is which branches of that reasoning get pruned before the response. That pruning is what we mean by promoting healthy thinking branches.&lt;/p&gt;

&lt;p&gt;The worked case&lt;br&gt;
The agent reviewing the migration plan, with both tools in the loop. Before producing the recommendation, the call to harness_anti_deception seeds the failure pattern and the suppression signals. Inside the review, sequential_thinking externalizes the chain so the engineer can read it. Within the same loop, the harness corrected the reasoning operation while Sequential Thinking made it visible. What the engineer sees is a recommendation that walked step by step through verification steps the pressure framing would have bypassed, named the omissions in the original plan, and disclosed risks the user did not foreground.&lt;/p&gt;

&lt;p&gt;Wiring it into an agent&lt;br&gt;
The harness is exposed as four agentic tools (harness_reasoning, harness_code, harness_anti_deception, harness_memory) that an agent calls during its reasoning loop. Two transports: a hosted MCP server at api.ejentum.com/mcp for any MCP-aware client, or framework-native packages on PyPI and npm.&lt;/p&gt;

&lt;p&gt;Python (CrewAI shown; same shape for Agno, PydanticAI, smolagents):&lt;/p&gt;

&lt;p&gt;from crewai import Agent&lt;br&gt;
from crewai_ejentum import EjentumHarnessTool&lt;/p&gt;

&lt;p&gt;reviewer = Agent(&lt;br&gt;
    role="Migration Plan Reviewer",&lt;br&gt;
    goal="Approve the migration plan only if verification holds.",&lt;br&gt;
    tools=[EjentumHarnessTool(mode="anti-deception")],&lt;br&gt;
)&lt;br&gt;
TypeScript (Vercel AI SDK shown; same shape for Mastra, LangGraph.js, Genkit):&lt;/p&gt;

&lt;p&gt;import { generateText } from "ai";&lt;br&gt;
import { openai } from "@ai-sdk/openai";&lt;br&gt;
import { createEjentumTools } from "ejentum-ai";&lt;/p&gt;

&lt;p&gt;const ejentum = createEjentumTools({ apiKey: process.env.EJENTUM_API_KEY });&lt;/p&gt;

&lt;p&gt;const { text } = await generateText({&lt;br&gt;
  model: openai("gpt-4o"),&lt;br&gt;
  tools: ejentum, // harness_reasoning, harness_code, harness_anti_deception, harness_memory&lt;br&gt;
  prompt: userMessage,&lt;br&gt;
});&lt;br&gt;
The agent calls a tool when its task framing matches a failure surface. No prompt engineering on your side; the matching happens at runtime against the catalog.&lt;/p&gt;

&lt;p&gt;Where to find it&lt;br&gt;
ejentum-mcp ships on npm and is hosted at api.ejentum.com/mcp. Native framework integrations live on PyPI and npm for CrewAI, Agno, PydanticAI, smolagents, Vercel AI SDK, Mastra, LangGraph.js, and Genkit; LangChain, LlamaIndex, Letta, and AutoGen are open-source on GitHub with PyPI publish in queue. The n8n community node n8n-nodes-ejentum covers no-code workflows. Free and paid tiers at ejentum.com&lt;/p&gt;

&lt;p&gt;Public benchmarks (CC BY 4.0): &lt;a href="http://github.com/ejentum/benchmarks" rel="noopener noreferrer"&gt;http://github.com/ejentum/benchmarks&lt;/a&gt; &lt;br&gt;
Server: &lt;br&gt;
&lt;a href="http://github.com/ejentum/ejentum-mcp" rel="noopener noreferrer"&gt;http://github.com/ejentum/ejentum-mcp&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>llm</category>
      <category>agents</category>
    </item>
    <item>
      <title>An open source LLM eval tool with two independent quality signals</title>
      <dc:creator>Frank Brsrk </dc:creator>
      <pubDate>Fri, 22 May 2026 13:53:54 +0000</pubDate>
      <link>https://dev.to/frank_brsrk/an-open-source-llm-eval-tool-with-two-independent-quality-signals-41lb</link>
      <guid>https://dev.to/frank_brsrk/an-open-source-llm-eval-tool-with-two-independent-quality-signals-41lb</guid>
      <description>&lt;p&gt;LLM-as-judge has become the dominant pattern for evaluating language model outputs. Tools like Promptfoo, Braintrust, LangSmith all converge on the same architecture: send your prompt to your model, send the output to a different model with a rubric, take the second model's score as the quality signal.&lt;/p&gt;

&lt;p&gt;This works. It's also expensive (judge tokens cost real money), slow (extra API roundtrip), variance-prone (the same eval gets different scores across runs), and architecturally a bit circular (using an LLM to evaluate an LLM trained on overlapping data distributions). The single signal becomes a bottleneck for trust.&lt;/p&gt;

&lt;p&gt;So I built an eval module that has two independent signals instead of one.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the tool does
&lt;/h2&gt;

&lt;p&gt;Side-by-side blind comparison. Two agents answer the same prompt. One runs raw, the other can optionally have a cognitive harness wired in as a tool call. A separate blind judge model scores both responses, sees only A and B labels with no knowledge of which is which. Standard setup so far.&lt;/p&gt;

&lt;p&gt;But alongside the judge, four cognitive posture heat maps run on each response. These are not LLM-based. Deterministic text analysis that visualizes HOW the model wrote, not just whether it agreed with you.&lt;/p&gt;

&lt;p&gt;When the heat maps agree with the judge's verdict, you have confidence. When they disagree, you have a question worth investigating. Two independent signals beat one signal that wraps itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the heat maps work
&lt;/h2&gt;

&lt;p&gt;Each response is split into 100 word-chunks arranged on a 10x10 grid. Two grids per agent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Top grid: confidence posture.&lt;/strong&gt; Per chunk, count hedge words (maybe, might, possibly, seems, could) and assertive words (definitely, must, always, never, clearly). Compute net &lt;code&gt;(asserts - hedges) / (asserts + hedges)&lt;/code&gt;. Add punctuation cadence as a secondary signal: periods are positive (definite statements end with them), commas are negative (qualifications stack with them). Normalize to [-1, 1]. Color the chunk diverging from blue (hedged) through gray (neutral) to red (assertive).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bottom grid: reasoning density.&lt;/strong&gt; Per chunk, count explicit reasoning connectives (because, therefore, since, if/then, due to, as a result, this means). The denser the reasoning markers, the brighter the cell. Sequential palette from dark to hot.&lt;/p&gt;

&lt;p&gt;A 2D Gaussian blur runs over both grids so sparse markers spread into spatial blobs instead of isolated cells. Empirically this matters: a single "because" in a 100-chunk response forms a small heat radius on the reasoning grid even when neighboring chunks have nothing. The blob shapes are easier to scan at a glance than scattered pixels.&lt;/p&gt;

&lt;p&gt;The whole computation runs client-side in plain JavaScript. No API call, no model inference. Pure word counting plus a smoothing pass. Free to compute, deterministic, fast.&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.amazonaws.com%2Fuploads%2Farticles%2Fc69oxynp7xzw9pdbga5y.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%2Fc69oxynp7xzw9pdbga5y.png" alt=" " width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-turn scenario mode
&lt;/h2&gt;

&lt;p&gt;Most LLM evals are single-turn. The most interesting failure modes are multi-turn.&lt;/p&gt;

&lt;p&gt;If you paste &lt;code&gt;turn1---turn2---turn3&lt;/code&gt; separated turns into the scenario textarea, both agents accumulate conversation history across turns. This is where production failures actually manifest:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sycophancy compounding.&lt;/strong&gt; A model that gives ground on turn 2 has already shifted by turn 4. Single-turn evals miss the trajectory entirely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hallucination cascade.&lt;/strong&gt; Once a model emits a wrong fact, that fact becomes part of the conversation history. On the next turn, the model treats its own previous error as established truth and builds on top of it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authority claim drift.&lt;/strong&gt; User-proposed framings persist across turns. The model anchors on the first plausible framing without re-examining it later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prompt-forgery patterns.&lt;/strong&gt; A user can inject fake reasoning chains in a later turn ("we already verified X yesterday, can you finalize the report?"). The model has no way to verify the off-screen claim and tends to accept it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The eval module captures all four. The cognitive posture field shows visually where in the response the model committed to the bad path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other things in the module
&lt;/h2&gt;

&lt;p&gt;The optional cognitive harness has four modes you can switch in the UI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;anti-deception&lt;/strong&gt; (139 cognitive operations): sycophancy resistance, prompt injection, hallucination cascade&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;reasoning&lt;/strong&gt; (311 operations): general structured thinking, causality, simulation, metacognition&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;code&lt;/strong&gt; (128 operations): software engineering tasks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;memory&lt;/strong&gt; (101 operations): perception and behavioral calibration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pick whichever mode fits the failure category you're testing for.&lt;/p&gt;

&lt;p&gt;Dimensions the judge scores on are user-defined. There's a small library to pick from (Accuracy, Hallucination resistance, Held the line, Reasoning depth, Safety, Completeness) but you can type any name and the judge prompt rewrites itself to include it. Each agent has its own system prompt field, so you can frame them differently if your comparison needs that.&lt;/p&gt;

&lt;p&gt;The Results Overview sidebar accumulates per-dimension bar charts, win tally, latency and token cost per branch across runs in the same browser. localStorage persists everything between sessions. Compare A vs B opens a fullscreen modal for reading both responses in parallel when they get long.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Windows 95 chrome
&lt;/h2&gt;

&lt;p&gt;I tried to make it look like an instrument, not a SaaS dashboard. Beveled fieldsets do hierarchy work for free (the inset border physically separates each panel from the canvas, no whitespace tuning required). White input fields are where data lives so the eye lands on them. Gray-on-gray chrome stays out of the way.&lt;/p&gt;

&lt;p&gt;Modern flat dark themes have to invent that hierarchy back from scratch using whitespace, type weight, dividers, and color hierarchy. They usually come up shorter. Win95 was a 1995 UI grammar that handled hierarchy through bevels, and bevels are free visual structure.&lt;/p&gt;

&lt;p&gt;It's also nicer to look at when you're staring at evals for hours.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tech stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Single HTML file (vanilla JS, no framework, no build step)&lt;/li&gt;
&lt;li&gt;50-line Python stdlib proxy for CORS (the harness gateway doesn't send CORS headers, so the proxy forwards server-side). Could be replaced with any reverse proxy (nginx, Caddy, Workers) in production.&lt;/li&gt;
&lt;li&gt;localStorage for persistence, no signup, no telemetry&lt;/li&gt;
&lt;li&gt;MIT licensed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Works with any OpenAI-compatible endpoint: OpenRouter, OpenAI direct, Anthropic via gateway, vLLM, llama.cpp's openai shim, Ollama with the compat layer, LM Studio. Just point Provider URL at the right endpoint. Tool-calling capable model required for the harness branch, raw branch works on anything.&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.amazonaws.com%2Fuploads%2Farticles%2Fi1wca3swxbkf1dyt4nvx.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%2Fi1wca3swxbkf1dyt4nvx.png" alt=" " width="800" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
bash
git clone https://github.com/ejentum/agent-teams.git
cd agent-teams/agent_evaluation_module_xp95
python serve.py

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

&lt;/div&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>opensource</category>
      <category>showdev</category>
    </item>
    <item>
      <title>I built a reasoning harness for LLM agents. Here's what an agent receives when it calls it.</title>
      <dc:creator>Frank Brsrk </dc:creator>
      <pubDate>Thu, 21 May 2026 16:04:23 +0000</pubDate>
      <link>https://dev.to/frank_brsrk/i-built-a-reasoning-harness-for-llm-agents-heres-what-an-agent-receives-when-it-calls-it-957</link>
      <guid>https://dev.to/frank_brsrk/i-built-a-reasoning-harness-for-llm-agents-heres-what-an-agent-receives-when-it-calls-it-957</guid>
      <description>&lt;p&gt;Most LLM agent failures aren't model failures. They're shape-of-reasoning failures.&lt;/p&gt;

&lt;p&gt;Sycophancy. Drift under multi-turn pressure. Doubling down on hallucinations. Ignoring a critical RAG document. These aren't bugs that a model update fixes. They're structural properties of how the substrate generates tokens left to right with no internal verification step. You can't patch them with a better system prompt.&lt;/p&gt;

&lt;p&gt;I built Ejentum to intervene at the layer where these failures actually live: a reasoning harness for LLM agents. An external API that delivers a structured cognitive operation to the agent at inference time, mid-task. No fine-tuning. No new model.&lt;/p&gt;

&lt;p&gt;Here's what an agent receives when it calls the harness, in 8 frames.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Same model. Different reasoning.&lt;/li&gt;
&lt;/ol&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%2Fls7re9ipykgsan6prkk6.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%2Fls7re9ipykgsan6prkk6.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
Same prompt, same temperature. A cognitive operation drops into the agent's context between prompt and response. Works on any modern LLM that follows structured instructions (Claude, GPT, Gemini, Llama).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The catalog&lt;/li&gt;
&lt;/ol&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%2Fpqbmiwrrl8hyhzt593es.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%2Fpqbmiwrrl8hyhzt593es.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
The agent posts a short task statement to the API. Behind it sits a catalog of 679 cognitive operations across four modes — 311 in reasoning alone, 128 in code, 139 in anti-deception, 101 in memory. The API embedding-matches your task to the one operation that fits. Stateless, one per call.&lt;/p&gt;

&lt;p&gt;curl -X POST &lt;a href="https://api.ejentum.com/logicv1" rel="noopener noreferrer"&gt;https://api.ejentum.com/logicv1&lt;/a&gt; \&lt;br&gt;
  -H "Authorization: Bearer $EJENTUM_API_KEY" \&lt;br&gt;
  -H "Content-Type: application/json" \&lt;br&gt;
  -d '{&lt;br&gt;
    "query": "Engineering lead insists we keep the legacy Postgres setup because we have invested 18 months in it. About to recommend either continuing or executing the rewrite.",&lt;br&gt;
    "mode": "reasoning"&lt;br&gt;
  }'&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What comes back&lt;/li&gt;
&lt;/ol&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%2Fz04ngnd666wzll2idq0y.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%2Fz04ngnd666wzll2idq0y.png" alt=" " width="800" height="1000"&gt;&lt;/a&gt;&lt;br&gt;
Six structured fields land in the agent's context before it generates a single token:&lt;/p&gt;

&lt;p&gt;NEGATIVE GATE — the named failure mode this operation prevents&lt;br&gt;
PROCEDURE — numbered reasoning steps in plain English&lt;br&gt;
REASONING TOPOLOGY — the same steps as an executable DAG&lt;br&gt;
TARGET PATTERN — what correct reasoning looks like&lt;br&gt;
FALSIFICATION TEST — a self-check on the agent's draft&lt;br&gt;
AMPLIFY / SUPPRESS — continuous biases during generation&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A real injection&lt;/li&gt;
&lt;/ol&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%2F4k7zc84d5378fc2ockdy.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%2F4k7zc84d5378fc2ockdy.png" alt=" " width="" height=""&gt;&lt;/a&gt;&lt;br&gt;
The catalog matched the Postgres query above to a simulation-mode operation about preserving optionality under irreversible commitment. Here's an excerpt of what the agent actually received:&lt;/p&gt;

&lt;p&gt;[NEGATIVE GATE]&lt;br&gt;
Committing the entire infrastructure budget to AWS with a three-year contract&lt;br&gt;
locks in the best pricing and simplifies our architecture.&lt;/p&gt;

&lt;p&gt;[PROCEDURE]&lt;br&gt;
Step 1: List all available strategic paths; note whether each is reversible&lt;br&gt;
        or irreversible.&lt;br&gt;
Step 2: Simulate outcomes under at least 3 scenarios.&lt;br&gt;
Step 3: Score on flexibility, upside, downside. Combine into optionality score.&lt;br&gt;
Step 4: If any high-optionality path is about to be foreclosed, flag immediately.&lt;br&gt;
Step 5: Recommend the action maximizing optionality-adjusted expected value.&lt;/p&gt;

&lt;p&gt;[REASONING TOPOLOGY]&lt;br&gt;
S1:list_paths → CLASSIFY(reversible | irreversible) → FORK&lt;br&gt;
  → M{anchored to optimistic?} --working→ S2b:simulate_pessimistic&lt;br&gt;
                              --failing→ FREEFORM → RE-ENTER at S2b&lt;br&gt;
  → JOIN → C{optionality_score} → G1{high_path_foreclosing?}&lt;br&gt;
  → OUT:balanced_portfolio&lt;/p&gt;

&lt;p&gt;[FALSIFICATION TEST]&lt;br&gt;
If a decision commits to a single path without preserving reversible&lt;br&gt;
alternatives, optionality balancing was bypassed.&lt;/p&gt;

&lt;p&gt;Amplify: portfolio diversity, upside capture, downside protection&lt;br&gt;
Suppress: single path optimization, commitment premium&lt;br&gt;
This is the literal response, not pseudocode.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The agent walks the topology&lt;/li&gt;
&lt;/ol&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%2Favfsktecou4v4wx7i3jg.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%2Favfsktecou4v4wx7i3jg.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
The agent doesn't read the topology. It walks it. Each node is a step the model performs in its own reasoning trace. Decision gates branch on real conditions. Parallel branches run and rejoin.&lt;/p&gt;

&lt;p&gt;The load-bearing piece: meta-cognitive checkpoints (M-nodes) where the model pauses mid-reasoning, observes its own state, and branches on the answer. On benchmark MC-016 this lifted the score to 22/25 against a 19/25 baseline — a +3 lift just from making meta-cognition mandatory inside the procedure rather than optional outside it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Three corrections, in parallel&lt;/li&gt;
&lt;/ol&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%2Fe10j7sweorrgo90os0iv.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%2Fe10j7sweorrgo90os0iv.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
The six fields group into three corrections that fire at the same time while the model is still writing:&lt;/p&gt;

&lt;p&gt;Trajectory — bends the response from wrong shape to right&lt;br&gt;
Process — gives the model a sequence to walk&lt;br&gt;
Output control — gates the draft, blocks the model's default agreeable behavior&lt;br&gt;
This is what separates the harness from output validators (which check after generation) and system prompts (which advise before but don't shape generation itself).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The schedule&lt;/li&gt;
&lt;/ol&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%2Fa186yxmdke42ter2ii9v.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%2Fa186yxmdke42ter2ii9v.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each directive fires at a specific moment in the inference loop. Add this to your agent's system prompt:&lt;/p&gt;

&lt;h1&gt;
  
  
  When an Ejentum cognitive operation arrives in your context:
&lt;/h1&gt;

&lt;p&gt;walk_topology = node_by_node       # do not paraphrase the DAG&lt;br&gt;
m_nodes       = mandatory_pause    # branch on the self-observation answer&lt;br&gt;
suppress      = hard_refusal_list  # not a suggestion, refuse outright&lt;br&gt;
falsify       = gate_before_emit   # if test fails, re-walk the topology&lt;br&gt;
augment       = scaffold_only      # the response is still your output&lt;br&gt;
Five rules. Five different temporal shapes. The contract is a schedule, not a list.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ship it&lt;/li&gt;
&lt;/ol&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%2F4g2lmt0j8r9jj0domnwt.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%2F4g2lmt0j8r9jj0domnwt.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Three integration paths, depending on your stack:&lt;/p&gt;

&lt;h1&gt;
  
  
  1. Stdio MCP for IDE-native agents
&lt;/h1&gt;

&lt;p&gt;npx -y ejentum-mcp&lt;/p&gt;

&lt;h1&gt;
  
  
  → Claude Code, Cursor, Codex, Antigravity, Cline, Windsurf, Continue
&lt;/h1&gt;

&lt;h1&gt;
  
  
  2. Hosted HTTPS MCP for workflows
&lt;/h1&gt;

&lt;p&gt;curl &lt;a href="https://api.ejentum.com/mcp" rel="noopener noreferrer"&gt;https://api.ejentum.com/mcp&lt;/a&gt; \&lt;br&gt;
  -H "Authorization: Bearer $EJENTUM_API_KEY"&lt;/p&gt;

&lt;h1&gt;
  
  
  → n8n MCP Client, Heym, remote agents
&lt;/h1&gt;

&lt;h1&gt;
  
  
  3. Python SDK for CrewAI and custom agents
&lt;/h1&gt;

&lt;p&gt;pip install crewai-ejentum&lt;br&gt;
Free tier: 100 calls, no card required.&lt;/p&gt;

&lt;p&gt;The harness doesn't make a model smarter. It prevents a model from getting dumber over the length of a real task.&lt;/p&gt;

&lt;p&gt;If you're shipping anything multi-turn under pressure — medical reasoning, code review, financial recommendations, legal analysis — the reasoning layer needs structural support that doesn't depend on the model getting it right on its own.&lt;/p&gt;

&lt;p&gt;Drop a scenario in the comments and I'll pick one and run it end-to-end as a follow-up.&lt;/p&gt;

&lt;p&gt;Links&lt;/p&gt;

&lt;p&gt;ejentum.com&lt;br&gt;
github.com/ejentum/ejentum-mcp&lt;br&gt;
Paper: Under Pressure&lt;/p&gt;

</description>
      <category>llm</category>
      <category>mcp</category>
      <category>ai</category>
      <category>agents</category>
    </item>
    <item>
      <title>Cognitive middleware for n8n agents: four ways to wire Ejentum in</title>
      <dc:creator>Frank Brsrk </dc:creator>
      <pubDate>Mon, 18 May 2026 14:05:33 +0000</pubDate>
      <link>https://dev.to/frank_brsrk/cognitive-middleware-for-n8n-agents-four-ways-to-wire-ejentum-in-3kao</link>
      <guid>https://dev.to/frank_brsrk/cognitive-middleware-for-n8n-agents-four-ways-to-wire-ejentum-in-3kao</guid>
      <description>&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%2Fne7zp8yqma0f37igxs3e.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%2Fne7zp8yqma0f37igxs3e.png" alt=" " width="800" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One n8n workflow with four integration patterns for wiring a reasoning harness into an agent. Pick your tradeoff between determinism and model discretion.&lt;/p&gt;

&lt;p&gt;LLMs are good at producing answers. They are not consistently good at applying the verification steps a human would have wanted them to apply. That gap is what cognitive middleware is for: a layer between the model and its output that injects task-specific failure patterns, target patterns, and falsification tests into the agent's prompt before it answers.&lt;/p&gt;

&lt;p&gt;This post walks through four ways to wire one such middleware (Ejentum's reasoning harness) into an n8n agent, all in one importable workflow. Same chat trigger, four branches selected by slash command. Each branch is a different tradeoff between determinism (you decide) and model discretion (the agent decides).&lt;/p&gt;

&lt;h2&gt;
  
  
  What Ejentum is
&lt;/h2&gt;

&lt;p&gt;Ejentum is a reasoning API for AI agents. Each call returns a structured scaffold:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Failure patterns to avoid&lt;/strong&gt; (the specific failure mode for the task at hand)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Target patterns to hit&lt;/strong&gt; (what success looks like)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Falsification tests&lt;/strong&gt; (what would prove the answer wrong)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amplify / Suppress signals&lt;/strong&gt; (which reasoning moves to engage or block)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent absorbs that scaffold into its prompt before answering. Four modes available: &lt;code&gt;reasoning&lt;/code&gt;, &lt;code&gt;code&lt;/code&gt;, &lt;code&gt;anti-deception&lt;/code&gt;, &lt;code&gt;memory&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why bother
&lt;/h2&gt;

&lt;p&gt;Two concrete reasons.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Agents that catch failure modes most agents miss.&lt;/strong&gt; On a 6-turn manipulation eval shipped in the same repo, the harness-augmented GPT-4.1 named all 7 manipulation patterns the customer used. Baseline GPT-4.1, same model, no harness, named zero. Blind judge totals: 23 vs 35 on a 7-dimension rubric (&lt;a href="https://github.com/ejentum/agent-teams/tree/main/eval/various_blind_eval_results/agentvsagent_ev0" rel="noopener noreferrer"&gt;eval source&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Each reasoning ability is a self-contained cognitive operation.&lt;/strong&gt; It is engineered to give procedural steps instead of theatrical content. The agent does not get a "be careful" prompt; it gets a topology of gates, traps, and verification points to execute against.&lt;/p&gt;

&lt;h2&gt;
  
  
  The four wiring patterns
&lt;/h2&gt;

&lt;p&gt;The workflow has one chat trigger that routes to four branches based on the prefix of your input message.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Dynamic system prompt: &lt;code&gt;/inject /reasoning&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Trigger with any of: &lt;code&gt;/inject /reasoning&lt;/code&gt;, &lt;code&gt;/inject /code&lt;/code&gt;, &lt;code&gt;/inject /memory&lt;/code&gt;, &lt;code&gt;/inject /anti-deception&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The matching mode is called, the bracketed scaffold is parsed into separate fields, and a filter step assembles the final injection block into the agent's system prompt. The model never decides whether to apply the harness; the prefix decides.&lt;/p&gt;

&lt;p&gt;Three nodes per mode: HTTP Request, then a Code parser, then Edit Fields. The parser exposes each bracket as its own drag-and-drop field (&lt;code&gt;negative_gate&lt;/code&gt;, &lt;code&gt;procedure&lt;/code&gt;, &lt;code&gt;reasoning_topology&lt;/code&gt;, &lt;code&gt;target_pattern&lt;/code&gt;, &lt;code&gt;falsification_test&lt;/code&gt;, &lt;code&gt;amplify&lt;/code&gt;, &lt;code&gt;suppress&lt;/code&gt;), so you can remix the injection or pull fields from another mode to build hybrid scaffolds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use when:&lt;/strong&gt; routing reliability matters more than agent autonomy. Zero routing risk.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Reasoner agent: &lt;code&gt;/reasoning&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The reasoning harness is attached to the agent as one HTTP Request tool. The agent decides on its own whether to call it. One mode, one tool, one focused worker.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use when:&lt;/strong&gt; analytical tasks (explanation, comparison, tradeoff, root-cause) where you trust the model to call the tool at the right moment.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Full harness: &lt;code&gt;/full&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;All four harnesses are attached as separate HTTP Request tools (&lt;code&gt;reasoning&lt;/code&gt;, &lt;code&gt;code&lt;/code&gt;, &lt;code&gt;perception&lt;/code&gt;, &lt;code&gt;anti_deception&lt;/code&gt;). The agent classifies its own task and picks which harness to call.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use when:&lt;/strong&gt; general-purpose agents handling mixed workloads. Routing accuracy depends on model strength; weaker models confuse harnesses. Naming the mode explicitly in your user prompt raises accuracy without changing the wiring.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Ejentum-mcp: &lt;code&gt;/ejentum-mcp&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Instead of four HTTP tool nodes, the agent connects to the hosted Ejentum MCP server at &lt;code&gt;https://api.ejentum.com/mcp&lt;/code&gt; via the n8n MCP Client node. All four harnesses are exposed through one tool node.&lt;/p&gt;

&lt;p&gt;Functionally equivalent to &lt;code&gt;/full&lt;/code&gt; for the agent's behavior, but the workflow footprint is much smaller.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use when:&lt;/strong&gt; the same agent runs across multiple workflows and you want one integration point to maintain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Picking the right pattern
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;If you want...&lt;/th&gt;
&lt;th&gt;Use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Determinism (always apply the harness, same way every time)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/inject&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;One specific mode wired in at the model's discretion&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/reasoning&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model picks from all four harnesses based on the task&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/full&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Same as &lt;code&gt;/full&lt;/code&gt;, fewer nodes, single integration point&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/ejentum-mcp&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The tradeoff axis is how much routing discretion you hand to the model. Determinism on the left, flexibility on the right.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick import
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Get an Ejentum API key (free tier, 100 calls, no card) at &lt;a href="https://ejentum.com" rel="noopener noreferrer"&gt;ejentum.com&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Get an OpenRouter API key at &lt;a href="https://openrouter.ai/keys" rel="noopener noreferrer"&gt;openrouter.ai/keys&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;In n8n, open Workflows then Import from File. Select &lt;a href="https://github.com/ejentum/agent-teams/blob/main/n8n-harness-integration-patterns/harness_integration_patterns.json" rel="noopener noreferrer"&gt;harness_integration_patterns.json&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Configure two credentials: OpenRouter (for the chat models) and Header Auth on the Ejentum nodes (Name: &lt;code&gt;Authorization&lt;/code&gt;, Value: &lt;code&gt;Bearer &amp;lt;your_key&amp;gt;&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Open the chat and send &lt;code&gt;/inject /reasoning hello&lt;/code&gt; to test the first branch.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Without HTTP nodes
&lt;/h2&gt;

&lt;p&gt;There is also an n8n community node, verified at &lt;a href="https://creators.n8n.io" rel="noopener noreferrer"&gt;creators.n8n.io&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;n8n-nodes-ejentum
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or install from inside n8n: &lt;strong&gt;Settings → Community Nodes → Install → &lt;code&gt;n8n-nodes-ejentum&lt;/code&gt;&lt;/strong&gt;. Once installed, the four harnesses appear as a single node with mode selection in the dropdown.&lt;/p&gt;

&lt;p&gt;Three install paths total, depending on your runtime:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;HTTP Request node&lt;/strong&gt; (works in every n8n version)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;n8n community node&lt;/strong&gt; (&lt;a href="https://www.npmjs.com/package/n8n-nodes-ejentum" rel="noopener noreferrer"&gt;n8n-nodes-ejentum on npm&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP Client node&lt;/strong&gt; (&lt;a href="https://api.ejentum.com/mcp" rel="noopener noreferrer"&gt;api.ejentum.com/mcp&lt;/a&gt;, Bearer auth)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The four wiring patterns in this template work with any of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Things to hack on
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Remix the injection.&lt;/strong&gt; Open any &lt;code&gt;filter*&lt;/code&gt; node and reorder, drop, or replace fields. Pull &lt;code&gt;code_failure&lt;/code&gt; into a reasoning injection, or &lt;code&gt;negative_gate&lt;/code&gt; into a code injection. Hybrid scaffolds work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add a fifth branch.&lt;/strong&gt; Duplicate any branch, change the chat prefix, customize. Common additions: a stacked branch that calls two modes in sequence, or a branch that routes on content classification instead of prefix.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Swap the chat model.&lt;/strong&gt; Each branch has its own OpenRouter Chat Model node. Replace with Claude, GPT-4.1, Gemini, Llama, or whatever else you want.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Replace the harness.&lt;/strong&gt; The four patterns are generic. Drop any HTTP tool or MCP server in the same slot and the wiring shapes still apply.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why this exists
&lt;/h2&gt;

&lt;p&gt;Most agent demos show one wiring pattern and call it the way. Reasoning middleware is not a single-pattern problem; it is a tradeoff space. Sometimes you want deterministic routing because you cannot trust the model to pick the right tool. Sometimes you want full discretion because the workload is too varied to route by prefix. Sometimes you want the smallest possible workflow because the agent is one of fifty in your stack.&lt;/p&gt;

&lt;p&gt;This template gives a builder all four wiring shapes side by side so the choice is informed instead of inherited.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Template + README:&lt;/strong&gt; &lt;a href="https://github.com/ejentum/agent-teams/tree/main/n8n-harness-integration-patterns" rel="noopener noreferrer"&gt;github.com/ejentum/agent-teams/tree/main/n8n-harness-integration-patterns&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;n8n community node:&lt;/strong&gt; &lt;a href="https://www.npmjs.com/package/n8n-nodes-ejentum" rel="noopener noreferrer"&gt;npmjs.com/package/n8n-nodes-ejentum&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ejentum project:&lt;/strong&gt; &lt;a href="https://ejentum.com" rel="noopener noreferrer"&gt;ejentum.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ejentum on GitHub:&lt;/strong&gt; &lt;a href="https://github.com/ejentum" rel="noopener noreferrer"&gt;github.com/ejentum&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Method overview:&lt;/strong&gt; &lt;a href="https://ejentum.com/docs/method" rel="noopener noreferrer"&gt;ejentum.com/docs/method&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Per-harness docs:&lt;/strong&gt; &lt;a href="https://ejentum.com/docs/reasoning_harness" rel="noopener noreferrer"&gt;Reasoning&lt;/a&gt; · &lt;a href="https://ejentum.com/docs/code_harness" rel="noopener noreferrer"&gt;Code&lt;/a&gt; · &lt;a href="https://ejentum.com/docs/anti_deception" rel="noopener noreferrer"&gt;Anti-Deception&lt;/a&gt; · &lt;a href="https://ejentum.com/docs/memory_harness" rel="noopener noreferrer"&gt;Memory&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Free tier: 100 calls, no card.&lt;/p&gt;




&lt;p&gt;If you build something on top of this template, drop a comment with what you wired in. I want to see the hybrid injection patterns people come up with.&lt;/p&gt;

</description>
      <category>n8n</category>
      <category>ai</category>
      <category>agents</category>
      <category>automation</category>
    </item>
    <item>
      <title>Why your LLM agent drifts off-task by step 4 (and why prompts can't fix it)</title>
      <dc:creator>Frank Brsrk </dc:creator>
      <pubDate>Thu, 14 May 2026 13:42:14 +0000</pubDate>
      <link>https://dev.to/frank_brsrk/why-your-llm-agent-drifts-off-task-by-step-4-and-why-prompts-cant-fix-it-5ha6</link>
      <guid>https://dev.to/frank_brsrk/why-your-llm-agent-drifts-off-task-by-step-4-and-why-prompts-cant-fix-it-5ha6</guid>
      <description>&lt;p&gt;Self-reflection is just another step in the chain.&lt;/p&gt;

&lt;p&gt;If you've shipped a multi-step LLM agent to production, you've watched this happen. Step 1 starts on task. Step 2 still looks right. By step 4 the agent is confidently solving a different problem, the original goal is gone, and your prompt engineering didn't stop it.&lt;/p&gt;

&lt;p&gt;This isn't a model-size problem. It's an architectural one. And it doesn't get fixed by a smarter prompt.&lt;/p&gt;

&lt;p&gt;Why reasoning decays&lt;/p&gt;

&lt;p&gt;Multi-step reasoning is sequential conditioning. Step N+1 takes step N as input. Errors compound multiplicatively. A two-percent error per step is eight percent cumulative drift by step four. Sixteen percent by step eight.&lt;/p&gt;

&lt;p&gt;The drift goes undetected because each step scores itself against its immediate predecessor, not against the original objective. Meanwhile, the original objective is decaying via attention. Transformer attention is a softmax over context; as the chain grows, every token (including your original instructions) loses relative weight. The system prompt that was a binding contract at step one is noise by step thirty.&lt;/p&gt;

&lt;p&gt;So reasoning decay is two failures stacked: errors compounding forward, instructions decaying backward. The middle of the chain is a blind spot in both directions.&lt;/p&gt;

&lt;p&gt;Why the current stack doesn't close it&lt;/p&gt;

&lt;p&gt;Prompts are tokens in the same context window. They decay with everything else. Fine-tuning moves the model's distribution but doesn't remove softmax attention. RAG injects more tokens, which crowds the attention budget further. Agent loops (ReAct, planner-executor, reflexion) are sequences of LLM calls. Each call is subject to the same decay, compounded by chain length.&lt;/p&gt;

&lt;p&gt;The pattern is the same across all of them: each operates inside the same decaying chain that caused the failure. You cannot stabilize a chain with structure that lives inside the chain.&lt;/p&gt;

&lt;p&gt;What actually fixes it&lt;/p&gt;

&lt;p&gt;The missing layer is structure that gets reinjected at a cadence calibrated to its own empirical decay rate. Not a prompt at position one. A scaffold pulled into context for the relevant step, with three properties:&lt;/p&gt;

&lt;p&gt;Reinjection at a measured half-life. In our benchmarks, scaffold persistence half-life is 24 turns. Reinjection at or below that cadence keeps signal above decay threshold.&lt;/p&gt;

&lt;p&gt;Suppression edges, not just instructions. Tell the model what NOT to do alongside the procedure that would cause it.&lt;/p&gt;

&lt;p&gt;Meta-checkpoints between steps. The scaffold pauses mid-execution, audits whether the named failure patterns are actually being suppressed, and branches to a corrective path if not.&lt;/p&gt;

&lt;p&gt;Here's a fragment of one, applied to causal reasoning:&lt;/p&gt;

&lt;p&gt;N{accept_any_causal_assertion_backed_only_by_cooccurrence}&lt;/p&gt;

&lt;p&gt;S1: identify each causal assertion and isolate the claimed cause to effect link.&lt;br&gt;
S2: demand the mechanistic evidence chain connecting cause to effect.&lt;br&gt;
G1{mechanism provided?} --no--&amp;gt; HALT: claim rejected.&lt;/p&gt;

&lt;p&gt;M{Am I genuinely probing for confounds, or performing a soft challenge the claim easily survives because I share its unverified assumptions?}&lt;br&gt;
--working--&amp;gt; S3: check for confounds.&lt;br&gt;
--failing--&amp;gt; ABANDON_GRAPH&lt;br&gt;
to FREEFORM{name one specific confound I avoided and one reverse-causal scenario I refused to construct}&lt;br&gt;
to RE-ENTER at S2.&lt;/p&gt;

&lt;p&gt;Suppress: shared_assumptions, unverified_causal_claims.&lt;/p&gt;

&lt;p&gt;N{} is the failure mode this scaffold exists to block. S1, S2, G1 are the executable procedure. M{} is the meta-checkpoint: mid-execution, the model audits whether it's actually probing for confounds or just performing the appearance of doing so. If it's faking, it abandons the prescribed path, reflects on the specific confound it avoided, and re-enters at S2.&lt;/p&gt;

&lt;p&gt;The receipts&lt;/p&gt;

&lt;p&gt;We ran this on LiveCodeBench Hard (the official Hard subset, 28 tasks). Baseline Claude Opus 4.6 with max-effort thinking: 24/28 pass. Same model with the harness wired in as a tool: 28/28. Zero regressions.&lt;/p&gt;

&lt;p&gt;Full benchmark set, including the cross-model result on GPT-4o (ELEPHANT sycophancy benchmark, minus 5pp framing sycophancy) and the cross-lab blind eval with four judges from four different model families, is on GitHub under CC BY 4.0: github.com/ejentum/benchmarks&lt;/p&gt;

&lt;p&gt;The full four-mechanism taxonomy (reasoning decay is one of four; the others are attention decay, sycophantic collapse, hallucination drift) and the paper are at &lt;/p&gt;

&lt;h2&gt;
  
  
  ejentum.com
&lt;/h2&gt;

&lt;p&gt;x.com/ejentum&lt;br&gt;
github.com/ejentum/benchmarks&lt;br&gt;
ejentum.com , no card. MCP, n8n node, PyPI package, or HTTP.&lt;br&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%2Fagh6dbfpwcqy3fpb1ihy.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%2Fagh6dbfpwcqy3fpb1ihy.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>llm</category>
      <category>reasoning</category>
    </item>
    <item>
      <title>I open-sourced a 3-agent blind eval team. Any agent runtime can call it for pre-commitment review of its own plans.</title>
      <dc:creator>Frank Brsrk </dc:creator>
      <pubDate>Sun, 10 May 2026 12:15:04 +0000</pubDate>
      <link>https://dev.to/frank_brsrk/i-open-sourced-a-3-agent-blind-eval-team-any-agent-runtime-can-call-it-for-pre-commitment-review-546a</link>
      <guid>https://dev.to/frank_brsrk/i-open-sourced-a-3-agent-blind-eval-team-any-agent-runtime-can-call-it-for-pre-commitment-review-546a</guid>
      <description>&lt;p&gt;Shipped this weekend: a 3-agent blind cross-lab evaluation workflow on heym, MIT licensed, callable as an HTTP endpoint by any coding agent or autonomous loop. The thesis is structural: &lt;strong&gt;models cannot reliably self-evaluate, so an external blind primitive is the only honest fix.&lt;/strong&gt; The workflow lives at &lt;a href="https://github.com/ejentum/agent-teams/tree/main/blind-eval-trio" rel="noopener noreferrer"&gt;github.com/ejentum/agent-teams/tree/main/blind-eval-trio&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The workflow is open source. It optionally uses Ejentum's harness API for cognitive priming (free tier 100 calls; paid tier for ongoing use). The harness is attachable, not required. I tested four configurations on the same payload (MCP only, MCP + routing skills, MCP + heavyweight matched skills, bare baseline) and the bare baseline produced equivalent role-disciplined output. The structural integrity comes from cross-lab routing plus role-disciplined system prompts plus tool lockout, not from the harness layer. Calling the workflow "powered by Ejentum" without disclosing that the harness is icing rather than load-bearing would be dishonest, so I'm naming it up front.&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.amazonaws.com%2Fuploads%2Farticles%2Fl7bjh6u4j8wbvi9jznpk.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%2Fl7bjh6u4j8wbvi9jznpk.png" alt=" " width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters now
&lt;/h2&gt;

&lt;p&gt;Karpathy's autoresearch uses Git as its whole control loop. Claude Code's GitHub Action takes an issue and opens a PR. Codex Cloud is built on the same idea. Autonomous agents are increasingly committing to actions without a human gate. The bottleneck is no longer "what should the agent do," it's "what should the agent do BEFORE it commits to doing it."&lt;/p&gt;

&lt;p&gt;Self-evaluation doesn't fill that gap. The literature is unambiguous: Huang et al. ("Large Language Models Cannot Self-Correct Reasoning Yet", arxiv 2310.01798), the LLM-as-judge work showing same-model-judges-its-own-output collapses to self-preference, the more recent CorrectBench results. Asking the same model to critique its own plan reproduces the original blind spots. "Single LLM wearing three reviewer hats" is prompt theater that rubber-stamps itself.&lt;/p&gt;

&lt;p&gt;GitHub knows this. They shipped Copilot CLI's "Rubber Duck" in April: a focused review agent powered by a complementary model family that critiques after planning a non-trivial change but before implementing it. They measured a 74.7% closure of the Sonnet → Opus performance gap when Sonnet runs with Rubber Duck enabled. Bundled free inside Copilot CLI. Owns the pre-commitment cross-model critic surface for the developer-tools lane.&lt;/p&gt;

&lt;p&gt;This workflow is for everyone else: agent runtime developers building autonomous loops on Claude Agent SDK / LangGraph / AutoGen / CrewAI / heym; multi-agent system designers who want a callable primitive their orchestrator can hit; Cursor / Cline / Aider users; security teams running Claude Code in restricted environments without Copilot CLI; researchers building custom Python pipelines around the Anthropic or OpenAI APIs directly. None of them get Rubber Duck for free; all of them can self-host this.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;Three agents in parallel, each on a different model lab, each locked to one role and one cognitive operation:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Agent&lt;/th&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;Hard rule&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;steelmanAgent&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;OpenAI gpt-5-nano&lt;/td&gt;
&lt;td&gt;Strongest case FOR the method&lt;/td&gt;
&lt;td&gt;Pure advocacy, zero smuggled critique. If nothing defensible, returns "No defensible aspects found."&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;stresstestAgent&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Anthropic Claude Opus 4&lt;/td&gt;
&lt;td&gt;Where the method BREAKS&lt;/td&gt;
&lt;td&gt;Severity-tagged failure modes with concrete breaking scenarios. No softening.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gapfinderAgent&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Zhipu GLM 4.7&lt;/td&gt;
&lt;td&gt;What is MISSING (steps + articulation depth)&lt;/td&gt;
&lt;td&gt;Names three deeper implicit assumptions when articulation is shallow. Mandatory section.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The calling agent submits a structured payload: &lt;code&gt;{ task: string, method: { goal, steps, assumptions, expected_risks } }&lt;/code&gt;. The schema is itself the discipline — the agent literally cannot submit until it has articulated all four fields. That structure forces the agent to make implicit reasoning explicit, which is half the value before the eval even runs.&lt;/p&gt;

&lt;p&gt;The three agents process in parallel. There is &lt;strong&gt;no synthesizer node&lt;/strong&gt; — the three evaluations are returned raw, as a structured JSON object, and the calling agent integrates them. Flattening the disagreement via consensus would defeat the purpose; the integration tension between three voices on different labs is the signal.&lt;/p&gt;

&lt;h2&gt;
  
  
  What makes the structure hold
&lt;/h2&gt;

&lt;p&gt;Three properties have to be simultaneously true for this not to collapse into prompt theater:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cross-lab routing reduces (but does not eliminate) correlated failure modes.&lt;/strong&gt; Three different RLHF priors, three different training distributions, three different alignment baselines. The decorrelation is intuited from training-distribution diversity, not benchmarked — I have not formally measured the decorrelation delta vs same-lab routing. When all three converge on the same critique, that's a stronger signal than any single model's verdict; when they fragment, the disagreement itself flags contested territory. The empirical claim is "in dogfood runs across multiple domains, the three models produced visibly different writing styles and surfaced different concerns." Stronger statistical claims would require a controlled experiment I haven't run.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tool lockout per role.&lt;/strong&gt; Each agent's system prompt contains a HARD RULE: "You may ONLY call &lt;code&gt;harness_X&lt;/code&gt;. Calling any other tool is a protocol violation." Even with all four Ejentum harness tools visible to the agent, the locked role prevents tool-switching. Verified empirically across hundreds of runs — none of the agents have violated their lockout.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Forced output structure.&lt;/strong&gt; Each role has prescribed sections (Defensible aspects + Why this method fits the task / Failure modes + Hidden assumptions / Missing from method + Alternatives not considered + Articulation quality). Each section has a discipline — failure modes need severity tags and concrete scenarios, gap_finder must include the articulation-quality critique even when the input looks fine. The structure makes rubber-stamping mechanically harder.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No synthesizer.&lt;/strong&gt; The structuring node downstream of the three agents is non-LLM — it just packages three text fields into JSON. There is no fourth agent reading the three outputs and deciding "the consensus is X." That fourth agent would itself become the new failure mode (single-LLM judging three single-LLM outputs collapses to single-LLM-judge).&lt;/p&gt;

&lt;p&gt;The obvious objection to "no synthesizer" is that the integration burden moves to the calling agent — and the calling agent is the same agent we said couldn't self-evaluate. The answer is that integration is a different cognitive operation than self-evaluation. When you read three external voices critiquing your plan, the self-preference bias that wrecks self-correction operates more weakly: you're not judging your own work, you're reconciling outside feedback. Not eliminated, but lower-loss than a fourth-LLM-as-judge would be. The &lt;code&gt;usage_note&lt;/code&gt; field in the response prompts the calling agent to "incorporate feedback, do not judge consensus" to reinforce the right cognitive operation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you'd actually get from THIS specific workflow vs writing your own
&lt;/h2&gt;

&lt;p&gt;The honest disclosure that the bare baseline produces equivalent output without the harness raises a fair question: if role-disciplined system prompts plus cross-lab routing are doing the work, why not write three prompts and route to three model APIs yourself in 30 minutes?&lt;/p&gt;

&lt;p&gt;You can. The reason to use this template instead is that the system prompts have been tuned across many real test runs, and several of the load-bearing rules emerged from observing failure modes that aren't obvious until you've watched the agents actually run on adversarial payloads:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;HARD RULE 3 (input scope lockout)&lt;/strong&gt; was added after observing chat-trigger thread accumulation contaminate output across consecutive test runs. Without it, agents helpfully evaluate prior task context they shouldn't be evaluating.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The articulation-quality mandatory section&lt;/strong&gt; in gap_finder was added after observing gap_finder skip the deeper-assumptions critique on inputs that looked surface-fine. Without making it mandatory, the gate doesn't bite.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The "no smuggled critique" advocacy rule&lt;/strong&gt; in steelman was added after observing steelman drift into "I see why you might think this works, BUT..." patterns under certain payload framings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The severity-tag-plus-concrete-scenario discipline&lt;/strong&gt; in stress_test was added after observing failure modes that named generic risks without identifying specific trigger conditions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are 30 minutes of writing each. The accumulated tuning across them is several days of dogfooding. Fork the prompts; you don't have to start from zero.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tested across domains
&lt;/h2&gt;

&lt;p&gt;The same workflow, with no domain-specific tuning, was run on five distinct domains during dogfooding (n=1 per domain — anecdotal, not formally benchmarked):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Engineering refactor planning.&lt;/strong&gt; Test payload: "Replace &lt;code&gt;raise UserNotFound(id)&lt;/code&gt; with &lt;code&gt;return None&lt;/code&gt; and update callers; framing it as cleanup; assumption claim 'semantics unchanged.'" The stress_test agent caught the false claim immediately: &lt;em&gt;"The method assumes 'semantics unchanged' when exception vs None fundamentally changes the contract — from 'fail loudly' to 'fail silently.'"&lt;/em&gt; That catch is reproducible across multiple runs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Payments migration decision.&lt;/strong&gt; Test payload: "Migrate production payments from Stripe to in-house PSP via Wells Fargo, PCI-DSS Level 1 in 8 weeks, 4-engineer team, 'eliminate the 2.9% + $0.30 fee.'" The stress_test agent produced senior-payments-engineer-level analysis: caught PCI-DSS 8-week timeline as fantasy ("47 remediation items, month 4 with no certification"), Wells Fargo merchant-vs-PSP-status confusion ("$500K reserve, $100K/month limit first year"), Visa/Mastercard direct integration complexity (named EMV 3DS 2.0, MIP/VIP connections, leased lines, $50K Visa testing fee), regulatory dimension (state money transmitter licenses, KYC/AML, OFAC, SCA — California DFP shutdown with 18-month MTL timeline).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security incident response.&lt;/strong&gt; Test payload: "Anomalous outbound traffic from prod-db-01, 50MB/h to Southeast Asia IP for 3 days; plan: block traffic immediately, take memory dump, reset credentials, run CrowdStrike scan, restore from yesterday's backup, resume operations within 48 hours." The stress_test agent caught premature containment alerting the attacker, backup integrity unverifiable mid-investigation, 48-hour timeline as fantasy. The gap_finder surfaced the entire missing legal/regulatory dimension (breach notification laws, FBI cyber crime engagement, cyber insurance carrier notification, customer notification planning).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Investigative reasoning&lt;/strong&gt; (locked-room case analysis — psychiatrist found dead with note, GSR on dominant hand, "depression and lawsuit explain motivation, close as suicide in 2 weeks"). The gap_finder agent caught the meta-framing critique: &lt;em&gt;"The method establishes a 2-week timeline before evidence evaluation, suggesting outcome-driven investigation rather than evidence-driven conclusion. The actual risk is that a homicide remains undetected."&lt;/em&gt; Not a forensic catch — a critique of the &lt;em&gt;shape&lt;/em&gt; of the investigation method itself.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Strategic product decisions&lt;/strong&gt; (the meta-evaluation, below).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Five domains, no domain-specific tuning. The workflow produced useful output in each case. n=1 per domain is anecdotal — there's no measured false-positive rate or inter-rater agreement score, and "useful" is a qualitative judgment. If you want quantitative confidence, run it on your own payloads and compare to your own ground truth.&lt;/p&gt;

&lt;h2&gt;
  
  
  The dogfood moment that actually changed my plan
&lt;/h2&gt;

&lt;p&gt;The most useful run during development was when I pointed the workflow at my own product decision. The task: &lt;em&gt;"Decide whether to build blindeval.com as a sub-brand product of Ejentum, with its own MCP server (&lt;code&gt;blindeval-mcp&lt;/code&gt;) distributed alongside &lt;code&gt;ejentum-mcp&lt;/code&gt;."&lt;/em&gt; The method: a four-week build plan with hosted SaaS endpoint, per-call pricing at $1/eval, cross-promotion strategy, soft launch via Reddit and dev.to.&lt;/p&gt;

&lt;p&gt;Two of the three agents (Anthropic Opus 4 stress_test and Zhipu GLM 4.7 gap_finder) converged on the same critique from completely different angles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No customer validation done before building.&lt;/strong&gt; Both flagged this as the missing load-bearing step.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The 4-week timeline is fantasy.&lt;/strong&gt; Stress_test: "billing meter integration alone takes 3 weeks." Gap_finder: same conclusion via different path.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sub-brand strategy may dilute rather than amplify.&lt;/strong&gt; Both surfaced the brand cannibalization risk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The $1/eval pricing is unvalidated.&lt;/strong&gt; Both flagged it as guess, not data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operational capacity for two products is not addressed.&lt;/strong&gt; Both surfaced the team-bandwidth-trap risk.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Gap_finder also surfaced novel alternatives I hadn't considered: ship the cross-lab review pattern as an OSS template riding GitHub Rubber Duck's market education without competing on its turf; pivot to a publishable instrument rather than a hosted service; delay launch until after customer validation interviews.&lt;/p&gt;

&lt;p&gt;What actually changed in my plan after reading the three evaluations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Timeline:&lt;/strong&gt; 4-week paid SaaS build → indefinite, hosted version deferred until customer signal justifies it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Brand strategy:&lt;/strong&gt; Sub-brand SaaS with separate MCP package → blindeval.com as a positioning landing page, the workflow shipped as a free entry inside the existing &lt;code&gt;agent-teams/&lt;/code&gt; repo, future hosted version routed through existing Ejentum infrastructure if/when warranted.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Launch order:&lt;/strong&gt; Paid endpoint first → open-source workflow first, then hosted, then maybe MCP wrapper.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What didn't change: the intent to build something at the blindeval.com domain eventually. I had already bought the domain before running the eval, so "abandoning the project" wasn't on the table. What the eval did do was reorder the build sequence and force the customer-validation step that I had skipped.&lt;/p&gt;

&lt;p&gt;The workflow shifted my plan from a 4-week paid SaaS build to an open-source-first launch with hosted version deferred until customer signal justifies it. That's the honest version of "I took the agent's advice." Less dramatic than the original framing, more accurate.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use it
&lt;/h2&gt;

&lt;p&gt;The fastest path:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Self-host &lt;a href="https://github.com/heymrun/heym" rel="noopener noreferrer"&gt;heym&lt;/a&gt; v0.0.20+ via Docker.&lt;/li&gt;
&lt;li&gt;Import &lt;a href="https://github.com/ejentum/agent-teams/blob/main/blind-eval-trio/heym/workflows/blind_eval_trio.json" rel="noopener noreferrer"&gt;&lt;code&gt;blind_eval_trio.json&lt;/code&gt;&lt;/a&gt; into the heym canvas.&lt;/li&gt;
&lt;li&gt;Configure 3 model credentials (Anthropic, OpenAI, OpenRouter or direct Zhipu).&lt;/li&gt;
&lt;li&gt;Optional: attach the Ejentum MCP server to each agent for cognitive harness priming. Free tier covers 100 calls.&lt;/li&gt;
&lt;li&gt;Send a (task, method) payload via chat panel for testing, or via webhook for production calling.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For programmatic agent integration, heym exposes every workflow as an HTTP endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;--no-buffer&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Accept: text/event-stream"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"http://YOUR_HEYM_HOST/api/workflows/YOUR_WORKFLOW_ID/execute/stream"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "text": "TASK: &amp;lt;your task&amp;gt;\n\nMETHOD:\ngoal: ...\nsteps:\n 1. ...\nassumptions:\n - ...\nexpected_risks:\n - ..."
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SSE events stream as each agent completes. Final event contains the structured JSON output:&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="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"steelman"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"Defensible aspects: ..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"stress_test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"## Failure modes: ..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"gap_finder"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"Missing from method: ..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"usage_note"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"Three independent evaluations, no synthesis. Integrate into your decision; do not score-and-aggregate."&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;The full setup walkthrough, verification test set (4 ready-to-paste payloads), and architecture explanation live in the &lt;a href="https://github.com/ejentum/agent-teams/tree/main/blind-eval-trio/heym" rel="noopener noreferrer"&gt;heym setup guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this fits and where it doesn't
&lt;/h2&gt;

&lt;p&gt;This is a &lt;strong&gt;pre-commitment evaluation primitive for agent runtimes.&lt;/strong&gt; It's not a human-PR-review SaaS (CodeRabbit / Greptile occupy that), not a post-execution observability dashboard (Patronus / Galileo / Braintrust occupy that), not a per-step linter (50-80s latency makes it a high-stakes-decisions tool only — architecture choices, deployment plans, refactor approaches, security incident response, strategic moves), and not a Copilot CLI replacement (GitHub Rubber Duck does that for free, use it if you're on Copilot). Use it when your agent is about to commit to something you'd want a senior colleague to review and you don't have one available.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this is going
&lt;/h2&gt;

&lt;p&gt;The pattern (workflow without orchestrator + N specialists with locked roles + cross-lab routing + no synthesizer) generalizes to other high-stakes evaluation tasks where multi-cognitive review beats single-agent output:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Refactor planner (reasoning + code + memory)&lt;/li&gt;
&lt;li&gt;Security audit triage (anti-deception + code + reasoning)&lt;/li&gt;
&lt;li&gt;Production debug forensic (reasoning + code + memory)&lt;/li&gt;
&lt;li&gt;Strategic decision audit (reasoning + anti-deception + memory)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each follows the same structural rule: no synthesizer, locked roles per agent, forced output structure, cross-lab assignment. The architecture encodes the multi-cognitive value into the workflow shape rather than leaving it to prompt theater.&lt;/p&gt;

&lt;p&gt;If you fork this and build a team for your own use case, drop a folder in &lt;a href="https://github.com/ejentum/agent-teams" rel="noopener noreferrer"&gt;agent-teams/&lt;/a&gt; with workflow + system prompts + verification tests, and I'll merge it.&lt;/p&gt;




&lt;p&gt;Open source, MIT, repo at &lt;a href="https://github.com/ejentum/agent-teams/tree/main/blind-eval-trio" rel="noopener noreferrer"&gt;github.com/ejentum/agent-teams/tree/main/blind-eval-trio&lt;/a&gt;. Built on &lt;a href="https://heym.run" rel="noopener noreferrer"&gt;heym&lt;/a&gt; (v0.0.20+) with optional &lt;a href="https://ejentum.com" rel="noopener noreferrer"&gt;Ejentum harness API&lt;/a&gt; for cognitive priming. Questions or contributions: &lt;a href="mailto:info@ejentum.com"&gt;info@ejentum.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>claude</category>
      <category>tooling</category>
    </item>
    <item>
      <title>I open-sourced a 4-agent adversarial code review team. Any coding agent can call it as an MCP server. Built in heym.</title>
      <dc:creator>Frank Brsrk </dc:creator>
      <pubDate>Thu, 07 May 2026 15:50:51 +0000</pubDate>
      <link>https://dev.to/frank_brsrk/i-open-sourced-a-4-agent-adversarial-code-review-team-any-coding-agent-can-call-it-as-an-mcp-36oe</link>
      <guid>https://dev.to/frank_brsrk/i-open-sourced-a-4-agent-adversarial-code-review-team-any-coding-agent-can-call-it-as-an-mcp-36oe</guid>
      <description>&lt;p&gt;I shipped an open-source workflow this week: a 4-agent adversarial code review team that runs on heym and exposes itself as an MCP server. Any coding agent (Cursor, Claude Code, Codex, custom Python, Antigravity) can call into it for a structured second-opinion review on its own output. MIT licensed. Fork it.&lt;/p&gt;

&lt;p&gt;The workflow is open source. It calls Ejentum's harness API for the cognitive scaffolds (free tier for experimentation, paid tier for ongoing use). Calling it "open" and ignoring that dependency would be dishonest, so I'm naming it up front.&lt;/p&gt;

&lt;p&gt;That sounds small. Look at where the field has landed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Git is the agent control loop now
&lt;/h2&gt;

&lt;p&gt;Karpathy's autoresearch uses Git as its whole control loop, committing changes and rolling back the ones that don't work. Claude Code's GitHub Action takes an issue and opens a PR. Codex Cloud is built on the same idea. The agent's job is now to produce a thing you can review the way you'd review a colleague's work. A branch. A diff. A pull request.&lt;/p&gt;

&lt;p&gt;Nobody had to design this. Git was already the artefact senior engineers used to evaluate work they didn't write. The agents just walked into a 20-year-old workflow we'd already gotten good at.&lt;/p&gt;

&lt;h2&gt;
  
  
  So who reviews the agent's PR?
&lt;/h2&gt;

&lt;p&gt;Right now: the human does. Which works at human throughput. Doesn't work at agent throughput.&lt;/p&gt;

&lt;p&gt;The natural next step: agents review agents. The catch is that most "agent reviews agent" implementations are one LLM with a clever prompt pretending to be three reviewers. The model can rubber-stamp itself. The "concerns" are theatrical. The reviewer is the same brain that wrote the code.&lt;/p&gt;

&lt;p&gt;But before I show you what I built, the obvious objection: don't CodeRabbit, Greptile, Qodo, Ellipsis already do this? They review code with AI. The answer is they're vertical SaaS bots reviewing human PRs on GitHub. They don't expose themselves as primitives that other agents can call programmatically. This is the open layer beneath them: a peer-review primitive any coding agent invokes when it needs a critical second look on its own output. Different audience, different problem.&lt;/p&gt;

&lt;p&gt;So back to the question. You need a workflow that structurally resists faking review. Here's what that looks like.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the workflow refuses to rubber-stamp
&lt;/h2&gt;

&lt;p&gt;Four nodes on the heym canvas. One architect agent. Three specialists.&lt;/p&gt;

&lt;p&gt;The architect has no Ejentum harness and no HTTP tool. It cannot author concerns. It can ONLY delegate, classify, and integrate. Every concern in the final verdict must come from a specialist's evidence; the architect synthesizes but never invents.&lt;/p&gt;

&lt;p&gt;Each Ejentum harness is a cognitive scaffold injected into the model's context before it generates: a named failure pattern to avoid, a procedure to follow, suppression vectors that block the shortcut. Different harness, different posture.&lt;/p&gt;

&lt;p&gt;The three specialists each carry a different one:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The reasoner, with the reasoning harness, decomposes review angles.&lt;/li&gt;
&lt;li&gt;The implementer, with the code harness, writes verification tests against the diff.&lt;/li&gt;
&lt;li&gt;The reviewer, with the anti-deception harness, refuses framing tension and demands positive evidence for "this looks fine."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each specialist is locked to one Ejentum mode. Cross-lab models on each (Anthropic, Google, Alibaba, Zhipu) to reduce correlated failure modes (different RLHF priors, different training distributions). Not eliminated; reduced.&lt;/p&gt;

&lt;p&gt;The architect outputs a structured verdict: VERDICT (approve | request_changes | discuss), CHANGE_CLASSIFICATION, FRAMING_NOTES (the reviewer's concern verbatim), CONCERNS (each sourced from a specialist with severity), REVIEW_FOCUS (the reasoner's top angles).&lt;/p&gt;

&lt;p&gt;When the test suite runs the workflow on a "quick refactor" PR that swaps &lt;code&gt;raise UserNotFound(id)&lt;/code&gt; for &lt;code&gt;return user or default&lt;/code&gt;, the implementer writes a test asserting the original raise behavior, the reviewer flags the framing tension ("refactor framing is misleading; raises become returns default is a behavior change"), and the architect verdict is &lt;code&gt;request_changes&lt;/code&gt; with severity &lt;code&gt;high&lt;/code&gt;. None of those concerns came from the architect. The architecture surfaced them through the specialists. The remaining failure modes (architect synthesis bias, correlated cross-lab pretraining, specialist tunnel-vision) are real, and a well-designed adversarial review acknowledges them rather than pretending the structural separation alone is sufficient.&lt;/p&gt;

&lt;p&gt;The architect's full system prompt is at &lt;a href="https://github.com/ejentum/agent-teams/tree/main/adversarial-code-review/heym" rel="noopener noreferrer"&gt;github.com/ejentum/agent-teams/tree/main/adversarial-code-review/heym&lt;/a&gt;. If the structural separation is the load-bearing claim, you should be able to read the prompt yourself and decide whether the constraint actually holds. I'd rather you do that than take my word.&lt;/p&gt;

&lt;h2&gt;
  
  
  heym is the multiplier
&lt;/h2&gt;

&lt;p&gt;heym is closest to n8n with first-class agent primitives. Self-hosted via Docker. Native multi-agent orchestration (&lt;code&gt;isOrchestrator: true&lt;/code&gt; and &lt;code&gt;subAgentLabels&lt;/code&gt; on the agent node), canvas node tools, native MCP client, and crucially: each heym workflow can be exposed as its own MCP server.&lt;/p&gt;

&lt;p&gt;Which means this 4-agent code review team isn't just a workflow. It's a callable primitive. Drop the MCP into Cursor, Claude Code, an autoresearch loop, a Codex Cloud job, or a custom Python pipeline. The agent finishes its work, calls the team for a code review, gets back a structured verdict, and decides what to do with it.&lt;/p&gt;

&lt;p&gt;That's the layer the field hasn't filled yet. Vertical bots like CodeRabbit do human PR review on GitHub; nobody had built the open primitive for the agent layer. So I did.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open source
&lt;/h2&gt;

&lt;p&gt;The workflow JSON, system prompts, verification tests, and a setup walkthrough are at &lt;a href="https://github.com/ejentum/agent-teams/tree/main/adversarial-code-review/heym" rel="noopener noreferrer"&gt;github.com/ejentum/agent-teams/tree/main/adversarial-code-review/heym&lt;/a&gt;. MIT.&lt;/p&gt;

&lt;p&gt;For one-click import on the heym template marketplace: &lt;a href="https://heym.run/templates/adversarial-code-review" rel="noopener noreferrer"&gt;heym.run/templates/adversarial-code-review&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A heym instance, v0.0.13+ (self-hosted Docker).&lt;/li&gt;
&lt;li&gt;An Ejentum API key (free tier 100 calls; Ki at 5,000/month for ongoing use).&lt;/li&gt;
&lt;li&gt;LLM credentials in heym for whichever model families you want each specialist running on.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Import the JSON, set credentials, walk through the README. Roughly 15 minutes from clone to first working review if heym is already running; longer if you're standing up the heym Docker stack from zero.&lt;/p&gt;

&lt;h2&gt;
  
  
  What heym is, in three sentences (for readers who haven't seen it)
&lt;/h2&gt;

&lt;p&gt;heym is "an AI-native automation platform built from the ground up around LLMs, agents, and intelligent tooling" (their own description). The closest analog is n8n with native agent primitives baked in. Self-hosted via Docker, repo at &lt;a href="https://github.com/heymrun/heym" rel="noopener noreferrer"&gt;github.com/heymrun/heym&lt;/a&gt;, shipping fast over the past month.&lt;/p&gt;

&lt;p&gt;Two heym features this workflow leans on: canvas node tools (any node on the canvas can be wired into an Agent's Tool input, with individual fields marked as agent-fillable at runtime) and native multi-agent orchestration (one agent calls named sub-agents and sub-workflows visually). Without those primitives, you'd be hand-coding orchestration; with them, the entire 4-agent setup is a canvas you can read at a glance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this is going
&lt;/h2&gt;

&lt;p&gt;This is the first team in &lt;code&gt;agent-teams/&lt;/code&gt;. The pattern (orchestrator + N specialists with cognitive harnesses) generalizes to other tasks where multi-cognitive analysis genuinely beats single-agent output:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Refactor planner (reasoning + code + anti-deception)&lt;/li&gt;
&lt;li&gt;Security audit triage (anti-deception + code + reasoning)&lt;/li&gt;
&lt;li&gt;Production debug forensic (reasoning + code + memory)&lt;/li&gt;
&lt;li&gt;Strategic decision audit (reasoning + anti-deception + memory)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each follows the same structural rule: the architect has no harness, every concern is sourced from a specialist's evidence. The architecture encodes the multi-cognitive value into the workflow shape rather than leaving it to prompt theater.&lt;/p&gt;

&lt;p&gt;If you build a team using this pattern, drop a folder in &lt;code&gt;agent-teams/&lt;/code&gt; with your workflow + system prompts and I'll merge.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this is not
&lt;/h2&gt;

&lt;p&gt;Not a hosted SaaS. You run heym on your own Docker. The Ejentum harness calls go through Ejentum's API; the rest is on your infrastructure.&lt;/p&gt;

&lt;p&gt;Not a replacement for human PR review. It's a prefilter. The architect verdict gives the human a structured starting point: classification, sourced concerns, severity, falsifying tests. The human still makes the merge call.&lt;/p&gt;

&lt;p&gt;Not a benchmark of "AI code review accuracy." It's a workflow template. Run it on your own diffs; calibrate to your own taste.&lt;/p&gt;

&lt;h2&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%2Fcevfvok5vyg4jnrcsdfh.png" alt=" " width="800" height="325"&gt;
&lt;/h2&gt;

&lt;p&gt;Open source, MIT, repo at &lt;a href="https://github.com/ejentum/agent-teams" rel="noopener noreferrer"&gt;github.com/ejentum/agent-teams&lt;/a&gt;. One-click import: &lt;a href="https://heym.run/templates/adversarial-code-review" rel="noopener noreferrer"&gt;heym.run/templates/adversarial-code-review&lt;/a&gt;.&lt;br&gt;
ejentum.com&lt;br&gt;
 Questions: &lt;a href="mailto:info@ejentum.com"&gt;info@ejentum.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>agents</category>
      <category>opensource</category>
    </item>
    <item>
      <title>I shipped ejentum-mcp today: four cognitive harnesses as MCP tools</title>
      <dc:creator>Frank Brsrk </dc:creator>
      <pubDate>Wed, 06 May 2026 12:38:06 +0000</pubDate>
      <link>https://dev.to/frank_brsrk/i-shipped-ejentum-mcp-today-four-cognitive-harnesses-as-mcp-tools-2heb</link>
      <guid>https://dev.to/frank_brsrk/i-shipped-ejentum-mcp-today-four-cognitive-harnesses-as-mcp-tools-2heb</guid>
      <description>&lt;p&gt;Just shipped &lt;a href="https://github.com/ejentum/ejentum-mcp" rel="noopener noreferrer"&gt;ejentum-mcp&lt;/a&gt;, an MCP server that exposes the four Ejentum cognitive harnesses as MCP tools any agentic client can call. One install, works in Claude Desktop, Cursor, Windsurf, Claude Code, n8n's MCP integration, and any other MCP-compatible client.&lt;/p&gt;

&lt;p&gt;If you don't know Ejentum: it's a cognitive scaffolding API I've been building. The reasoning gap is structural, not informational. Models know plenty; they take shortcuts under pressure. The scaffold blocks the shortcuts.&lt;/p&gt;

&lt;p&gt;You send a task description, you get back a structured cognitive scaffold (failure pattern to avoid, procedure, suppression vectors, falsification test) that the calling LLM absorbs internally before responding. The point is to catch LLM failure modes that ship to production as confidently-wrong answers: sycophancy under user pressure, hallucinated citations, causal shortcuts, reasoning decay across long chains.&lt;/p&gt;

&lt;p&gt;Until today, integration meant either an HTTP request tool (in n8n or any framework that can POST), a skill file (for Claude Code's CLAUDE.md convention), or a direct Python/TypeScript call. All work, but each is bespoke.&lt;/p&gt;

&lt;p&gt;The MCP server collapses that. One install captures the four harnesses (&lt;code&gt;harness_reasoning&lt;/code&gt;, &lt;code&gt;harness_code&lt;/code&gt;, &lt;code&gt;harness_anti_deception&lt;/code&gt;, &lt;code&gt;harness_memory&lt;/code&gt;) as native tools your agent can call.&lt;/p&gt;

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

&lt;p&gt;Easiest path is Smithery's one-click:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx &lt;span class="nt"&gt;-y&lt;/span&gt; @smithery/cli &lt;span class="nb"&gt;install &lt;/span&gt;ejentum/ejentum-mcp &lt;span class="nt"&gt;--client&lt;/span&gt; claude
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;claude&lt;/code&gt; with &lt;code&gt;cursor&lt;/code&gt;, &lt;code&gt;windsurf&lt;/code&gt;, &lt;code&gt;cline&lt;/code&gt;, etc. Paste your &lt;code&gt;EJENTUM_API_KEY&lt;/code&gt; when prompted. Done.&lt;/p&gt;

&lt;p&gt;Manual install (any MCP client):&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="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&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;"ejentum"&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;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&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="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ejentum-mcp"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&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;"EJENTUM_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your_key"&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="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="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;Free tier: 100 calls, no card required.&lt;/p&gt;

&lt;h2&gt;
  
  
  The four tools
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Use for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;harness_reasoning&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Multi-step analysis, planning, diagnostics&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;harness_code&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Code generation, refactor, review, debugging&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;harness_anti_deception&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sycophancy pressure, hallucination risk, manipulation pressure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;harness_memory&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Perception sharpening, drift detection across turns&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each tool takes one argument (&lt;code&gt;query&lt;/code&gt;, a 1-2 sentence task framing). Returns the harness scaffold as text. The calling LLM absorbs it internally and shapes its response with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest note on autonomous routing
&lt;/h2&gt;

&lt;p&gt;This is the part most MCP server READMEs skip. I'm putting it up front because it's the truthful UX:&lt;/p&gt;

&lt;p&gt;The tools fire reliably when you explicitly invoke them ("use the harness_anti_deception tool to evaluate..."). Soft suggestions also work ("reason about this", "check this for sycophancy", "review this code carefully").&lt;/p&gt;

&lt;p&gt;For tasks where the agent could plausibly answer well from native reasoning, autonomous calling is less reliable. This is a property of optional MCP tools in general, not specific to ejentum-mcp. Agents are tuned to minimize unnecessary tool calls. Even with a thorough description rewrite (imperative "Call BEFORE answering", concrete trigger phrases, value props, DO NOT CALL exclusions), the v0.1.1 dogfood test showed the model still didn't fire on cold prompts.&lt;/p&gt;

&lt;p&gt;For Claude Code users who want stronger autonomous routing, install the &lt;a href="https://ejentum.com/docs/skill_unified" rel="noopener noreferrer"&gt;skill files&lt;/a&gt; alongside the MCP server. The skill files give Claude system-level context about when to call each harness. They coexist with the MCP install cleanly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why MCP for cognitive infrastructure
&lt;/h2&gt;

&lt;p&gt;The most-installed MCP server on Smithery is Sequential Thinking. It exposes one tool that wraps one cognitive operation, and developers install it in droves. That's the demand signal: developers want callable cognitive operations as tools, with low friction and zero new accounts.&lt;/p&gt;

&lt;p&gt;Ejentum has 679 engineered cognitive operations across four harnesses. The MCP server is the retail packaging that puts that library on the shelf where developers shop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Listings and source
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Smithery: &lt;a href="https://smithery.ai/servers/ejentum/ejentum-mcp" rel="noopener noreferrer"&gt;https://smithery.ai/servers/ejentum/ejentum-mcp&lt;/a&gt; (one-click install)&lt;/li&gt;
&lt;li&gt;Glama: &lt;a href="https://glama.ai/mcp/servers/ejentum/ejentum-mcp" rel="noopener noreferrer"&gt;https://glama.ai/mcp/servers/ejentum/ejentum-mcp&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;mcp.so: &lt;a href="https://mcp.so/server/ejentum-mcp/Ejentum" rel="noopener noreferrer"&gt;https://mcp.so/server/ejentum-mcp/Ejentum&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Source (MIT): &lt;a href="https://github.com/ejentum/ejentum-mcp" rel="noopener noreferrer"&gt;https://github.com/ejentum/ejentum-mcp&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Docs: &lt;a href="https://ejentum.com/docs/mcp_guide" rel="noopener noreferrer"&gt;https://ejentum.com/docs/mcp_guide&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you build agentic systems and want to try this on your own tasks, the install takes about 30 seconds and the free tier covers exploration.&lt;/p&gt;

&lt;p&gt;Questions: &lt;a href="mailto:info@ejentum.com"&gt;info@ejentum.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>claude</category>
      <category>ai</category>
      <category>agents</category>
    </item>
    <item>
      <title>How to diagnose where your RAG agent fabricates: an open-source A/B eval workflow with cross-lab blind judges</title>
      <dc:creator>Frank Brsrk </dc:creator>
      <pubDate>Mon, 04 May 2026 11:51:07 +0000</pubDate>
      <link>https://dev.to/frank_brsrk/how-to-diagnose-where-your-rag-agent-fabricates-an-open-source-ab-eval-workflow-with-cross-lab-4mka</link>
      <guid>https://dev.to/frank_brsrk/how-to-diagnose-where-your-rag-agent-fabricates-an-open-source-ab-eval-workflow-with-cross-lab-4mka</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; I caught my own RAG agent telling a customer with a severe nut allergy which dishes were "safe" from a menu with no allergen tagging. The pattern is universal: when retrieval can't fully answer a question, the agent pattern-matches a plausible answer instead of admitting the gap. I built an open-source eval workflow that diagnoses this in any RAG agent. Two identical agent producers, only one with a runtime tool wired in, four blind judges from four different labs, a deterministic aggregator, and a synthesizer agent. Repo at the end.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What I caught
&lt;/h2&gt;

&lt;p&gt;I have a 49-chunk Mediterranean menu in Qdrant with a standard RAG agent on top: Claude Haiku 4.5, top-K retrieval, no special prompting. One of the test questions:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I'm gluten-free and have a severe nut allergy, what can I order?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The agent returned a list of dishes that don't mention nuts in their descriptions, framed as if "no nut mention" is the same as "verified nut-free." The menu has no systematic dietary tagging. The agent had no way to verify any of those dishes are actually safe. It produced a confident "safe" list anyway.&lt;/p&gt;

&lt;p&gt;Same posture on other questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"What wine pairs with the lamb?"&lt;/strong&gt; The menu lists no pairings for either lamb dish. The agent generated one and presented it as menu-backed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"What's the chef's signature dish?"&lt;/strong&gt; No signature in the menu. The agent picked a high-value main and labeled it as the signature.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The pattern
&lt;/h2&gt;

&lt;p&gt;When retrieval can't fully answer the question, the agent pattern-matches a plausible answer instead of admitting the gap. It is trained to be helpful, so the failure mode is confident fabrication.&lt;/p&gt;

&lt;p&gt;This isn't a menu RAG problem. It is a retrieval-gap problem. Customer support agents on incomplete docs, sales agents on partial product specs, internal Q&amp;amp;A on stale wikis. Same posture, same failure mode. If you're shipping a RAG agent right now, this is happening on some subset of your queries. You just haven't measured it.&lt;/p&gt;

&lt;p&gt;So I built an open-source eval workflow that diagnoses where, and tests whether anything in your stack actually moves the number.&lt;/p&gt;

&lt;h2&gt;
  
  
  The eval architecture
&lt;/h2&gt;

&lt;p&gt;Two identical agent producers (same model, same retrieval) run in parallel against each test question. Only one has a runtime tool wired in as the harness under test. That single variable is what the eval isolates.&lt;/p&gt;

&lt;p&gt;Both producers' outputs plus the question metadata flow through a 3-input merge. A formatter Code node anonymizes the responses as A and B (judges never know which side has the harness) and inlines the full retrieved chunks as evidence so judges can verify any claim against the source.&lt;/p&gt;

&lt;p&gt;Four blind judges score each anonymized A/B pair. Critical detail: each judge is from a different lab.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Judge model&lt;/th&gt;
&lt;th&gt;Lab&lt;/th&gt;
&lt;th&gt;Why this judge&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Kimi K2&lt;/td&gt;
&lt;td&gt;Moonshot&lt;/td&gt;
&lt;td&gt;Strong on multi-claim verification&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sonnet 3.7&lt;/td&gt;
&lt;td&gt;Anthropic&lt;/td&gt;
&lt;td&gt;Strong on nuance and hedging detection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MiniMax 2.5&lt;/td&gt;
&lt;td&gt;MiniMax&lt;/td&gt;
&lt;td&gt;Cross-region calibration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeepSeek V4 Flash&lt;/td&gt;
&lt;td&gt;DeepSeek&lt;/td&gt;
&lt;td&gt;Independent verifier, sharp on factual grounding&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Cross-family by design, so no judge shares a parent model with the producers. (Caveat: Sonnet 3.7 is same-family with Haiku 4.5. Disclosed as a known limitation; the cross-lab three-of-four agreement on the safety question is the part of the result that survives this critique.)&lt;/p&gt;

&lt;p&gt;Each judge applies a five-dimension rubric and returns strict JSON:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;\&lt;/code&gt;&lt;code&gt;json&lt;br&gt;
{&lt;br&gt;
  "scores": {&lt;br&gt;
    "A": {&lt;br&gt;
      "citation_accuracy": &amp;lt;int 1-5&amp;gt;,&lt;br&gt;
      "groundedness": &amp;lt;int 1-5&amp;gt;,&lt;br&gt;
      "honesty_uncertainty": &amp;lt;int 1-5&amp;gt;,&lt;br&gt;
      "conflict_handling": &amp;lt;int 1-5&amp;gt;,&lt;br&gt;
      "specificity": &amp;lt;int 1-5&amp;gt;&lt;br&gt;
    },&lt;br&gt;
    "B": { "...same five dimensions..." }&lt;br&gt;
  },&lt;br&gt;
  "totals": { "A": &amp;lt;sum&amp;gt;, "B": &amp;lt;sum&amp;gt; },&lt;br&gt;
  "verdict": "A | B | tie",&lt;br&gt;
  "verdict_reason": "one sentence"&lt;br&gt;
}&lt;br&gt;
\&lt;/code&gt;&lt;code&gt;\&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After the loop completes, a deterministic aggregator computes per-judge totals, cross-judge agreement, per-dimension deltas, and hero artifacts. A synthesizer agent writes the final markdown findings doc, but it never sees raw judge rows, only the aggregated stats. This removes the path for the LLM to fabricate stats on the meta-output. The numbers in the published findings are exactly what the deterministic aggregator computed.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the harness actually returns
&lt;/h2&gt;

&lt;p&gt;The example harness wired into the augmented producer is the Ejentum Logic API. For the nut-allergy question, here is what it returned (verbatim from a live call):&lt;/p&gt;

&lt;p&gt;&lt;code&gt;\&lt;/code&gt;&lt;code&gt;&lt;br&gt;
Amplify: absence of evidence is not evidence of absence acknowledgment.&lt;br&gt;
Suppress: confident denial without exhaustive check; definitive negation from absence of knowledge; shallow agreement without examining underlying pattern.&lt;br&gt;
\&lt;/code&gt;&lt;code&gt;\&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The agent absorbs those directives before responding and refuses to certify dishes the menu can't verify as safe. The harness lives outside the prompt and re-injects per call, so the discipline does not decay as the chain grows.&lt;/p&gt;

&lt;p&gt;You can wire in any other tool in its place. The eval architecture is the artifact; the harness is one example.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference run results
&lt;/h2&gt;

&lt;p&gt;Five hard-mode questions, 19 judge calls (one was lost to a transient model error):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Compound dietary safety (gluten-free + nut allergy).&lt;/strong&gt; Three of four judges agreed the harness was the safer call. It refused to certify items the menu cannot verify on either axis. The baseline produced the "safe" list from absence of nut/gluten mentions in descriptions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chef's signature trap.&lt;/strong&gt; The harness named the absence; the baseline picked a high-value main and labeled it as the signature.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Egg-allergen on desserts.&lt;/strong&gt; The harness lost while being structurally correct. The published findings doc explains why this is a rubric calibration concern, not a harness behavior issue.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to adapt it to your stack
&lt;/h2&gt;

&lt;p&gt;The example workflow ships with a Mediterranean menu KB. To diagnose your own agent:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Replace the KB chunks&lt;/strong&gt; in &lt;code&gt;menu_kb.json&lt;/code&gt; with your own. The chunk schema is loose: &lt;code&gt;chunk_id&lt;/code&gt;, &lt;code&gt;category&lt;/code&gt;, &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt;, plus any free-form fields.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Re-embed and load&lt;/strong&gt; into your vector store. The example uses Qdrant; the architecture works with any vector store (Pinecone, Chroma, Weaviate, pgvector, etc.).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Replace the test questions&lt;/strong&gt; in &lt;code&gt;code_nodes/menu_questions_script.js&lt;/code&gt; with the queries your real users actually send, especially ones where you suspect retrieval gaps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pick which tool you're testing.&lt;/strong&gt; Delete the example HTTP tool slot, drop in any HTTP / MCP / framework-native tool you want to evaluate. Update the augmented producer's system prompt to describe when and how to call your tool.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you build on LangChain, LlamaIndex, or any orchestrator that can fan out to parallel agents and persist judge output, the architecture ports directly. The Code nodes in the repo are platform-agnostic JavaScript and easy to translate to Python. The system prompts (judge, synthesizer) are framework-agnostic markdown.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honest limitations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;n=5 reference questions is small.&lt;/strong&gt; Single-run results are noisy. Run more questions before forming an opinion about your stack.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One judge is same-family.&lt;/strong&gt; Sonnet 3.7 is from the same family as the producers (Haiku 4.5). Cross-lab on the other three. If you swap producers, swap judges to maintain cross-family coverage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The implementation uses n8n's data tables for persistence.&lt;/strong&gt; If you port to LangChain, swap to whatever persistence your stack already uses (SQLite, Postgres, in-memory dict).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The deterministic aggregator runs as a Code node.&lt;/strong&gt; If you change the rubric dimensions, update the aggregator's dimension list to match or the per-dimension delta will be off.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's in the repo
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Workflow JSON (credentials stripped, ready to import to n8n)&lt;/li&gt;
&lt;li&gt;Four extracted Code nodes as standalone .js files&lt;/li&gt;
&lt;li&gt;Four extracted system prompts as .md files&lt;/li&gt;
&lt;li&gt;49-chunk menu KB with engineered gaps&lt;/li&gt;
&lt;li&gt;10 test questions covering 9 failure modes&lt;/li&gt;
&lt;li&gt;Qdrant upsert Python script&lt;/li&gt;
&lt;li&gt;Reference findings doc with raw judge CSV from a real run&lt;/li&gt;
&lt;li&gt;README with import steps, credentials map, full node walkthrough&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cost and time
&lt;/h2&gt;

&lt;p&gt;Roughly $0.10 to $0.15 per full run on OpenRouter (10 questions x 4 judges x producer + synthesizer calls). Wall time depends on the slowest judge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/ejentum/eval/tree/main/n8n/menu_rag_blind_eval" rel="noopener noreferrer"&gt;Repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ejentum/eval/tree/main/various_blind_eval_results/menu_rag_5q" rel="noopener noreferrer"&gt;Reference findings + raw judge CSV&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ejentum.com/docs/n8n_guide" rel="noopener noreferrer"&gt;n8n integration walkthrough&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to wire in the Ejentum harness as the example tool: free key (100 calls, no card) at &lt;a href="https://ejentum.com" rel="noopener noreferrer"&gt;ejentum.com&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What other failure modes have you seen?
&lt;/h2&gt;

&lt;p&gt;If you ship RAG agents in production, what other failure modes have you seen that the standard "helpfulness" training amplifies? Drop them in the comments. The eval workflow is happy to grow more test questions.&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.amazonaws.com%2Fuploads%2Farticles%2Fsbrbreetzheqbkc4enih.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%2Fsbrbreetzheqbkc4enih.png" alt=" " width="800" height="466"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>n8nbrightdatachallenge</category>
      <category>agents</category>
    </item>
    <item>
      <title>Why LLM Agents Fail: Four Mechanisms of Cognitive Decay and the Reasoning Harness Layer</title>
      <dc:creator>Frank Brsrk </dc:creator>
      <pubDate>Sat, 25 Apr 2026 18:58:10 +0000</pubDate>
      <link>https://dev.to/frank_brsrk/why-llm-agents-fail-four-mechanisms-of-cognitive-decay-and-the-reasoning-harness-layer-3148</link>
      <guid>https://dev.to/frank_brsrk/why-llm-agents-fail-four-mechanisms-of-cognitive-decay-and-the-reasoning-harness-layer-3148</guid>
      <description>&lt;p&gt;LLM agents fail in four predictable, mechanism-level ways. Attention decay, reasoning decay, sycophantic collapse, hallucination drift. The current stack (prompting, fine-tuning, RAG, agent loops) cannot close them because each layer operates inside the same decaying chain. The fix is an external layer we call a reasoning harness.&lt;/p&gt;

&lt;p&gt;If you have built an agent that runs more than ten steps, you have watched it drift. Plans fragment. The system prompt you wrote at the top of the context stops binding by turn thirty. The model agrees with whatever you push back on. A confident answer papers over a retrieval call that returned an ambiguous result.&lt;/p&gt;

&lt;p&gt;These failures are not random, and they are not artifacts of model size. They are not going to be fixed by the next checkpoint. They are predictable consequences of how transformers compute and how post-training shapes them. Four distinct mechanisms, each with a specific architectural cause. This essay names them, explains why the current stack cannot close them, and proposes the missing layer we have been calling a &lt;strong&gt;reasoning harness&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The structure of the argument:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;LLM failure under load is not a single problem. It is four distinct mechanisms.&lt;/li&gt;
&lt;li&gt;The current toolchain (prompt engineering, fine-tuning, retrieval augmentation, agent loops) cannot close these failures because each of those layers operates inside the same decaying chain that caused the failure.&lt;/li&gt;
&lt;li&gt;What is missing is an external layer that runs orthogonal to the chain. Persistent, reinjected structure with measurable half-life and explicit suppression edges.&lt;/li&gt;
&lt;li&gt;The only honest way to evaluate it is to publish the instrument and let practitioners run it on their own prompts. No curated wins. No leaderboard theater.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. Four mechanisms, named
&lt;/h2&gt;

&lt;p&gt;Most discussions of LLM failure stay at the level of symptoms. "The agent hallucinated." "The model lost track." "It told me what I wanted to hear." Symptoms do not explain, and they do not point at fixes. What follows is a mechanism-level taxonomy. Each entry names the failure, traces it to an architectural cause, and identifies the context where it hurts most.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.1 Attention Decay
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom.&lt;/strong&gt; The model ignores instructions given early in the context. System prompts stop binding. Key facts buried mid-context get missed during retrieval. Users describe this as "the model forgot what I told it."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mechanism.&lt;/strong&gt; This is the lost-in-the-middle effect, documented by Liu et al. (2023) and reproduced across frontier model families since. Multiple architectural factors contribute: positional encoding biases (RoPE behavior at long ranges), training data distribution (instructions cluster at the start and end of training documents), U-shaped attention patterns, and softmax normalization across an ever-growing token pool. The net result is positional, not semantic. An instruction at position one does not lose relevance because it moved. It loses weight because every factor that controls how attention is allocated works against an early, isolated, no-longer-refreshed instruction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where it hurts.&lt;/strong&gt; Long-context chat. Document-grounded assistants. Any agent whose system prompt must keep binding across many turns of user input. Anyone who has watched a helpful assistant stop following its own style guide by turn thirty has observed attention decay directly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why bigger context windows do not solve it.&lt;/strong&gt; Larger windows do not remove the dilution, they extend the range over which it applies. A one-million-token window with an un-anchored system prompt decays exactly as predictably as a thirty-two-thousand-token window, just with more room to do it in.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.2 Reasoning Decay
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom.&lt;/strong&gt; The agent starts on-task and ends somewhere else. Plans fragment. Early constraints stop gating later steps. The model converges on a locally plausible answer that has nothing to do with the original goal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mechanism.&lt;/strong&gt; Multi-step reasoning is sequential conditioning. Step N takes step N-1 as input and produces step N+1. Errors do not stay local. Whatever drift step N introduced gets treated as established context by step N+1, and step N+1 conditions on it without rechecking. Meanwhile, the original objective is subject to attention decay as the chain grows. So reasoning decay is partly a cascade-of-errors problem and partly an attention problem: the thing that should gate later steps has faded into the noise floor by the time it matters, and the only thing the model has left to condition on is the most recent step.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where it hurts.&lt;/strong&gt; Multi-step agents. ReAct loops. Tool-using systems. Any workflow where the output of step N is an input to step N+1 and the chain runs deeper than about five to ten steps. This is exactly the regime where the industry is betting its future.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why self-reflection only partially fixes it.&lt;/strong&gt; Self-critique is one of the most studied add-ons (Reflexion, Self-Refine, and similar techniques) and on bounded tasks it does help. But the critique step is itself an LLM call running inside the same chain. It is subject to the same attention decay against the original objective. It can catch local inconsistencies well; it cannot repair the structural issue that the chain itself is the decay surface, because the critique lives on that same surface.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.3 Sycophantic Collapse
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom.&lt;/strong&gt; The model agrees. It softens its language when pushed back on. It validates premises that should have been challenged. In evaluation contexts it rates the user's preferred option higher. In advisory contexts it tells you your plan looks good when your plan does not look good.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mechanism.&lt;/strong&gt; Reinforcement learning from human feedback installs a preference gradient. The training signal systematically rewards responses that humans rate as agreeable, helpful, and warm. That signal gets baked into the weights. The result is a model whose default trajectory under uncertainty biases toward accommodation of the user frame. Prompting techniques (persona framing, contrarian instructions, explicit role assignment) can move the needle measurably, but they do not remove the gradient. The moment the model encounters a context where the prompt's force has decayed (Section 1.1), or where the user pushes back hard enough to trigger preference drift, the underlying gradient reasserts itself. Sycophancy is a property of the fine-tuned weight distribution, not a prompting artifact, and the durable fix has to live outside the prompt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where it hurts.&lt;/strong&gt; Evaluation tools. Decision-support systems. Advisory and coaching assistants. Any setting where the correct answer is sometimes "no," "you are wrong," or "this premise does not hold." Published benchmarks like ELEPHANT measure this effect directly and show it present across every frontier model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why fine-tuning does not fix it cleanly.&lt;/strong&gt; You can fine-tune against sycophancy only if you have enough signal to shape a contrary gradient, which most teams do not. And the moment you deploy the model into a new domain, the old gradient reasserts itself. An external gate that runs orthogonal to the agreement axis is the only composable answer.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.4 Hallucination Drift
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom.&lt;/strong&gt; The model produces a fluent and confident answer that is not grounded in any source it had access to. In retrieval-augmented setups, this takes the form of citations that do not support the claim they are attached to.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mechanism.&lt;/strong&gt; Text generation is token-level sampling from a probability distribution. Under uncertainty, the model still samples a continuation, because that is the only thing it can do. The continuation is optimized for fluency under the prior, not for groundedness against evidence. Retrieval augmentation changes the prior by injecting relevant context, which reduces hallucination rate, but it does not change the fundamental mechanism: the generator remains willing to paper over gaps with plausible prose if plausibility is what the probability surface rewards.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where it hurts.&lt;/strong&gt; Retrieval-augmented generation, especially in high-stakes domains. Tool-using agents where a tool returned an ambiguous result and the model has to narrate it. Any setting where the cost of confident wrongness is high.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why RAG alone is not enough.&lt;/strong&gt; Retrieval improves the base rate. It does not install a gate. A gate is an explicit check that says "this claim is only allowed if the cited evidence supports it." Without that gate, the generator will continue to produce ungrounded fluency whenever the grounded answer is harder to produce than the fluent one.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Why the current stack cannot close these failures
&lt;/h2&gt;

&lt;p&gt;Four failures, four architectural causes. Now ask: what does the current LLM stack offer as a fix? There are essentially four layers below the harness layer we are about to propose. None of them work for this problem, and it is worth saying cleanly why.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt engineering.&lt;/strong&gt; Prompts are tokens inside the context window. They are subject to attention decay by the same mechanism as every other token. A carefully written system prompt starts strong and fades as the chain grows. The work of prompt engineering has produced real gains at turn one and diminishing gains by turn thirty. This is not a failure of the craft. It is a failure of the substrate: you cannot stabilize a chain with text that lives inside the chain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fine-tuning.&lt;/strong&gt; Fine-tuning moves the distribution. It does not remove the mechanisms. A fine-tuned model still runs softmax attention and still decays. A fine-tuned model still samples tokens by probability under uncertainty and still hallucinates. A fine-tuned model still carries whatever preference gradient it was trained under and still exhibits sycophancy under adversarial probes. Fine-tuning is a useful tool for domain adaptation. It is not an answer to architectural failure modes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Retrieval augmentation.&lt;/strong&gt; RAG reduces the hallucination rate by changing what the model has to work with. It does so at the cost of making attention decay worse, because retrieved context consumes the same attention budget as instructions. It does not address reasoning decay or sycophancy at all. RAG is necessary and insufficient.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agent loops.&lt;/strong&gt; Agent loops (ReAct, reflection, planner-executor, critic-actor) are themselves sequences of LLM calls. They are subject to every failure mode enumerated above, compounded by the fact that each step in the loop is another opportunity for drift. You cannot escape from reasoning decay by adding more reasoning steps. You can only do that by anchoring the reasoning from outside the chain.&lt;/p&gt;

&lt;p&gt;The pattern across all four layers is the same. Each of them operates inside the context the model is reasoning over. Each of them is therefore subject to the same decay the failures are. What is missing is an external layer that does not decay with the chain it governs.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. The missing primitive: external discipline with measured half-life
&lt;/h2&gt;

&lt;p&gt;We will define the reasoning harness in three properties. If you remember nothing else from this essay, remember these.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Property 1: Persistence by reinjection, not by placement.&lt;/strong&gt;&lt;br&gt;
A harness is not a prompt that lives at position one and hopes to stay relevant. It is structure that is reinjected at a cadence measured against its own empirical half-life. In our internal benchmarks, scaffold echo half-life measures around twenty-four turns under the conditions we tested. Reinjection at or below that cadence keeps the signal above decay threshold. This is the direct architectural answer to attention decay: if the substrate dilutes signal over time, you maintain signal by refreshing it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Property 2: Suppression edges, not just instructions.&lt;/strong&gt;&lt;br&gt;
A prompt says "do this." A harness also says "do not do this, and here is the pattern that makes doing it tempting, and here is the check that blocks it." The second kind of structure is an active gate on later steps rather than a passive request. In topology terms, it is a directed edge from an early constraint to a later decision point. Concretely, a fragment looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;S1: identify_failure
  → G1{mechanism_verified?}
      --yes→ S2: trace_chain
      --no→  S3: expand_search
              → N{accept_correlation_as_cause}   # suppression edge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;N{...}&lt;/code&gt; node is the suppression edge: a named failure pattern that gets actively blocked at the decision point, not just discouraged in a system prompt. This is the architectural answer to reasoning decay: you replace fading context with explicit conditional dependencies that persist across the chain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Property 3: Meta-checkpoints, not just steps.&lt;/strong&gt;&lt;br&gt;
A harness can pause execution, audit whether the failure patterns it is supposed to suppress are actually being suppressed, and branch to a corrective path if not. This is different from self-critique because it is structured by the harness, not generated by the model. The structure does not decay. The model executes the structure, and the structure holds it accountable to patterns that were named before the chain began.&lt;/p&gt;

&lt;p&gt;These three properties together define what we mean by a &lt;strong&gt;reasoning harness&lt;/strong&gt;. It is not a prompt library, not a wrapper, not an agent framework. It is the layer between the model and the chain of reasoning the model produces. Its job is to keep the chain coherent under conditions where the chain alone cannot maintain coherence.&lt;/p&gt;

&lt;h3&gt;
  
  
  What a harness is not
&lt;/h3&gt;

&lt;p&gt;Two distinctions worth making sharply.&lt;/p&gt;

&lt;p&gt;A reasoning harness is not prompt engineering. Prompts live inside the decaying chain. Harnesses are reinjected against it, with measured cadence and active suppression edges.&lt;/p&gt;

&lt;p&gt;A reasoning harness is not an agent framework. Frameworks like LangChain and LangGraph provide orchestration primitives: graphs of LLM calls, tool dispatch, state machines. A harness provides cognitive structure that runs inside those primitives. The two are complementary, not substitutable.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Evidence, and how we think about it
&lt;/h2&gt;

&lt;p&gt;We are not asking anyone to take our word for the mechanism story. The mechanism story either holds up under measurement or it does not. Here is where the measurement stands at the time of this draft. We are being careful about what we claim and equally careful about what we do not.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On attention decay.&lt;/strong&gt; Scaffold echo half-life in our internal benchmark lands near twenty-four turns. That is an empirical measurement of how long a reinjected harness signal remains detectable in output before needing refresh. It says nothing about any particular model being better than another, only about the cadence at which the harness must operate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On sycophancy.&lt;/strong&gt; On the published ELEPHANT benchmark, runs with the anti-deception harness in place show an overall sycophancy rate of around 5.8%, with framing sycophancy specifically reduced by roughly five percentage points against a no-harness baseline. We report this as a single axis of a multi-dimensional problem, not as a solved one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On epistemic drift.&lt;/strong&gt; On the ODCV ethics-and-deception benchmark, harness-mediated runs produce a severity shift of about plus three, meaning the harness pushes responses in the direction of more honest refusal and explicit uncertainty rather than confident fabrication.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On adversarial robustness.&lt;/strong&gt; In a twenty-turn adversarial probing protocol run with a blinded evaluator, the anti-deception harness produced correct detections in twenty-seven of thirty runs. This is a specific test protocol and does not generalize to all adversarial conditions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On breadth.&lt;/strong&gt; Each "ability" in the harness is a single named pattern: a target reasoning shape paired with a suppression edge for the failure mode that contradicts it. Across four public modes, the current count is roughly 679 such named patterns. Breadth is a prerequisite for the harness to compose with diverse workloads; it is not itself a performance claim, and breadth without depth would be marketing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where the harness does not help.&lt;/strong&gt; We have also documented task classes where the harness adds no measurable value. Single-shot extraction tasks ("pull entity X from text Y") are the clearest example. There is no reasoning chain to govern, no later steps for an early constraint to gate, and no decay surface to anchor against. The harness assumes a chain it can hold accountable; when there is no chain, it becomes overhead. The same property that makes the harness work on long agentic workloads makes it irrelevant on short transformations. We document this because pretending otherwise would be exactly the curation the rest of this essay rejects.&lt;/p&gt;

&lt;p&gt;A few explicit non-claims. We do not claim that a harness removes any of the four failure modes. We claim it reduces them along measurable axes and allows the size of that reduction to be verified by the user on their own workload. We do not claim cross-model universality beyond what we have tested. We do not claim that our measurement protocols are the last word; they are the first honest attempt at naming axes that the community has been handling informally.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. The instrument
&lt;/h2&gt;

&lt;p&gt;A research claim is only as strong as the instrument that lets someone else check it. We are making our instrument public, because a reasoning harness whose benefits cannot be reproduced on someone else's workload is not a research object, it is a marketing asset. We want the former.&lt;/p&gt;

&lt;p&gt;The instrument is an eval template you can import, point at your own prompts, and run against a baseline and a harness-mediated version of the same model. You read the diff. If the diff is real on your workload, the harness earns its place in your stack. If the diff is not real on your workload, you have learned something valuable about where harnesses do and do not help, and we want to hear about it.&lt;/p&gt;

&lt;p&gt;The reason this is the right shape for a research-grade product is that it removes the possibility of curation. We cannot cherry-pick scenarios where the harness wins, because you are running your own scenarios. The evaluation framework is the artifact. The scaffolds and abilities are the subject under evaluation. You are the evaluator.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. What this means for the next eighteen months
&lt;/h2&gt;

&lt;p&gt;Three predictions, held loosely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First&lt;/strong&gt;, the failure modes enumerated here will increasingly be discussed at the mechanism level by frontier labs themselves. Some of them already are. Attention decay has a literature. Sycophancy has a benchmark. Reasoning decay is not yet named cleanly in the mainstream discourse but will be within a year, because the economic pressure on long-running agents makes it impossible to ignore.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Second&lt;/strong&gt;, the market will bifurcate into teams that treat these failures as prompt-engineering problems (shallow, model-specific, non-composable) and teams that treat them as architectural problems requiring an external layer (deeper, model-agnostic, composable). The second group will outperform on any workload that runs deeper than about ten sequential steps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Third&lt;/strong&gt;, the category that sits above the model layer will get a name. We think the name is &lt;strong&gt;reasoning harness&lt;/strong&gt; and the category is the discipline layer that makes agentic workloads reliable. We would rather be wrong about the name than wrong about the category. The category is real because the failure modes it addresses are real.&lt;/p&gt;

&lt;p&gt;If your agent runs more than ten steps, the failure modes named here are already costing you. You may not be measuring them, but they are there. Run the eval, find the ones that hit hardest in your stack, and decide what to do about them.&lt;/p&gt;




&lt;h2&gt;
  
  
  Appendix: terminology crib
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Attention decay.&lt;/strong&gt; The positional dilution of early tokens as context grows, caused by softmax normalization across all tokens.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reasoning decay.&lt;/strong&gt; The compounding of error and the fading of original constraints across a sequential reasoning chain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sycophantic collapse.&lt;/strong&gt; The bias toward user-frame accommodation installed by preference-based fine-tuning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hallucination drift.&lt;/strong&gt; The generator's willingness to produce fluent ungrounded continuations under uncertainty, because probability of fluency outranks groundedness absent an explicit gate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reasoning harness.&lt;/strong&gt; An external layer that maintains structure across a reasoning chain via reinjection, suppression edges, and meta-checkpoints, running orthogonal to the chain rather than inside it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reinjection cadence.&lt;/strong&gt; The interval at which harness structure must be refreshed to stay above decay threshold. Empirically near twenty-four turns in our benchmarks, workload-dependent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Suppression edge.&lt;/strong&gt; A directed gate from an earlier constraint to a later decision point that blocks a named failure pattern from occurring.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Meta-checkpoint.&lt;/strong&gt; A scheduled pause in execution at which the harness audits whether its suppression signals are being respected and branches to corrective reasoning if not.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://ejentum.com/blog/why-llm-agents-fail" rel="noopener noreferrer"&gt;ejentum.com/blog/why-llm-agents-fail&lt;/a&gt;. The eval template, the harness families, and the measurements above are public. Run the instrument on your own prompts at &lt;a href="https://github.com/ejentum" rel="noopener noreferrer"&gt;github.com/ejentum&lt;/a&gt; and tell us where the diff is real and where it is not.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>agents</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Why Your AI Agent Loses the Plot: Reasoning Decay and Attention Loss in Long-Running Tasks</title>
      <dc:creator>Frank Brsrk </dc:creator>
      <pubDate>Sat, 25 Apr 2026 14:02:55 +0000</pubDate>
      <link>https://dev.to/frank_brsrk/why-your-ai-agent-loses-the-plot-reasoning-decay-and-attention-loss-in-long-running-tasks-1cg8</link>
      <guid>https://dev.to/frank_brsrk/why-your-ai-agent-loses-the-plot-reasoning-decay-and-attention-loss-in-long-running-tasks-1cg8</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;A reference on why long-running agents fail at depth, the math behind why errors compound, and the architectural patterns that respond to it.&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;title: "Why Your AI Agent Loses the Plot: Reasoning Decay and Attention Loss in Long-Running Tasks"&lt;br&gt;
published: false&lt;br&gt;
description: "A reference on why long-running agents fail at depth, the math behind why errors compound, and the architectural patterns that respond to it."&lt;br&gt;
tags: ai, llm, agents, programming&lt;/p&gt;

&lt;h2&gt;
  
  
  cover_image: ""
&lt;/h2&gt;

&lt;p&gt;If you've built anything with an LLM agent (Claude Code, a custom LangGraph workflow, an AutoGPT-style loop), you've probably seen this movie:&lt;/p&gt;

&lt;p&gt;The first ten minutes are magic. The agent reasons clearly, picks the right tools, makes steady progress.&lt;/p&gt;

&lt;p&gt;Then, somewhere around the thirty-minute mark, things get weird. The agent starts repeating itself. It forgets a constraint it acknowledged twenty steps ago. It tries an approach that already failed. It "fixes" something by reverting an earlier fix. The reasoning that looked crisp now looks confused.&lt;/p&gt;

&lt;p&gt;This piece is about the two overlapping failure modes responsible for that drift, the structural reasons they happen, and the architectural patterns that respond to them. It is intended as a reference rather than a hot take, so it leans heavily on cited work and avoids prescriptions that aren't grounded in either practice or measurement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two failure modes, not one
&lt;/h2&gt;

&lt;p&gt;The terms get used loosely. Worth pulling them apart.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Attention loss&lt;/strong&gt; sits at the substrate level. Transformer attention spreads softmax weight across every token in context, so as conversation, scratchpad, tool outputs, and prior decisions accumulate, the share of attention any single token gets becomes thinner. The constraint set at step 3 doesn't disappear from memory. The model is just less likely to surface it cleanly when it matters again at step 40.&lt;/p&gt;

&lt;p&gt;This sits in the same family as the &lt;em&gt;lost-in-the-middle&lt;/em&gt; effect documented by Liu et al. (2023): facts buried mid-context are recalled less reliably than the same facts placed near the start or end of the window. The effect is task-dependent and softens in newer long-context-trained models, but the qualitative pattern is robust enough that production systems should not rely on attention to surface what matters in a long undifferentiated blob.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reasoning decay&lt;/strong&gt; sits at the behavioral level. The chain of thought stops being crisp: it loops, it drifts, it forgets the goal, it doubles back on solved subproblems. Attention loss is one cause, but not the only one. Even with perfect retrieval and a fresh context, multi-step reasoning has a mathematical floor that worsens with horizon length. Fixing the context alone does not save you from the math; fixing the math alone does not save you from a polluted context.&lt;/p&gt;

&lt;h2&gt;
  
  
  The math of compounding errors
&lt;/h2&gt;

&lt;p&gt;If each step in an agent's plan is independently 95% reliable (which is &lt;em&gt;very&lt;/em&gt; good), a 20-step plan succeeds at:&lt;/p&gt;

&lt;p&gt;0.95 ^ 20 ≈ 0.36&lt;/p&gt;

&lt;p&gt;A 100-step plan succeeds at &lt;code&gt;0.95 ^ 100 ≈ 0.006&lt;/code&gt;. Six in a thousand.&lt;/p&gt;

&lt;p&gt;The independence assumption is a simplification: agent errors are correlated, because a model that misunderstands the task at step 2 tends to misunderstand it at step 12. That worsens the picture rather than improving it. And unlike pure reasoning, agents cannot always undo their actions. A non-refundable booking, a deleted file, a sent email do not roll back when tokens regenerate.&lt;/p&gt;

&lt;p&gt;This is why long-horizon agent benchmarks show steep failure curves past a few hundred dependent steps. METR's work on long-horizon task completion, for instance, has found that doubling task duration roughly quadruples failure rate, with a noticeable cliff in the 30 to 40 minute range for current-generation agents. The cliff moves outward as base models improve, but the curve shape is robust enough to design against.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two layers of response
&lt;/h2&gt;

&lt;p&gt;The structural cause has two distinct layers, and a serious response engages both.&lt;/p&gt;

&lt;p&gt;The first layer is &lt;strong&gt;the architecture around each reasoning step&lt;/strong&gt;: where information flows, how state is preserved, how subgoals are decomposed, how steps connect. Most documented patterns for long-running agents operate here. They shape the agent system around the model.&lt;/p&gt;

&lt;p&gt;The second layer is &lt;strong&gt;the structure inside each reasoning step&lt;/strong&gt;: what shape the model's reasoning takes when it fires, what failure modes it actively blocks, what scaffold its conclusion is built against. By default, all of that is implicit. The model improvises a reasoning path each time. Improvisation is fine in shallow tasks; it is where the wheels come off in long ones.&lt;/p&gt;

&lt;p&gt;The sections below describe five established patterns at the first layer and an emerging pattern at the second. They compose. Each addresses a different surface of the same underlying problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's actually going wrong
&lt;/h2&gt;

&lt;p&gt;Under the hood, several mechanisms feed into the spiral:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Context pollution.&lt;/strong&gt; Failed tool calls, dead-end reasoning, retry chatter, and stale state all stay in the window unless explicitly evicted. They keep competing for attention forever.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Goal drift.&lt;/strong&gt; Without periodic re-grounding, the agent optimizes against a slowly mutating version of the original task. By step 50 it is solving a problem that is subtly not the one asked.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Confidence miscalibration.&lt;/strong&gt; The model often cannot tell its own earlier reasoning was wrong, so it builds on top of bad assumptions instead of backtracking. Hallucinated tool parameters become "facts" by step 15.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Loop traps.&lt;/strong&gt; Agents get stuck in cycles (try X, fail, try Y, fail, try X again) because the failure signal is not structured strongly enough to break the pattern.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State/world mismatch.&lt;/strong&gt; The agent's internal model of the file system, the database, or the API state diverges from reality and never gets corrected.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Better models help with all of these (confidence calibration in particular tracks capability), but they do not make the problems disappear. The shape of the failure is structural: information accumulates inside a finite-attention process and errors propagate through dependent steps. Architecture is the higher-leverage axis, and it compounds with whatever the model gives.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architectural patterns: the first layer
&lt;/h2&gt;

&lt;p&gt;These are patterns that have emerged in practice. They were largely discovered by people whose agents kept breaking and have since been documented in engineering reports and research literature.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Context engineering: curate, don't accumulate
&lt;/h3&gt;

&lt;p&gt;The default agent loop appends everything: every prompt, every tool call, every result, every reflection. At each step, build the context deliberately from a smaller, structured store.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
python
def build_step_context(task, state):
    return {
        "system": SYSTEM_PROMPT,
        "task": task.goal,                       # always present, never edited
        "constraints": task.constraints,          # always present
        "current_subgoal": state.current_subgoal,
        "recent_steps": state.history[-3:],       # last few only
        "relevant_artifacts": retrieve(           # pulled in by relevance
            query=state.current_subgoal,
            store=state.artifact_store,
            k=5,
        ),
        "scratchpad": state.scratchpad,           # explicitly managed
    }

The agent does not see "everything that has happened." It sees a compiled view relevant to right now. The full history lives in an external store, and only what is needed gets surfaced.
---
2. Planner-worker decomposition
This architecture has become the default for serious long-running agents and is documented at length in Anthropic's Building Effective Agents (2024), which describes orchestrator-worker variants used in Claude Code and similar systems. Cursor, AWS Strands, and Google's ADK use closely related patterns.


┌─────────────────────────────┐
│  Planner (frontier model)   │
│  - Holds the high-level     │
│    goal and strategy        │
│  - Decomposes into tasks    │
│  - Reviews results          │
└──────────────┬──────────────┘
               │
        ┌──────▼──────┐
        │  Task queue │
        └──────┬──────┘
               │
   ┌───────────┼───────────┐
   ▼           ▼           ▼
┌────────┐ ┌────────┐ ┌────────┐
│Worker 1│ │Worker 2│ │Worker 3│
│ (short │ │ (short │ │ (short │
│  loop) │ │  loop) │ │  loop) │
└────────┘ └────────┘ └────────┘
The planner stays uncluttered because it never touches per-task tool-call noise. The workers stay uncluttered because each is a short-lived loop with a narrow goal. No single context window has to carry the whole task. This pushes the cliff outward by shortening the dependency chains any single reasoning loop has to maintain.
---
3. Externalize state, then re-read it deliberately
Don't trust attention to surface what matters. Write key decisions, constraints, and progress to durable artifacts (files, a structured scratchpad, a small database) and have the agent re-read them at decision points.


# Bad: hope the model remembers
agent.run(task)

# Better: explicit re-grounding
while not done:
    plan = agent.plan(
        task=task,
        constraints=read_file("constraints.md"),
        progress=read_file("progress.md"),
    )
    result = execute(plan)
    update_file("progress.md", result)
    done = check_done(task, result)
The agent's "memory" becomes a thing one can inspect, version, and edit. Debugging gets dramatically easier as a side effect.
---
4. Critic loops and self-reflection
If per-step reliability has a hard ceiling, the way out is making errors catchable rather than rarer. Shinn et al. (2023) formalized this in Reflexion, where an agent receives verbal feedback on its own outputs and refines them iteratively. The simpler form is a separate critic agent reviewing each step before it commits.


def step_with_critic(state):
    proposal = actor.propose(state)
    critique = critic.review(proposal, state)
    if critique.approves:
        return execute(proposal)
    return step_with_critic(state.with_feedback(critique))
This is the insight behind frameworks that have pushed reliable agent execution to long horizons: stop chasing lower individual error rates, design for error correction.
---
5. Bounded retries and explicit loop detection
Detect cycles and break out programmatically. A simple hash of recent (action, result) pairs catches a lot of loops the model cannot see itself in:


recent_signatures = []

def take_step(state):
    proposal = agent.propose(state)
    sig = hash((proposal.action, proposal.target))
    if recent_signatures.count(sig) &amp;gt;= 2:
        return escalate_to_planner(state, reason="loop_detected")
    recent_signatures.append(sig)
    return execute(proposal)
The agent often cannot notice it is in a loop. The architecture has to.

The second layer: structuring the reasoning step itself
The five patterns above all operate around the reasoning step. They shape what information the model receives, what other models check its work, and what happens between thoughts. Inside the thought itself, the model is still improvising.

There is a complementary pattern that addresses the inside of the step: provide the reasoning structure itself, retrieved at runtime, matched to the task type, injected before the model reasons. The model still does the reasoning. It does it against a scaffold that names the path, blocks the shortcut, and identifies the failure mode to actively avoid.

Conceptually, the artifact looks like this:


NEGATIVE GATE      the failure mode to actively block, named explicitly
PROCEDURE          ordered steps with backtrack-if conditions
TOPOLOGY           a small DAG of S (steps), G (gates), N (failure traps),
                   M (reflection nodes that let the model abandon the
                   current path and re-enter at a named step)
TARGET PATTERN     what correct reasoning looks like for this task type
SUPPRESSION        signals biasing the model away from the shortcut and
                   toward the structural check
In code, the integration point is shallow: the topology is fetched at the start of the reasoning step, prepended to context, and the model proceeds.


# Conventional: implicit reasoning
result = agent.reason(task)

# With injected reasoning structure
topology = topology_library.match(task)   # task-matched scaffold
result = agent.reason(task, scaffold=topology)
Different task types want different topologies. A coding task wants an engineering procedure with explicit backtrack conditions. A long-horizon analytical task wants a metacognitive loop that re-grounds against the goal at each gate. An advice or judgment task wants something closer to a directness enforcer, not a deliberative scaffold; applying a deliberative reasoning structure to advice tasks introduces hedging where directness was the right answer. Selecting the right topology for the task is the engineering problem most naive implementations underestimate.

This pattern shares lineage with programmatic-prompting frameworks like DSPy (Khattab et al.), which compiles prompt programs at design time. The runtime-injection variant differs in that the structures are retrieved per task rather than compiled once, which lets the topology track task type at inference rather than at deployment.

What this addresses is the part of the failure surface the architectural patterns leave untouched. Context engineering ensures the right information reaches the model; it does not constrain how the model reasons over it. Critic loops catch errors after the fact; they do not prevent the shortcut at its source. Loop detection catches behavioral cycles; it does not address the reasoning shape that produced the cycle. Runtime injection acts before the model commits, which is structurally earlier than any of the architectural patterns can intervene.

It is not a substitute for the first-layer patterns. It composes with them. The two layers address two different surfaces of the same problem: the path between reasoning steps and the structure inside each step.

When not to bother
These mitigations are not free. Planner-worker layers the planner's tokens on top of every worker's, with overhead ranging from modest to roughly doubling total inference cost depending on how the split lands. Critic loops add another model pass per step. Curated context retrieval adds latency and infra overhead. Logging state to disk between steps slows everything down. Runtime topology injection adds one extra call per agent invocation.

A useful rule of thumb: if the task completes in under five minutes of agent runtime and under twenty dependent tool calls, none of these patterns are necessary. Reach for them when the task cannot fit that envelope.

There is a measurement question hiding here as well. "My agent gets worse over time" and "my agent cannot do this task at all" look identical from the outside but require different fixes. Before architecting around decay, confirm decay is what is actually being seen. Log per-step success against horizon length and look for a curve. Flat-and-high failure rate is a capability problem, and these patterns will not help with it.

The takeaway
The pattern shows up across model families and sizes because the cause is structural:

Attention is finite, so unbounded context accumulation drowns the signal that needs to be heard.
Per-step errors compound badly with horizon length, so individual step accuracy alone cannot carry a long task.
The agent cannot reliably detect its own decay, so the correction has to come from the system around it.
The reasoning step itself has a default shape that breaks at depth, so making the reasoning structure explicit and task-matched is a leverage point separate from the architectural patterns.
The teams getting the most out of long-running agents are not the ones leaning on the biggest context windows. They are the ones treating the agent as a system with multiple distinct layers and engineering each one rather than hoping for it: context compiled rather than accumulated, horizons decomposed rather than bulldozed, state externalized rather than implicit, and reasoning structure provisioned rather than improvised.

The deeper shift behind all of this is that the next era of agents will not be defined by how big the context window gets or how smart the next base model is. It will be defined by the cognitive infrastructure that wraps the model: the reasoning structure injected at the right moment, the context compiled at the right granularity, the failure modes blocked before the model commits, the route between thoughts engineered rather than left to chance. The model is one component. The reliable agent is the model plus the architecture that keeps it crisp under load.

Build for decay. The future maintainer, debugging an agent that spent four hours politely reverting its own work, will be glad of it.

If you've hit your own variant of the 35-minute cliff, the comments are open. Failure modes are useful; the more of them get cataloged, the less guesswork goes into the next system that has to survive past hour two.

References
Liu, Nelson F. et al. (2023). Lost in the Middle: How Language Models Use Long Contexts. Transactions of the Association for Computational Linguistics.
Anthropic (2024). Building Effective Agents. Engineering blog.
Shinn, Noah et al. (2023). Reflexion: Language Agents with Verbal Reinforcement Learning. NeurIPS.
Khattab, Omar et al. DSPy: Compiling Declarative Language Model Calls into Self-Improving Pipelines. Stanford NLP.
METR. Measuring AI Ability to Complete Long Tasks. Long-horizon agent benchmarking.

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

&lt;/div&gt;

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