{"id":8654,"date":"2026-07-08T09:34:30","date_gmt":"2026-07-08T09:34:30","guid":{"rendered":"https:\/\/algocademy.com\/blog\/?p=8654"},"modified":"2026-07-08T09:39:38","modified_gmt":"2026-07-08T09:39:38","slug":"stop-reviewing-every-ai-output-how-to-build-agents-that-can-work-at-scale","status":"publish","type":"post","link":"https:\/\/algocademy.com\/blog\/stop-reviewing-every-ai-output-how-to-build-agents-that-can-work-at-scale\/","title":{"rendered":"Stop Reviewing Every AI Output: How to Build Agents That Can Work at Scale"},"content":{"rendered":"\n<p>AI coding agents are becoming very good at producing large amounts of code and content.<\/p>\n\n\n\n<p>When an agent changes 20 lines of code, th. You run the application. You spot a mistake. You ask the agent to fix it.<\/p>\n\n\n\n<p>But what happens when an agent modifies 120 files?<\/p>\n\n\n\n<p>Or generates 1,000 coding tutorials?<\/p>\n\n\n\n<p>Or produces 100,000 lines of code and content?<\/p>\n\n\n\n<p>Suddenly, the human becomes the bottleneck.<\/p>\n\n\n\n<p>This is a problem I have been facing while building AlgoCademy, an interactive platform that teaches programming and algorithmic thinking through step-by-step coding tutorials.<\/p>\n\n\n\n<p>A tutorial might teach Two Sum like this:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Create a map.<\/li>\n\n\n\n<li>Write an empty <code>for<\/code> loop.<\/li>\n\n\n\n<li>Calculate the complement.<\/li>\n\n\n\n<li>Check whether the complement exists in the map.<\/li>\n\n\n\n<li>Store the current number.<\/li>\n\n\n\n<li>Return the matching indexes.<\/li>\n<\/ol>\n\n\n\n<p>AI agents are surprisingly good at generating this type of content.<\/p>\n\n\n\n<p>The problem is volume.<\/p>\n\n\n\n<p>Imagine an agent generates 500 tutorials with 10 steps each.<\/p>\n\n\n\n<p>That is 5,000 individual tutorial steps.<\/p>\n\n\n\n<p>Even if reviewing one step takes only 20 seconds, manually checking everything would require almost 28 hours of uninterrupted work.<\/p>\n\n\n\n<p>At that point, what exactly have we automated?<\/p>\n\n\n\n<p>This led me to a much more important question:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Can AI agents produce large amounts of code or content without a human checking every single output?<\/p>\n<\/blockquote>\n\n\n\n<p>I think the answer is yes.<\/p>\n\n\n\n<p>But not by making the agent more careful.<\/p>\n\n\n\n<p>The real solution is to build a system that is good at <strong>detecting bad output<\/strong>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">The Wrong Goal: Make the Agent Stop Making Mistakes<\/h1>\n\n\n\n<p>The natural response to unreliable AI output is to improve the prompt.<\/p>\n\n\n\n<p>You start with:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Generate a step-by-step coding tutorial.\n<\/code><\/pre>\n\n\n\n<p>Then you find a mistake.<\/p>\n\n\n\n<p>So you add:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Make sure every step is technically correct.\n<\/code><\/pre>\n\n\n\n<p>Then another mistake appears.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Do not introduce variables before explaining them.\n<\/code><\/pre>\n\n\n\n<p>Then:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Make sure the code from each step is consistent with the previous step.\n<\/code><\/pre>\n\n\n\n<p>Then:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>VERY IMPORTANT: Never reveal code from a future step.\n<\/code><\/pre>\n\n\n\n<p>Six months later, your system prompt looks like the terms and conditions for a mortgage.<\/p>\n\n\n\n<p>And the agent still occasionally makes mistakes.<\/p>\n\n\n\n<p>I am not saying prompts do not matter. They obviously do.<\/p>\n\n\n\n<p>But there is a fundamental difference between:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Reducing the probability of an error.<\/p>\n<\/blockquote>\n\n\n\n<p>and:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Building a system that detects errors when they happen.<\/p>\n<\/blockquote>\n\n\n\n<p>For serious automation, you need both.<\/p>\n\n\n\n<p>Traditional software engineering already works this way.<\/p>\n\n\n\n<p>We do not assume programmers never create bugs.<\/p>\n\n\n\n<p>We use:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Type systems<\/li>\n\n\n\n<li>Compilers<\/li>\n\n\n\n<li>Linters<\/li>\n\n\n\n<li>Unit tests<\/li>\n\n\n\n<li>Integration tests<\/li>\n\n\n\n<li>CI pipelines<\/li>\n\n\n\n<li>Code review<\/li>\n\n\n\n<li>Production monitoring<\/li>\n<\/ul>\n\n\n\n<p>The developer is not the entire reliability system.<\/p>\n\n\n\n<p><strong>The engineering process is the reliability system.<\/strong><\/p>\n\n\n\n<p>AI agents need the same thing.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Stop Reviewing AI Output. Start Building an AI CI Pipeline<\/h1>\n\n\n\n<p>The simplest AI workflow looks like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>AI generates artifact\n        \u2193\nHuman reviews artifact\n        \u2193\nPublish\n<\/code><\/pre>\n\n\n\n<p>The problem is that human review scales linearly with AI output.<\/p>\n\n\n\n<p>Generate ten times more content and you create ten times more review work.<\/p>\n\n\n\n<p>A better architecture looks like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>AI generates artifact\n        \u2193\nDeterministic checks\n        \u2193\nSemantic evaluators\n        \u2193\nAdversarial execution\n        \u2193\nAutomatic repair\n        \u2193\nRisk assessment\n        \u2193\nPublish or escalate to human\n<\/code><\/pre>\n\n\n\n<p>The human no longer checks every artifact.<\/p>\n\n\n\n<p>The human designs and improves the system that decides which artifacts are safe.<\/p>\n\n\n\n<p>This is very close to how current agent-evaluation guidance is evolving. Anthropic describes agent evaluations as commonly combining code-based, model-based, and human graders, and explicitly recommends deterministic graders where possible, model graders where necessary, and human review as an additional validation layer. escribes a practical agent eval as:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>prompt\n   \u2193\ncaptured run: trace + artifacts\n   \u2193\nchecks\n   \u2193\nscore\n<\/code><\/pre>\n\n\n\n<p>The goal is to turn &#8220;this seems better&#8221; into concrete, repeatable tests. of this as <strong>AI CI<\/strong>.<\/p>\n\n\n\n<p>Traditional CI asks:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Does the code compile?\nDo the tests pass?\nDid linting succeed?\n<\/code><\/pre>\n\n\n\n<p>AI CI might ask:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Is the artifact structurally valid?\nIs the code correct?\nDid the output violate a rule?\nDoes the instruction match the generated code?\nDoes the artifact depend on knowledge it should not require?\nCan another agent successfully execute the instructions?\nHow much disagreement exists between our evaluators?\n<\/code><\/pre>\n\n\n\n<p>The important mental shift is this:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Do not try to make the generator trustworthy enough that validation becomes unnecessary.<\/p>\n<\/blockquote>\n\n\n\n<p>Build validation assuming the generator will eventually fail.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">My Specific Problem: Step-by-Step Coding Tutorials<\/h1>\n\n\n\n<p>Let&#8217;s use AlgoCademy as a concrete example.<\/p>\n\n\n\n<p>The final Two Sum solution might be:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>function twoSum(nums, target) {\n    const seen = new Map();\n\n    for (let i = 0; i &lt; nums.length; i++) {\n        const complement = target - nums&#91;i];\n\n        if (seen.has(complement)) {\n            return &#91;seen.get(complement), i];\n        }\n\n        seen.set(nums&#91;i], i);\n    }\n\n    return &#91;];\n}\n<\/code><\/pre>\n\n\n\n<p>An AI can explain this solution in a few seconds.<\/p>\n\n\n\n<p>But AlgoCademy does not just show the final solution.<\/p>\n\n\n\n<p>The student might start with:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>function twoSum(nums, target) {\n\n}\n<\/code><\/pre>\n\n\n\n<p>Step 1:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Create a Map called <code>seen<\/code>.<\/p>\n<\/blockquote>\n\n\n\n<p>The expected transformation is:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>function twoSum(nums, target) {\n    const seen = new Map();\n}\n<\/code><\/pre>\n\n\n\n<p>Step 2:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Create an empty <code>for<\/code> loop that iterates through the indexes of <code>nums<\/code>.<\/p>\n<\/blockquote>\n\n\n\n<p>The code becomes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>function twoSum(nums, target) {\n    const seen = new Map();\n\n    for (let i = 0; i &lt; nums.length; i++) {\n\n    }\n}\n<\/code><\/pre>\n\n\n\n<p>Step 3:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Inside the loop, calculate the difference between <code>target<\/code> and the current number. Store it in a variable called <code>complement<\/code>.<\/p>\n<\/blockquote>\n\n\n\n<p>And so on.<\/p>\n\n\n\n<p>An AI agent can create a tutorial that looks perfectly reasonable while still making subtle mistakes.<\/p>\n\n\n\n<p>It might:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Introduce <code>complement<\/code> before explaining it.<\/li>\n\n\n\n<li>Modify unrelated code from the previous step.<\/li>\n\n\n\n<li>Skip an important reasoning step.<\/li>\n\n\n\n<li>Refer to a Map before the student has learned Maps.<\/li>\n\n\n\n<li>Use <code>seen<\/code> in the instruction but <code>map<\/code> in the code.<\/li>\n\n\n\n<li>Reveal the next step in the explanation.<\/li>\n\n\n\n<li>Make a step so large that the student is effectively writing the whole solution.<\/li>\n\n\n\n<li>Create an instruction with several valid interpretations.<\/li>\n\n\n\n<li>Produce a technically correct final solution with a terrible learning progression.<\/li>\n<\/ul>\n\n\n\n<p>A normal unit test cannot detect all of these problems.<\/p>\n\n\n\n<p>But that does not mean a human has to inspect every tutorial.<\/p>\n\n\n\n<p>It means different problems require different validators.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">First: Turn Content Into Structured Artifacts<\/h1>\n\n\n\n<p>Before validating AI-generated content, make the content easy to validate.<\/p>\n\n\n\n<p>Do not ask an agent to return one giant Markdown document containing instructions, explanations, and code blocks.<\/p>\n\n\n\n<p>Instead, ask it to return structured data.<\/p>\n\n\n\n<p>For example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"problemId\": \"two-sum\",\n  \"language\": \"javascript\",\n  \"concepts\": &#91;\n    \"arrays\",\n    \"hash-maps\"\n  ],\n  \"initialCode\": \"function twoSum(nums, target) {\\n\\n}\",\n  \"finalCode\": \"...\",\n  \"steps\": &#91;\n    {\n      \"id\": \"create-map\",\n      \"instruction\": \"Create a Map called `seen`.\",\n      \"concept\": \"hash-map\",\n      \"previousCode\": \"...\",\n      \"expectedCode\": \"...\",\n      \"introducedSymbols\": &#91;\n        \"seen\"\n      ]\n    }\n  ]\n}\n<\/code><\/pre>\n\n\n\n<p>Now the tutorial is not just text.<\/p>\n\n\n\n<p>It is an artifact with a contract.<\/p>\n\n\n\n<p>You can enforce rules such as:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Every step must have a unique ID.\n\nEvery referenced concept must exist in the concept registry.\n\nEvery declared prerequisite must already be available to the student.\n\nThe final step must reach a valid solution.\n\nA symbol cannot be marked as introduced twice.\n<\/code><\/pre>\n\n\n\n<p>None of these checks require an LLM.<\/p>\n\n\n\n<p>Your application already knows whether two IDs are identical.<\/p>\n\n\n\n<p>Do not ask Claude:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Are all step IDs unique?<\/p>\n<\/blockquote>\n\n\n\n<p>Write:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const ids = tutorial.steps.map(step =&gt; step.id);\n\nif (new Set(ids).size !== ids.length) {\n    throw new Error(\"Duplicate step ID\");\n}\n<\/code><\/pre>\n\n\n\n<p>This is one of the most important rules I have learned while building AI workflows:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Never use an LLM to check something that ordinary code can check reliably.<\/p>\n<\/blockquote>\n\n\n\n<p>LLMs should handle ambiguity.<\/p>\n\n\n\n<p>Software should enforce invariants.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Think of Every Tutorial Step as a State Transition<\/h1>\n\n\n\n<p>A step-by-step coding tutorial is essentially a sequence of program states:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>S0 \u2192 S1 \u2192 S2 \u2192 S3 \u2192 S4\n<\/code><\/pre>\n\n\n\n<p>Each tutorial instruction describes a transition:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Sn \u2192 Sn+1\n<\/code><\/pre>\n\n\n\n<p>For example:<\/p>\n\n\n\n<p>Previous state:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>function twoSum(nums, target) {\n    const seen = new Map();\n}\n<\/code><\/pre>\n\n\n\n<p>Next state:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>function twoSum(nums, target) {\n    const seen = new Map();\n\n    for (let i = 0; i &lt; nums.length; i++) {\n\n    }\n}\n<\/code><\/pre>\n\n\n\n<p>The transformation is approximately:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ADD ForStatement\n\ninitializer:\n    let i = 0\n\ncondition:\n    i &lt; nums.length\n\nincrement:\n    i++\n<\/code><\/pre>\n\n\n\n<p>The instruction says:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Create an empty <code>for<\/code> loop that iterates through the indexes of <code>nums<\/code>.<\/p>\n<\/blockquote>\n\n\n\n<p>The instruction and transformation agree.<\/p>\n\n\n\n<p>Now imagine the instruction says:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Loop through every number in <code>nums<\/code>.<\/p>\n<\/blockquote>\n\n\n\n<p>But the generated code iterates over indexes.<\/p>\n\n\n\n<p>That instruction is ambiguous.<\/p>\n\n\n\n<p>A student might reasonably write:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>for (const num of nums) {\n\n}\n<\/code><\/pre>\n\n\n\n<p>The final algorithm may still be possible.<\/p>\n\n\n\n<p>But the generated tutorial expects an index-based loop.<\/p>\n\n\n\n<p>This is exactly the kind of problem a compiler will not catch.<\/p>\n\n\n\n<p>So instead of asking:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Is this a good tutorial step?<\/p>\n<\/blockquote>\n\n\n\n<p>I can ask a much narrower question:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Does the instruction accurately describe the transformation from the previous program state to the next program state?<\/p>\n<\/blockquote>\n\n\n\n<p>That is a much easier evaluation problem.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">But Do Not Require Exact AST Equality<\/h1>\n\n\n\n<p>This is an important detail.<\/p>\n\n\n\n<p>My first instinct was to compare the student&#8217;s Abstract Syntax Tree with the expected AST.<\/p>\n\n\n\n<p>For example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>student AST === expected AST\n<\/code><\/pre>\n\n\n\n<p>I now think that is too rigid for many coding tutorials.<\/p>\n\n\n\n<p>Consider:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>for (let i = 0; i &lt; nums.length; i++) {\n}\n<\/code><\/pre>\n\n\n\n<p>and:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>for (let index = 0; index &lt; nums.length; index++) {\n}\n<\/code><\/pre>\n\n\n\n<p>The ASTs are different.<\/p>\n\n\n\n<p>The transformation may be pedagogically equivalent.<\/p>\n\n\n\n<p>Or consider:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const complement = target - nums&#91;i];\n<\/code><\/pre>\n\n\n\n<p>versus:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const needed = target - nums&#91;i];\n<\/code><\/pre>\n\n\n\n<p>Again, different structure.<\/p>\n\n\n\n<p>Potentially the same valid idea.<\/p>\n\n\n\n<p>Anthropic&#8217;s evaluation guidance explicitly warns that deterministic graders can be brittle when valid variations do not match the expected pattern exactly. It also cautions against overly rigid process checks that punish valid approaches an evaluator did not anticipate. etter approach is not:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Does the AST exactly equal our expected AST?\n<\/code><\/pre>\n\n\n\n<p>It is:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Does the program satisfy the structural contract for this step?\n<\/code><\/pre>\n\n\n\n<p>For example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>A loop was added.\n\nThe loop traverses nums.\n\nThe loop exposes the current index.\n\nThe loop body is empty.\n\nExisting required statements were not removed.\n<\/code><\/pre>\n\n\n\n<p>The validator might accept several AST patterns that satisfy those properties.<\/p>\n\n\n\n<p>This is a major difference.<\/p>\n\n\n\n<p>You are validating <strong>invariants<\/strong>, not formatting.<\/p>\n\n\n\n<p>For AlgoCademy, this is especially important because a coding-learning platform should avoid teaching students that there is only one textual way to write correct code.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Make Evaluations Atomic<\/h1>\n\n\n\n<p>One of the worst evaluators you can create is:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Review this tutorial.\n\nMake sure it is:\n- correct\n- clear\n- educational\n- beginner friendly\n- progressive\n- technically accurate\n\nScore it from 1 to 10.\n<\/code><\/pre>\n\n\n\n<p>Suppose the result is:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>8\/10\n<\/code><\/pre>\n\n\n\n<p>What do I do with that?<\/p>\n\n\n\n<p>Why was it an eight?<\/p>\n\n\n\n<p>What failed?<\/p>\n\n\n\n<p>Can an agent automatically repair it?<\/p>\n\n\n\n<p>Did version two improve?<\/p>\n\n\n\n<p>Instead, I want atomic validators.<\/p>\n\n\n\n<p>For example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>V001: Tutorial schema is valid\n\nV002: Step IDs are unique\n\nV003: Final solution passes hidden tests\n\nV004: Required checkpoints parse successfully\n\nV005: Symbols are introduced before they are referenced\n\nV006: Instruction matches the code transformation\n\nV007: No unrelated code is modified\n\nV008: Step introduces at most one primary learning objective\n\nV009: Explanation does not reveal future implementation details\n\nV010: Terminology matches the curriculum\n\nV011: Variable references are consistent\n\nV012: Required concepts were previously introduced\n\nV013: The tutorial reaches a correct solution\n\nV014: Complexity explanation matches the implementation\n\nV015: A student can reasonably perform the requested transformation\n<\/code><\/pre>\n\n\n\n<p>The result might be:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"V001\": \"PASS\",\n  \"V002\": \"PASS\",\n  \"V003\": \"PASS\",\n  \"V004\": \"PASS\",\n  \"V005\": \"PASS\",\n  \"V006\": \"FAIL\",\n  \"V007\": \"PASS\",\n  \"V008\": \"PASS\",\n  \"V009\": \"PASS\",\n  \"V010\": \"PASS\",\n  \"V011\": \"PASS\",\n  \"V012\": \"PASS\",\n  \"V013\": \"PASS\",\n  \"V014\": \"PASS\",\n  \"V015\": {\n    \"score\": 0.81\n  }\n}\n<\/code><\/pre>\n\n\n\n<p>Now we know exactly what happened.<\/p>\n\n\n\n<p>This is the agent equivalent of:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>48 tests passed\n2 tests failed\n<\/code><\/pre>\n\n\n\n<p>Instead of:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Your code feels pretty good.\n<\/code><\/pre>\n\n\n\n<p>OpenAI&#8217;s current eval guidance similarly emphasizes defining measurable success and using a small set of concrete checks rather than relying on whether a new version merely &#8220;feels better.&#8221; alidate Code With Code<\/p>\n\n\n\n<p>For coding education, we have an enormous advantage.<\/p>\n\n\n\n<p>Code is much easier to validate than most AI-generated content.<\/p>\n\n\n\n<p>Use that advantage aggressively.<\/p>\n\n\n\n<p>For each final solution, I can run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Public examples\nHidden tests\nEdge cases\nRandomly generated tests\nReference implementations\n<\/code><\/pre>\n\n\n\n<p>Consider Two Sum.<\/p>\n\n\n\n<p>Generate:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const nums = &#91;-3, 7, 2, 11, 5];\nconst target = 9;\n<\/code><\/pre>\n\n\n\n<p>Run both:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>generated solution\nreference solution\n<\/code><\/pre>\n\n\n\n<p>Then validate the result.<\/p>\n\n\n\n<p>For problems with several valid answers, I do not necessarily need an exact expected output.<\/p>\n\n\n\n<p>I can validate properties.<\/p>\n\n\n\n<p>For example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>function isValidTwoSumAnswer(\n    nums: number&#91;],\n    target: number,\n    result: number&#91;]\n): boolean {\n    if (result.length !== 2) {\n        return false;\n    }\n\n    const &#91;i, j] = result;\n\n    if (\n        !Number.isInteger(i) ||\n        !Number.isInteger(j) ||\n        i &lt; 0 ||\n        j &lt; 0 ||\n        i &gt;= nums.length ||\n        j &gt;= nums.length\n    ) {\n        return false;\n    }\n\n    if (i === j) {\n        return false;\n    }\n\n    return nums&#91;i] + nums&#91;j] === target;\n}\n<\/code><\/pre>\n\n\n\n<p>The validator does not know the exact answer.<\/p>\n\n\n\n<p>It knows what must be true about a correct answer.<\/p>\n\n\n\n<p>This leads to a much broader principle for AI systems:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Instead of asking whether the AI produced exactly what you expected, identify the properties every acceptable result must satisfy.<\/p>\n<\/blockquote>\n\n\n\n<p>The more quality requirements you can convert into invariants, the less human review you need.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Not Every Intermediate Step Has to Compile<\/h1>\n\n\n\n<p>There is another subtle issue with step-by-step coding education.<\/p>\n\n\n\n<p>It is tempting to create this rule:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Every intermediate code state must compile.\n<\/code><\/pre>\n\n\n\n<p>That may work for a specific tutorial format.<\/p>\n\n\n\n<p>It is not universally correct.<\/p>\n\n\n\n<p>Some educational systems intentionally let a learner stop at a partially complete expression or temporarily incomplete block.<\/p>\n\n\n\n<p>For example, a lesson could ask the student to first write:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>if (\n<\/code><\/pre>\n\n\n\n<p>before teaching the condition.<\/p>\n\n\n\n<p>A normal JavaScript parser will reject that state.<\/p>\n\n\n\n<p>You have several choices.<\/p>\n\n\n\n<p>You can design AlgoCademy so every completed step is a valid parsing checkpoint.<\/p>\n\n\n\n<p>Or you can use a tolerant parser.<\/p>\n\n\n\n<p>Or you can validate the edited region without requiring the whole program to execute.<\/p>\n\n\n\n<p>The important part is that this should be an explicit product rule.<\/p>\n\n\n\n<p>Do not accidentally turn:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Our current examples happen to parse.<\/p>\n<\/blockquote>\n\n\n\n<p>into:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Every educational programming step must always compile.<\/p>\n<\/blockquote>\n\n\n\n<p>Your validator should enforce your pedagogy, not silently define it.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Use LLM Judges Only Where Rules Become Semantic<\/h1>\n\n\n\n<p>Some questions are difficult to answer with ordinary code.<\/p>\n\n\n\n<p>For example:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Is this instruction ambiguous?<\/p>\n<\/blockquote>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Does this step require a concept the student probably does not understand yet?<\/p>\n<\/blockquote>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Does the explanation accidentally reveal how to solve the next step?<\/p>\n<\/blockquote>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Is this learning step too cognitively large?<\/p>\n<\/blockquote>\n\n\n\n<p>These are reasonable jobs for an LLM evaluator.<\/p>\n\n\n\n<p>But there is a trap.<\/p>\n\n\n\n<p>Do not simply ask:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Is this a good instruction?\n<\/code><\/pre>\n\n\n\n<p>Instead, give the evaluator a narrow rubric.<\/p>\n\n\n\n<p>For example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>The student knows:\n- variables\n- arrays\n- basic for loops\n\nThe student does NOT know:\n- Maps\n- Sets\n- destructuring\n\nInstruction:\n&#91;INSTRUCTION]\n\nDoes completing this instruction require a programming concept\noutside the student's known concepts?\n\nReturn JSON:\n\n{\n  \"pass\": boolean,\n  \"unknownConcepts\": &#91;],\n  \"evidence\": &#91;]\n}\n<\/code><\/pre>\n\n\n\n<p>The judge has one job.<\/p>\n\n\n\n<p>I generally prefer binary or narrowly scored questions over broad quality scores.<\/p>\n\n\n\n<p>Compare:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Score the tutorial's consistency from 1 to 10.\n<\/code><\/pre>\n\n\n\n<p>with:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Does the instruction reference a symbol that is unavailable\nin the previous program state?\n<\/code><\/pre>\n\n\n\n<p>The second result is much more useful.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Do Not Blindly Trust AI to Judge AI<\/h1>\n\n\n\n<p>LLM judges are useful.<\/p>\n\n\n\n<p>They are not objective truth machines.<\/p>\n\n\n\n<p>Research on LLM-as-a-judge has documented limitations including position, verbosity, and self-enhancement biases. s not mean we should avoid model-based evaluators.<\/p>\n\n\n\n<p>It means we should treat them as imperfect components.<\/p>\n\n\n\n<p>Some things I would do:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Give each evaluator one narrow job<\/h3>\n\n\n\n<p>A pedagogy evaluator should evaluate pedagogy.<\/p>\n\n\n\n<p>A technical correctness evaluator should evaluate technical correctness.<\/p>\n\n\n\n<p>Do not create:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SUPER REVIEW AGENT\n\nCheck absolutely everything.\n<\/code><\/pre>\n\n\n\n<p>That is just recreating the original context problem.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Require structured evidence<\/h3>\n\n\n\n<p>Instead of:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"score\": 0.72\n}\n<\/code><\/pre>\n\n\n\n<p>I prefer:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"pass\": false,\n  \"stepId\": \"calculate-complement\",\n  \"rule\": \"FUTURE_STEP_LEAKAGE\",\n  \"evidence\": &#91;\n    \"The explanation references seen.has(), which is introduced in the next step.\"\n  ]\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Measure evaluator disagreement<\/h3>\n\n\n\n<p>Suppose three evaluators return:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>PASS\nPASS\nPASS\n<\/code><\/pre>\n\n\n\n<p>That is different from:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>PASS\nPASS\nFAIL\n<\/code><\/pre>\n\n\n\n<p>Even if your majority-vote result is still PASS.<\/p>\n\n\n\n<p>Disagreement itself is information.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Calibrate judges against humans<\/h3>\n\n\n\n<p>Take a manually reviewed dataset.<\/p>\n\n\n\n<p>Run your model judge.<\/p>\n\n\n\n<p>Measure what it misses.<\/p>\n\n\n\n<p>A semantic judge should earn trust based on its performance on your specific tutorial defects.<\/p>\n\n\n\n<p>Do not trust it merely because you used an expensive model.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Build a Simulated Student Agent<\/h1>\n\n\n\n<p>This is the validator I find most interesting for AlgoCademy.<\/p>\n\n\n\n<p>Instead of asking:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Is the instruction clear?<\/p>\n<\/blockquote>\n\n\n\n<p>Try to execute the instruction.<\/p>\n\n\n\n<p>Give an agent only:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Student knowledge\nCurrent code\nTutorial instruction\n<\/code><\/pre>\n\n\n\n<p>Do not show it the expected solution.<\/p>\n\n\n\n<p>Then say:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Modify the code by following the instruction.<\/p>\n<\/blockquote>\n\n\n\n<p>Imagine the instruction is:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Create a loop through <code>nums<\/code>.<\/p>\n<\/blockquote>\n\n\n\n<p>The expected tutorial transformation uses:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>for (let i = 0; i &lt; nums.length; i++) {\n\n}\n<\/code><\/pre>\n\n\n\n<p>But the simulated student writes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>for (const num of nums) {\n\n}\n<\/code><\/pre>\n\n\n\n<p>This does not automatically mean the student&#8217;s answer is wrong.<\/p>\n\n\n\n<p>In fact, that is the important part.<\/p>\n\n\n\n<p>It may mean the instruction allows more than one reasonable interpretation.<\/p>\n\n\n\n<p>The evaluator can compare the student&#8217;s transformation with the <strong>step contract<\/strong>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Required:\n- traverse nums\n- expose the current index\n\nStudent result:\n- traverses nums: YES\n- exposes current index: NO\n<\/code><\/pre>\n\n\n\n<p>Now ask:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Did the student ignore an explicit requirement, or did the instruction fail to communicate the requirement?<\/p>\n<\/blockquote>\n\n\n\n<p>If &#8220;index&#8221; never appears in the instruction, the problem may be the tutorial.<\/p>\n\n\n\n<p>The output could be:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"result\": \"AMBIGUOUS_INSTRUCTION\",\n  \"requiredProperty\": \"INDEX_AVAILABLE\",\n  \"studentInterpretation\": \"VALUE_ITERATION\",\n  \"reason\": \"The instruction says to loop through nums but does not specify index-based iteration.\"\n}\n<\/code><\/pre>\n\n\n\n<p>This is much better than asking another AI:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Do you think this instruction is clear?<\/p>\n<\/blockquote>\n\n\n\n<p>We attempted to follow the instruction and observed what happened.<\/p>\n\n\n\n<p>This leads to one of my favorite ideas for evaluating AI-generated workflows:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Do not only review instructions. Execute them.<\/p>\n<\/blockquote>\n\n\n\n<p>If an AI creates installation instructions, run them in a clean container.<\/p>\n\n\n\n<p>If an AI writes API documentation, give the documentation to an agent that has never seen the implementation and ask it to integrate the API.<\/p>\n\n\n\n<p>If an AI creates a migration plan, execute the plan in a disposable environment.<\/p>\n\n\n\n<p>If an AI creates a coding tutorial step, simulate a student performing the step.<\/p>\n\n\n\n<p><strong>Execution is an evaluator.<\/strong><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Build an Automatic Repair Loop<\/h1>\n\n\n\n<p>Once your validators are atomic, repair becomes much easier.<\/p>\n\n\n\n<p>A bad repair prompt looks like:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>There are a few issues with the tutorial.\n\nPlease improve it.\n<\/code><\/pre>\n\n\n\n<p>The agent may rewrite half the tutorial.<\/p>\n\n\n\n<p>It may fix one problem and introduce three new ones.<\/p>\n\n\n\n<p>Instead, give it exact failures:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"failures\": &#91;\n    {\n      \"validator\": \"V006\",\n      \"stepId\": \"iterate-array\",\n      \"error\": \"The instruction does not specify that the loop must expose the current index.\"\n    },\n    {\n      \"validator\": \"V009\",\n      \"stepId\": \"calculate-complement\",\n      \"error\": \"The explanation references seen.has(), which is introduced in a future step.\"\n    }\n  ]\n}\n<\/code><\/pre>\n\n\n\n<p>Then constrain the repair agent:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Fix only the reported failures.\n\nDo not modify passing steps unless a modification is required\nto maintain consistency.\n\nReturn a patch containing:\n- changed step IDs\n- old values\n- new values\n- validator failures addressed\n<\/code><\/pre>\n\n\n\n<p>Then run the entire validation suite again.<\/p>\n\n\n\n<p>The loop becomes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>GENERATE\n   \u2193\nVALIDATE\n   \u2193\nPASS? \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2192 ACCEPT\n   \u2502\n   NO\n   \u2193\nREPAIR\n   \u2193\nVALIDATE\n   \u2193\nPASS? \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2192 ACCEPT\n   \u2502\n   NO\n   \u2193\nREPAIR\n<\/code><\/pre>\n\n\n\n<p>But set a limit.<\/p>\n\n\n\n<p>For example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Generation: attempt 0\nRepair: attempt 1\nRepair: attempt 2\nRepair: attempt 3\nHuman escalation\n<\/code><\/pre>\n\n\n\n<p>Do not let an agent repair forever.<\/p>\n\n\n\n<p>An infinite agent loop is not autonomy.<\/p>\n\n\n\n<p>It is an expensive <code>while (true)<\/code>.<\/p>\n\n\n\n<p>OpenAI has published an example of a broader agent-improvement flywheel where traces, human feedback, and model feedback are converted into reusable evals and then into changes to the surrounding harness. In that example, the harness is explicitly defined as the contract around the model: instructions, tools, routing, output requirements, and validation checks. inition is very close to how I now think about these systems.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">The Secret to Huge Outputs: Never Review the Huge Output as One Thing<\/h1>\n\n\n\n<p>Suppose Claude Code modifies 120 files.<\/p>\n\n\n\n<p>One of the worst review prompts is:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Review all 120 files carefully and tell me whether everything is correct.\n<\/code><\/pre>\n\n\n\n<p>You have recreated the original problem.<\/p>\n\n\n\n<p>The review agent now has almost the same context problem as the generation agent.<\/p>\n\n\n\n<p>Instead, break the artifact into the smallest meaningful evaluation units.<\/p>\n\n\n\n<p>For a repository:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Repository\n   \u2193\nPackage\n   \u2193\nModule\n   \u2193\nFile\n   \u2193\nFunction\n   \u2193\nInvariant\n<\/code><\/pre>\n\n\n\n<p>For AlgoCademy:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Curriculum\n   \u2193\nTrack\n   \u2193\nTutorial\n   \u2193\nStep\n   \u2193\nState transition\n<\/code><\/pre>\n\n\n\n<p>Then validate at several levels.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step-level<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>Does the instruction describe the required code transformation?\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Tutorial-level<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>Does the tutorial introduce concepts progressively?\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Track-level<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>Does this tutorial require concepts that appear later in the track?\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Curriculum-level<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>Are prerequisite dependencies acyclic and complete?\n<\/code><\/pre>\n\n\n\n<p>Most checks should receive the minimum context required for their decision.<\/p>\n\n\n\n<p>This is one reason subagents can be useful in Claude Code. Anthropic&#8217;s current documentation explicitly describes subagents as separate context windows with focused prompts and tool access, and recommends them for isolating high-volume operations so logs, file reads, and test output do not flood the main conversation. er principle is not specific to Claude Code:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Context should be treated as a dependency problem, not an ever-growing chat history.<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Artifacts Are Better Than Agent Memory<\/h1>\n\n\n\n<p>It is tempting to keep one enormous Claude Code or Codex session running.<\/p>\n\n\n\n<p>The agent has all the context.<\/p>\n\n\n\n<p>At first, this feels powerful.<\/p>\n\n\n\n<p>Eventually, the session contains:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>200 file reads\n50 tool calls\n17 failed approaches\n8 temporary scripts\n3 architecture changes\nseveral abandoned assumptions\n<\/code><\/pre>\n\n\n\n<p>Everything may technically be somewhere in the context.<\/p>\n\n\n\n<p>That does not mean the context is useful.<\/p>\n\n\n\n<p>For high-volume workflows, I prefer explicit artifacts.<\/p>\n\n\n\n<p>For example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/tutorials\/two-sum\/spec.json\n\/tutorials\/two-sum\/generated.json\n\/tutorials\/two-sum\/validation.json\n\/tutorials\/two-sum\/repair-1.json\n\/tutorials\/two-sum\/final.json\n<\/code><\/pre>\n\n\n\n<p>Along with shared definitions:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/evals\/tutorial-step-rules.json\n\/concepts\/registry.json\n\/languages\/javascript.json\n\/reference-solutions\/two-sum.js\n<\/code><\/pre>\n\n\n\n<p>The repair agent does not need the generator&#8217;s entire conversation.<\/p>\n\n\n\n<p>It receives:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Input artifact\nValidation failures\nRepair contract\nOutput schema\n<\/code><\/pre>\n\n\n\n<p>That&#8217;s it.<\/p>\n\n\n\n<p>Instead of:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Remember the issue we discussed 45 minutes ago with step 17?<\/p>\n<\/blockquote>\n\n\n\n<p>The workflow says:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Read validation.json.\n\nRepair BLOCKER failures.\n\nWrite repair-1.json.\n<\/code><\/pre>\n\n\n\n<p>The source of truth lives outside the model.<\/p>\n\n\n\n<p>The model is a worker operating on artifacts.<\/p>\n\n\n\n<p>That is a far more scalable architecture.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Claude Code Should Not Be the Human Workflow Hidden in a Terminal<\/h1>\n\n\n\n<p>Claude Code can already support pieces of this architecture.<\/p>\n\n\n\n<p>Its documentation describes non-interactive execution for CI and batch processing. Its hook system supports automatic lifecycle actions, including command-based checks and agent-based verification. Its Agent SDK exposes the same general tools, agent loop, and context-management model programmatically in Python and TypeScript. e is still an important distinction.<\/p>\n\n\n\n<p>Imagine I use Claude Code like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Build 20 tutorials.\n\nNow inspect them.\n\nRun the tests.\n\nCheck the instructions.\n\nFix the problems.\n\nReview them again.\n<\/code><\/pre>\n\n\n\n<p>Claude Code is doing a lot of work.<\/p>\n\n\n\n<p>But the actual workflow still lives in my head.<\/p>\n\n\n\n<p><strong>I am the harness.<\/strong><\/p>\n\n\n\n<p>I decide:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>when to test\nwhat to inspect\nwhat looks suspicious\nwhen to ask for another review\nwhen to retry\nwhen the result is good enough\n<\/code><\/pre>\n\n\n\n<p>That works for interactive development.<\/p>\n\n\n\n<p>It does not scale to thousands of artifacts.<\/p>\n\n\n\n<p>The decisions need to move into software.<\/p>\n\n\n\n<p>Conceptually:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const tutorial = await generateTutorial(spec);\n\nconst deterministicResults =\n    await runDeterministicValidators(tutorial);\n\nif (deterministicResults.hasBlocker) {\n    return runRepairLoop(tutorial, deterministicResults);\n}\n\nconst semanticResults =\n    await runSemanticEvaluators(tutorial);\n\nconst simulationResults =\n    await simulateStudent(tutorial);\n\nconst risk = calculateRisk({\n    deterministicResults,\n    semanticResults,\n    simulationResults\n});\n\nif (risk &gt;= HUMAN_REVIEW_THRESHOLD) {\n    return sendToHumanReview(tutorial);\n}\n\nreturn publishTutorial(tutorial);\n<\/code><\/pre>\n\n\n\n<p>Claude Code, Codex, or another agent may do some of the work.<\/p>\n\n\n\n<p>But the workflow exists outside the conversation.<\/p>\n\n\n\n<p>That is the difference between:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>I have an AI coding assistant.<\/p>\n<\/blockquote>\n\n\n\n<p>and:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>I have an AI production system.<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Do Not Ask &#8220;Did It Pass?&#8221; Ask &#8220;How Likely Are We to Have Missed Something?&#8221;<\/h1>\n\n\n\n<p>Eventually, every artifact may have dozens of validation signals.<\/p>\n\n\n\n<p>Some are hard requirements.<\/p>\n\n\n\n<p>For example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Schema valid                         REQUIRED\nFinal code passes tests              REQUIRED\nNo broken dependency references      REQUIRED\nRequired tutorial states exist        REQUIRED\n<\/code><\/pre>\n\n\n\n<p>Others are probabilistic:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Instruction clarity                  0.94\nPedagogical progression              0.91\nBeginner solvability                 0.87\nFuture-step leakage                  0.03\n<\/code><\/pre>\n\n\n\n<p>I would be careful about making an LLM judge a hard blocker before calibrating it.<\/p>\n\n\n\n<p>For example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>LLM says instruction is unclear\n        \u2193\nALWAYS REJECT\n<\/code><\/pre>\n\n\n\n<p>may produce too many false positives.<\/p>\n\n\n\n<p>Instead, the release decision can combine signals:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Deterministic failures\nSemantic scores\nEvaluator disagreement\nNumber of repair attempts\nNovel concepts\nTutorial difficulty\nHistorical defect rate for this template\n<\/code><\/pre>\n\n\n\n<p>Imagine:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Risk &lt; 0.10\n    Auto approve\n\nRisk 0.10\u20130.30\n    Run extra evaluation\n\nRisk &gt; 0.30\n    Human review\n<\/code><\/pre>\n\n\n\n<p>Those numbers are only examples.<\/p>\n\n\n\n<p>The thresholds need to be calibrated using real AlgoCademy tutorials and real defects.<\/p>\n\n\n\n<p>The architecture is the important part.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">You Still Need Humans, Just in a Different Place<\/h1>\n\n\n\n<p>I do not think the goal should be zero human involvement.<\/p>\n\n\n\n<p>The goal should be to move human effort from:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Review every tutorial.\n<\/code><\/pre>\n\n\n\n<p>to:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Review the evaluation system.\n<\/code><\/pre>\n\n\n\n<p>Humans should inspect:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Validator disagreements<\/li>\n\n\n\n<li>New tutorial formats<\/li>\n\n\n\n<li>New programming languages<\/li>\n\n\n\n<li>New learning mechanics<\/li>\n\n\n\n<li>High-risk artifacts<\/li>\n\n\n\n<li>Random samples of auto-approved content<\/li>\n\n\n\n<li>Student-reported problems<\/li>\n<\/ul>\n\n\n\n<p>Imagine the system publishes 1,000 tutorials.<\/p>\n\n\n\n<p>You manually audit 50.<\/p>\n\n\n\n<p>You discover two bad tutorials.<\/p>\n\n\n\n<p>The least valuable response is:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Fix those two tutorials.<\/p>\n<\/blockquote>\n\n\n\n<p>Of course you should fix them.<\/p>\n\n\n\n<p>But the more important question is:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Why did the harness approve them?<\/p>\n<\/blockquote>\n\n\n\n<p>Suppose the first problem is:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>The instruction says &#8220;store the previous value,&#8221; but there are two possible values it could mean.<\/p>\n<\/blockquote>\n\n\n\n<p>Great.<\/p>\n\n\n\n<p>Create:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>V016: Ambiguous referent detection\n<\/code><\/pre>\n\n\n\n<p>The second problem is:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>The tutorial uses modulo before modulo has been introduced.<\/p>\n<\/blockquote>\n\n\n\n<p>Create:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>V017: Concept prerequisite violation\n<\/code><\/pre>\n\n\n\n<p>Add both failures to your evaluation dataset.<\/p>\n\n\n\n<p>Run the validators against every future tutorial.<\/p>\n\n\n\n<p>Anthropic describes evals as a way to avoid purely reactive loops where problems are discovered only in production and individual fixes can create new regressions elsewhere. there is an even simpler way to remember this:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Every escaped AI mistake is a missing regression test.<\/p>\n<\/blockquote>\n\n\n\n<p>Do not waste human-discovered failures.<\/p>\n\n\n\n<p>Turn them into evals.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Build a Gold Dataset Before You Trust the Harness<\/h1>\n\n\n\n<p>Before automatically publishing thousands of tutorials, I would create a smaller collection of extremely well-reviewed tutorials.<\/p>\n\n\n\n<p>For example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>50 beginner tutorials\n30 intermediate tutorials\n20 advanced tutorials\n<\/code><\/pre>\n\n\n\n<p>The exact numbers do not matter.<\/p>\n\n\n\n<p>The quality and variety do.<\/p>\n\n\n\n<p>Then intentionally create broken versions.<\/p>\n\n\n\n<p>Examples:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Ambiguous instruction\nFuture-step leakage\nWrong variable name\nSkipped learning step\nOversized step\nIncorrect loop bound\nInstruction\/code mismatch\nBroken state chain\nUnknown concept dependency\nIncorrect complexity explanation\nUnnecessary code modification\n<\/code><\/pre>\n\n\n\n<p>Now you have:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Known good examples\nKnown bad examples\nKnown defect categories\n<\/code><\/pre>\n\n\n\n<p>Run your validators.<\/p>\n\n\n\n<p>Measure:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>True positives\nFalse positives\nFalse negatives\n<\/code><\/pre>\n\n\n\n<p>The most dangerous number is usually:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>False negatives\n<\/code><\/pre>\n\n\n\n<p>These are known bad tutorials your harness approves.<\/p>\n\n\n\n<p>Suppose you have 500 seeded defects.<\/p>\n\n\n\n<p>Your system detects 490.<\/p>\n\n\n\n<p>Ten escape.<\/p>\n\n\n\n<p>Now you have ten concrete failures to study.<\/p>\n\n\n\n<p>That is much more useful than saying:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Claude seems pretty good at reviewing tutorials.<\/p>\n<\/blockquote>\n\n\n\n<p>Every time you change something, rerun the dataset.<\/p>\n\n\n\n<p>Changed the generator prompt?<\/p>\n\n\n\n<p>Run evals.<\/p>\n\n\n\n<p>Changed the model?<\/p>\n\n\n\n<p>Run evals.<\/p>\n\n\n\n<p>Added a repair agent?<\/p>\n\n\n\n<p>Run evals.<\/p>\n\n\n\n<p>Changed the curriculum schema?<\/p>\n\n\n\n<p>Run evals.<\/p>\n\n\n\n<p>Changed the semantic judge?<\/p>\n\n\n\n<p>Run evals.<\/p>\n\n\n\n<p>Your AI workflow now has regression tests.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">What I Would Actually Build for AlgoCademy<\/h1>\n\n\n\n<p>If I were designing the tutorial-generation workflow from scratch today, I would build this.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. Tutorial Specification<\/h2>\n\n\n\n<p>Before generation:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"problem\": \"two-sum\",\n  \"language\": \"javascript\",\n  \"studentLevel\": \"beginner\",\n  \"knownConcepts\": &#91;\n    \"variables\",\n    \"arrays\",\n    \"for-loops\"\n  ],\n  \"conceptsToTeach\": &#91;\n    \"hash-maps\"\n  ],\n  \"targetSteps\": {\n    \"min\": 7,\n    \"max\": 12\n  },\n  \"referenceSolution\": \"...\"\n}\n<\/code><\/pre>\n\n\n\n<p>The generator receives a contract.<\/p>\n\n\n\n<p>It does not invent the entire curriculum.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. Structured Generation<\/h2>\n\n\n\n<p>The agent returns strict structured data.<\/p>\n\n\n\n<p>No parsing arbitrary Markdown.<\/p>\n\n\n\n<p>No guessing where an explanation ends and code begins.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. Deterministic Validation<\/h2>\n\n\n\n<p>Run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Schema validation\nCode parsing where required\nCode execution\nHidden tests\nDependency checks\nState-chain validation\nAST or syntax-tree analysis\nSymbol validation\nConcept-registry validation\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">4. Transformation Contracts<\/h2>\n\n\n\n<p>For every tutorial step, define the required change.<\/p>\n\n\n\n<p>For example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"stepId\": \"create-index-loop\",\n  \"requiredProperties\": &#91;\n    \"LOOP_ADDED\",\n    \"TRAVERSES_NUMS\",\n    \"CURRENT_INDEX_AVAILABLE\"\n  ],\n  \"forbiddenProperties\": &#91;\n    \"MAP_LOOKUP_ADDED\",\n    \"RETURN_ADDED\"\n  ]\n}\n<\/code><\/pre>\n\n\n\n<p>Validate properties instead of exact code equality.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">5. Semantic Evaluators<\/h2>\n\n\n\n<p>Use narrow evaluators for:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Instruction ambiguity\nInstruction\/transformation consistency\nPedagogical step size\nConcept difficulty\nFuture-step leakage\nExplanation clarity\n<\/code><\/pre>\n\n\n\n<p>Require structured evidence.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">6. Simulated Student<\/h2>\n\n\n\n<p>Give another agent:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Student knowledge\nCurrent code\nInstruction\n<\/code><\/pre>\n\n\n\n<p>Ask it to perform the step.<\/p>\n\n\n\n<p>Check its result against the transformation contract.<\/p>\n\n\n\n<p>Investigate reasonable alternative interpretations.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">7. Repair Loop<\/h2>\n\n\n\n<p>Give the repair agent exact validator failures.<\/p>\n\n\n\n<p>Require a patch.<\/p>\n\n\n\n<p>Re-run the complete validator suite.<\/p>\n\n\n\n<p>Limit the number of repair attempts.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">8. Risk Routing<\/h2>\n\n\n\n<p>Auto-approve low-risk tutorials.<\/p>\n\n\n\n<p>Run additional checks on uncertain tutorials.<\/p>\n\n\n\n<p>Send high-risk tutorials to humans.<\/p>\n\n\n\n<p>Randomly audit auto-approved content.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">9. Evaluation Flywheel<\/h2>\n\n\n\n<p>Every student-reported or human-discovered defect becomes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>A regression example\n\nand possibly:\n\nA deterministic validator\nA semantic rubric\nA simulated-student scenario\nA new adversarial test\n<\/code><\/pre>\n\n\n\n<p>Over time, the target is:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Human review rate \u2193\n\nValidator coverage \u2191\n\nEscaped defect rate \u2193\n<\/code><\/pre>\n\n\n\n<p>That is what scalable AI generation should look like.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">The Metrics I Would Track<\/h1>\n\n\n\n<p>I would not use:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Number of tutorials generated\n<\/code><\/pre>\n\n\n\n<p>as my primary success metric.<\/p>\n\n\n\n<p>AI can generate enormous amounts of content.<\/p>\n\n\n\n<p>Volume is no longer the hard problem.<\/p>\n\n\n\n<p>I would track:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Auto-Approval Rate<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>automatically approved tutorials\n\/\ngenerated tutorials\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Human Escalation Rate<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>tutorials requiring human review\n\/\ngenerated tutorials\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Escaped Defect Rate<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>bad published tutorials\n\/\npublished tutorials\n<\/code><\/pre>\n\n\n\n<p>This may be the most important quality metric.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Repair Success Rate<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>automatically repaired tutorials\n\/\ntutorials that initially failed\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Average Repair Iterations<\/h3>\n\n\n\n<p>How many repair loops are needed before acceptance?<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Evaluator Disagreement Rate<\/h3>\n\n\n\n<p>How frequently do semantic evaluators disagree?<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">False-Negative Rate<\/h3>\n\n\n\n<p>How many known defects in the gold dataset does the harness miss?<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Student-Reported Defect Rate<\/h3>\n\n\n\n<p>How frequently do real students find problems the harness failed to detect?<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Defect-to-Eval Conversion Rate<\/h3>\n\n\n\n<p>This is a metric I would seriously consider.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>human-discovered defect categories converted into reusable evals\n\/\nunique defect categories discovered\n<\/code><\/pre>\n\n\n\n<p>If the same class of mistake reaches a human five times, the evaluation system is not learning.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">So, Is Fully Autonomous AI Content Generation Possible?<\/h1>\n\n\n\n<p>It depends on what we mean by autonomous.<\/p>\n\n\n\n<p>If we mean:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Give Claude Code one prompt and let it generate 10,000 tutorials without external validation.<\/p>\n<\/blockquote>\n\n\n\n<p>I would not trust that system.<\/p>\n\n\n\n<p>If we mean:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Agents generate structured artifacts inside a constrained workflow with deterministic validation, semantic evals, execution-based tests, automatic repair, risk-based escalation, and statistical human auditing.<\/p>\n<\/blockquote>\n\n\n\n<p>Yes.<\/p>\n\n\n\n<p>I think that can become highly autonomous.<\/p>\n\n\n\n<p>And there is an interesting paradox here.<\/p>\n\n\n\n<p>The way to create more autonomous AI systems is to <strong>trust the AI less<\/strong>.<\/p>\n\n\n\n<p>Assume the generator will eventually make a mistake.<\/p>\n\n\n\n<p>Assume the AI reviewer will occasionally miss it.<\/p>\n\n\n\n<p>Assume your prompt has blind spots.<\/p>\n\n\n\n<p>Assume a valid solution exists that your original evaluator did not anticipate.<\/p>\n\n\n\n<p>Then build independent mechanisms for finding those failures.<\/p>\n\n\n\n<p>This is how reliable engineering has always worked.<\/p>\n\n\n\n<p>A reliable distributed system is not reliable because no server ever crashes.<\/p>\n\n\n\n<p>It is reliable because the architecture expects servers to crash.<\/p>\n\n\n\n<p>AI systems will probably work the same way.<\/p>\n\n\n\n<p><strong>Do not try to build an agent that never makes mistakes.<\/strong><\/p>\n\n\n\n<p><strong>Build a harness that expects mistakes, detects them, repairs what it can, and knows when to ask a human.<\/strong><\/p>\n\n\n\n<p>That, to me, is the difference between using an AI coding assistant and building an AI-native production system.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>AI coding agents are becoming very good at producing large amounts of code and content. When an agent changes 20&#8230;<\/p>\n","protected":false},"author":1,"featured_media":8663,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[23],"tags":[],"class_list":["post-8654","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-problem-solving"],"_links":{"self":[{"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/posts\/8654"}],"collection":[{"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/comments?post=8654"}],"version-history":[{"count":1,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/posts\/8654\/revisions"}],"predecessor-version":[{"id":8660,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/posts\/8654\/revisions\/8660"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/media\/8663"}],"wp:attachment":[{"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/media?parent=8654"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/categories?post=8654"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/tags?post=8654"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}