<?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: shizhe Lim</title>
    <description>The latest articles on DEV Community by shizhe Lim (@shizhe_lim_61b5948cb8081d).</description>
    <link>https://dev.to/shizhe_lim_61b5948cb8081d</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4026882%2F6222e6cb-5003-45c5-bd0f-fbdd9d91c05c.png</url>
      <title>DEV Community: shizhe Lim</title>
      <link>https://dev.to/shizhe_lim_61b5948cb8081d</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shizhe_lim_61b5948cb8081d"/>
    <language>en</language>
    <item>
      <title>Stop Asking One Model to Do Everything: A Four-Layer Pattern for AI Workflows</title>
      <dc:creator>shizhe Lim</dc:creator>
      <pubDate>Fri, 23 Oct 2026 09:48:31 +0000</pubDate>
      <link>https://dev.to/shizhe_lim_61b5948cb8081d/stop-asking-one-model-to-do-everything-a-four-layer-pattern-for-ai-workflows-3cjh</link>
      <guid>https://dev.to/shizhe_lim_61b5948cb8081d/stop-asking-one-model-to-do-everything-a-four-layer-pattern-for-ai-workflows-3cjh</guid>
      <description>&lt;p&gt;OpenAI’s Decisions API became generally available this week. The interesting part is not simply that there is another API endpoint. It is the architectural distinction the release makes explicit:&lt;/p&gt;

&lt;p&gt;Some AI tasks need generation. Many only need a bounded decision.&lt;/p&gt;

&lt;p&gt;Asking the same general-purpose model to classify a request, select an action, draft a response, and approve the result may be convenient during prototyping. In production, however, those jobs have different requirements and failure modes.&lt;/p&gt;

&lt;p&gt;A more testable AI workflow can be divided into four layers.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Deterministic rules for hard constraints
&lt;/h2&gt;

&lt;p&gt;Some decisions should not depend on probabilistic inference.&lt;/p&gt;

&lt;p&gt;Permissions, contractual restrictions, data-residency requirements, spending limits, and known security policies belong in normal application logic. A model can help identify relevant context, but it should not silently override a hard rule.&lt;/p&gt;

&lt;p&gt;If a condition must always produce the same result, start with code.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Bounded models for repetitive judgments
&lt;/h2&gt;

&lt;p&gt;Classification, prioritization, routing, and scoring are different from open-ended generation.&lt;/p&gt;

&lt;p&gt;A bounded decision layer receives evidence and returns a constrained result: a probability, one choice from a known set, or a score against a rubric. This makes the output easier to validate and easier for the rest of the application to consume.&lt;/p&gt;

&lt;p&gt;Typical examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Routing a support request to the right queue&lt;/li&gt;
&lt;li&gt;Scoring whether an agent action needs review&lt;/li&gt;
&lt;li&gt;Choosing which model should handle the next step&lt;/li&gt;
&lt;li&gt;Prioritizing documents for human inspection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This layer still needs evaluation. A probability is not automatically well calibrated, and a confidence threshold should be derived from representative application data rather than selected arbitrarily.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Generative models for open-ended work
&lt;/h2&gt;

&lt;p&gt;Use generative models where the output space is genuinely open: drafting an explanation, synthesizing several documents, writing code, or planning a multi-step task.&lt;/p&gt;

&lt;p&gt;The goal is not to avoid larger models. It is to reserve them for work where their broader capabilities provide value.&lt;/p&gt;

&lt;p&gt;A simplified workflow might look 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;if request violates a hard policy:
    block or escalate

decision = classify_and_route(request)

if decision is low-confidence or high-impact:
    send to human review
else:
    use the selected model and workflow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Human review for consequential uncertainty
&lt;/h2&gt;

&lt;p&gt;A human-review path should be part of the architecture, not an emergency patch added after deployment.&lt;/p&gt;

&lt;p&gt;Review is especially important when an action is irreversible, affects another person, accesses sensitive data, or falls outside the examples used during evaluation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Evaluate the whole route
&lt;/h2&gt;

&lt;p&gt;When testing this architecture, do not measure only raw model accuracy. Track:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Decision calibration&lt;/li&gt;
&lt;li&gt;End-to-end latency&lt;/li&gt;
&lt;li&gt;Cost per successfully completed workflow&lt;/li&gt;
&lt;li&gt;Escalation and fallback rates&lt;/li&gt;
&lt;li&gt;Performance drift as real inputs change&lt;/li&gt;
&lt;li&gt;Whether each decision can be audited&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The emerging lesson is that “Which model should we use?” is becoming the wrong first question.&lt;/p&gt;

&lt;p&gt;A better question is: &lt;strong&gt;What kind of inference does each step actually require?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://openai.com/index/decisions-api/" rel="noopener noreferrer"&gt;OpenAI announcement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.openai.com/api/docs/guides/decisions" rel="noopener noreferrer"&gt;Decisions API documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;AI assistance disclosure: This article was drafted with AI assistance. The author reviewed and edited the final version and verified its factual claims against the linked primary sources.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>api</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>The Missing Component in Agentic Software Engineering: A Machine-Checkable Oracle</title>
      <dc:creator>shizhe Lim</dc:creator>
      <pubDate>Fri, 16 Oct 2026 06:23:05 +0000</pubDate>
      <link>https://dev.to/shizhe_lim_61b5948cb8081d/the-missing-component-in-agentic-software-engineering-a-machine-checkable-oracle-4m8j</link>
      <guid>https://dev.to/shizhe_lim_61b5948cb8081d/the-missing-component-in-agentic-software-engineering-a-machine-checkable-oracle-4m8j</guid>
      <description>&lt;p&gt;A recent software-engineering experiment reportedly consumed more than 500 billion tokens over three months.&lt;/p&gt;

&lt;p&gt;That number attracted attention, but it was not the most important result.&lt;/p&gt;

&lt;p&gt;The project used a fleet of AI coding agents to reconstruct a large application in C++. After the first month, the output looked promising: the code was readable, the application launched, and visible features worked.&lt;/p&gt;

&lt;p&gt;However, much of the implementation was semantically wrong.&lt;/p&gt;

&lt;p&gt;Functions used incorrect signatures. Data structures were misinterpreted. Logic was invented or removed. Some simple operations were replaced with unnecessarily expensive abstractions.&lt;/p&gt;

&lt;p&gt;The agents were producing activity, but the team had no reliable definition of correctness.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why a Reviewer Agent Was Not Enough
&lt;/h2&gt;

&lt;p&gt;The initial workflow included worker agents and a reviewer agent.&lt;/p&gt;

&lt;p&gt;That sounds reasonable, but both sides were operating from the same incomplete description of the goal. When a worker explained why it had made a change, the reviewer could accept that explanation instead of independently verifying the behavior.&lt;/p&gt;

&lt;p&gt;This exposes a common weakness in multi-agent systems:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Adding another model does not automatically create independent evidence.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A reviewer can find obvious defects, but it cannot consistently enforce requirements that have never been translated into objective checks.&lt;/p&gt;

&lt;h2&gt;
  
  
  The System Changed When It Gained an Oracle
&lt;/h2&gt;

&lt;p&gt;The team eventually introduced an automated verification harness.&lt;/p&gt;

&lt;p&gt;Each reconstructed function was compared with the corresponding reference output. The result was deliberately simple: PASS or FAIL.&lt;/p&gt;

&lt;p&gt;That feedback loop made the workflow much more reliable:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;An agent produced an implementation.&lt;/li&gt;
&lt;li&gt;The verifier checked it independently.&lt;/li&gt;
&lt;li&gt;Failed work returned to the agent with concrete feedback.&lt;/li&gt;
&lt;li&gt;Passing work was recorded and checked again in CI.&lt;/li&gt;
&lt;li&gt;The verification mechanism itself was protected from modification.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The important component was not another prompt. It was an oracle: an external system capable of deciding whether an output satisfied the requirement.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Other Agent Workflows Can Learn
&lt;/h2&gt;

&lt;p&gt;Most projects cannot compare compiled functions byte for byte, but the same pattern applies elsewhere.&lt;/p&gt;

&lt;h3&gt;
  
  
  For coding agents
&lt;/h3&gt;

&lt;p&gt;Use tests, static analysis, type checks, security scans, performance budgets, and reproducible builds.&lt;/p&gt;

&lt;h3&gt;
  
  
  For data agents
&lt;/h3&gt;

&lt;p&gt;Validate schemas, row counts, invariants, allowed ranges, lineage, and reconciliation totals.&lt;/p&gt;

&lt;h3&gt;
  
  
  For customer-support agents
&lt;/h3&gt;

&lt;p&gt;Check policy compliance, required fields, escalation conditions, tool permissions, and whether cited account data actually exists.&lt;/p&gt;

&lt;h3&gt;
  
  
  For research agents
&lt;/h3&gt;

&lt;p&gt;Require source availability, citation support, date checks, contradiction detection, and explicit reporting of missing evidence.&lt;/p&gt;

&lt;h3&gt;
  
  
  For workflow agents
&lt;/h3&gt;

&lt;p&gt;Validate state transitions and permissions before allowing irreversible actions.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Minimal Agent Verification Loop
&lt;/h2&gt;

&lt;p&gt;A production workflow can start with a simple structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;define acceptance criteria
set a cost and retry budget

while budget remains:
    generate or revise the result
    run an independent verifier

    if verification passes:
        accept the result
        record the evidence
        stop

    return structured failure feedback

escalate to a human or fail safely
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The verifier should ideally be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Independent from the generating agent&lt;/li&gt;
&lt;li&gt;Deterministic where possible&lt;/li&gt;
&lt;li&gt;Protected from modification&lt;/li&gt;
&lt;li&gt;Easy to audit&lt;/li&gt;
&lt;li&gt;Able to fail closed&lt;/li&gt;
&lt;li&gt;Connected to cost and retry limits&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Measure Verified Outcomes, Not Agent Activity
&lt;/h2&gt;

&lt;p&gt;Token usage, tool calls, generated files, and completed subtasks can all look like progress.&lt;/p&gt;

&lt;p&gt;None of them proves that the result is correct.&lt;/p&gt;

&lt;p&gt;A more useful operational metric is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;total workflow cost / number of verified successful outcomes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This captures an important tradeoff. A cheaper model is not cheaper if it generates more failures, consumes more retries, or creates additional human review work.&lt;/p&gt;

&lt;p&gt;At the same time, a strong verification harness may make less expensive models viable because they receive precise feedback.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bigger Lesson
&lt;/h2&gt;

&lt;p&gt;Model capability still matters, but production Agent systems need more than intelligence.&lt;/p&gt;

&lt;p&gt;They need boundaries, evidence, protected evaluation, retry controls, and a clear path for human escalation.&lt;/p&gt;

&lt;p&gt;Before scaling the number of agents, define the mechanism that tells them—and your team—when the work is actually correct.&lt;/p&gt;

&lt;p&gt;What machine-checkable oracle could you add to your current AI workflow?&lt;/p&gt;




&lt;p&gt;Sources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maurice Heumann, “500+ Billion Tokens Later: Letting AI Agents Decompile a First-Person Shooter”&lt;/li&gt;
&lt;li&gt;Tom’s Hardware coverage published October 12, 2026&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI disclosure: This article was prepared with AI assistance. Before publication, I reviewed the cited material and take responsibility for the final text.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>testing</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Rules Engine vs. Decision Model vs. General LLM: A Practical Routing Framework</title>
      <dc:creator>shizhe Lim</dc:creator>
      <pubDate>Wed, 07 Oct 2026 09:14:45 +0000</pubDate>
      <link>https://dev.to/shizhe_lim_61b5948cb8081d/rules-engine-vs-decision-model-vs-general-llm-a-practical-routing-framework-50h5</link>
      <guid>https://dev.to/shizhe_lim_61b5948cb8081d/rules-engine-vs-decision-model-vs-general-llm-a-practical-routing-framework-50h5</guid>
      <description>&lt;p&gt;Choosing an AI model is becoming less important than deciding when each model—or non-model system—should be used.&lt;/p&gt;

&lt;p&gt;OpenAI’s release of the Decisions API is one recent signal of this shift. Instead of generating an open-ended response, a decision endpoint can return structured predicates, choices, or scores.&lt;/p&gt;

&lt;p&gt;But a dedicated decision model should not automatically replace rules engines or general-purpose LLMs. Each belongs in a different part of the stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Use rules when the decision is deterministic
&lt;/h2&gt;

&lt;p&gt;A rules engine is usually the right choice when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The policy is explicit and stable.&lt;/li&gt;
&lt;li&gt;The inputs are already structured.&lt;/li&gt;
&lt;li&gt;The result must be fully explainable.&lt;/li&gt;
&lt;li&gt;A wrong decision creates compliance or financial risk.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Examples include permission checks, spending limits, required fields, and geographic restrictions.&lt;/p&gt;

&lt;p&gt;Adding a model to these decisions may increase latency and introduce uncertainty without creating additional value.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Use a decision model when the input is ambiguous but the output is constrained
&lt;/h2&gt;

&lt;p&gt;A decision model fits tasks such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Intent classification&lt;/li&gt;
&lt;li&gt;Priority scoring&lt;/li&gt;
&lt;li&gt;Tool selection&lt;/li&gt;
&lt;li&gt;Model routing&lt;/li&gt;
&lt;li&gt;Moderation triage&lt;/li&gt;
&lt;li&gt;Mapping unstructured requests to a fixed set of actions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The input may be natural language or an image, but the output remains controlled.&lt;/p&gt;

&lt;p&gt;The important production question is not simply whether the model returned a valid label. Teams also need to define:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A minimum confidence threshold&lt;/li&gt;
&lt;li&gt;A fallback for low-confidence results&lt;/li&gt;
&lt;li&gt;An evaluation dataset&lt;/li&gt;
&lt;li&gt;Version and prompt tracking&lt;/li&gt;
&lt;li&gt;Logging for later review&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Use a general LLM when the task requires open-ended reasoning
&lt;/h2&gt;

&lt;p&gt;A general-purpose model is more appropriate when the system must:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compare incomplete evidence&lt;/li&gt;
&lt;li&gt;Produce a detailed explanation&lt;/li&gt;
&lt;li&gt;Plan multiple steps&lt;/li&gt;
&lt;li&gt;Resolve an unfamiliar situation&lt;/li&gt;
&lt;li&gt;Generate original content&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These tasks benefit from broader reasoning, but they also tend to cost more and take longer than narrow classification or scoring.&lt;/p&gt;

&lt;h2&gt;
  
  
  A simple hybrid router
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def route(request):
    if matches_deterministic_policy(request):
        return run_rules(request)

    decision = classify_request(request)

    if decision.confidence &amp;lt; 0.80:
        return run_reasoning_model(request)

    if decision.action_is_irreversible:
        return request_human_approval(decision)

    result = execute(decision)
    return verify_outcome(result)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The exact threshold should come from evaluation data, not from copying 0.80 into production. Different actions can also use different thresholds.&lt;/p&gt;

&lt;p&gt;A support-ticket label might tolerate a lower threshold than a payment, account deletion, or infrastructure change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Routing is only half of the system
&lt;/h2&gt;

&lt;p&gt;A router can choose the correct model or tool and the workflow can still fail.&lt;/p&gt;

&lt;p&gt;Production systems should verify the resulting state:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Did the selected tool actually run?&lt;/li&gt;
&lt;li&gt;Did the database reach the required state?&lt;/li&gt;
&lt;li&gt;Were unintended side effects created?&lt;/li&gt;
&lt;li&gt;Should the workflow retry, escalate, or stop?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A successful API response is not necessarily a successful business outcome.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical selection rule
&lt;/h2&gt;

&lt;p&gt;Use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rules&lt;/strong&gt; for known policies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decision models&lt;/strong&gt; for constrained choices over ambiguous inputs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;General LLMs&lt;/strong&gt; for open-ended reasoning&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Humans&lt;/strong&gt; for high-impact or irreversible decisions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Outcome checks&lt;/strong&gt; after every state-changing action&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is not to find one model that handles everything. It is to build a system that assigns each request to the most appropriate decision mechanism—and can explain, evaluate, and reverse that decision when necessary.&lt;/p&gt;

&lt;p&gt;How are you implementing routing today? Are you using deterministic rules, an LLM classifier, a specialized decision model, or a hybrid system?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;AI disclosure: This article was prepared with AI assistance and reviewed by the author for technical accuracy and final judgment.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>programming</category>
      <category>llm</category>
    </item>
    <item>
      <title>Always-On AI Agents Need a Permission Architecture, Not Just Better Prompts</title>
      <dc:creator>shizhe Lim</dc:creator>
      <pubDate>Tue, 06 Oct 2026 08:56:29 +0000</pubDate>
      <link>https://dev.to/shizhe_lim_61b5948cb8081d/always-on-ai-agents-need-a-permission-architecture-not-just-better-prompts-5dea</link>
      <guid>https://dev.to/shizhe_lim_61b5948cb8081d/always-on-ai-agents-need-a-permission-architecture-not-just-better-prompts-5dea</guid>
      <description>&lt;p&gt;AI agents are moving from request-response tools to systems that can keep working after the user leaves.&lt;/p&gt;

&lt;p&gt;That shift changes the security model.&lt;/p&gt;

&lt;p&gt;A chatbot produces text for a person to review. An agent may read email, edit files, call an API, deploy code or initiate a transaction. Once a model can take actions, prompt quality is no longer enough.&lt;/p&gt;

&lt;p&gt;The system needs a permission architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prompts are not access control
&lt;/h2&gt;

&lt;p&gt;Instructions such as “never send an email without permission” are useful, but they are not a reliable security boundary.&lt;/p&gt;

&lt;p&gt;The model is still interpreting language. It may encounter ambiguous instructions, untrusted content or conflicting context. A privileged action should therefore be enforced outside the model by a deterministic execution layer.&lt;/p&gt;

&lt;p&gt;The model may propose an action. The surrounding system should decide whether that action is allowed.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Give each agent its own identity
&lt;/h2&gt;

&lt;p&gt;Avoid letting multiple agents share one broad service account.&lt;/p&gt;

&lt;p&gt;A separate identity makes it possible to answer basic operational questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which agent requested the action?&lt;/li&gt;
&lt;li&gt;Which user or workflow initiated it?&lt;/li&gt;
&lt;li&gt;What resources was it allowed to access?&lt;/li&gt;
&lt;li&gt;Can its access be revoked without affecting other agents?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agent identity should be treated like workload identity, not like a convenient shared API key.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Separate reading from writing
&lt;/h2&gt;

&lt;p&gt;Reading a calendar and deleting an event are not equivalent permissions.&lt;/p&gt;

&lt;p&gt;Tool definitions should separate capabilities according to their consequences. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;email.read&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;email.draft&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;email.send&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;email.delete&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An agent may receive read access by default while send or delete operations remain behind an approval step.&lt;/p&gt;

&lt;p&gt;This also makes logs and security reviews much easier to understand.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Gate actions by consequence
&lt;/h2&gt;

&lt;p&gt;Not every tool call needs human approval. Requiring confirmation for everything removes much of the value of automation.&lt;/p&gt;

&lt;p&gt;Approval should be based on impact.&lt;/p&gt;

&lt;p&gt;A useful starting point is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reversible, internal action: allow automatically&lt;/li&gt;
&lt;li&gt;External but recoverable action: allow with notification&lt;/li&gt;
&lt;li&gt;Irreversible or high-impact action: require approval&lt;/li&gt;
&lt;li&gt;Action outside the agent’s defined scope: deny&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The policy should live in code or configuration, not only in the system prompt.&lt;/p&gt;

&lt;p&gt;An illustrative policy could look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;send_external_email&lt;/span&gt;
&lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deny&lt;/span&gt;
&lt;span class="na"&gt;requires&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;scoped_agent_identity&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;human_approval&lt;/span&gt;
&lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;initiating_user&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;destination&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;proposed_content&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;policy_decision&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Keep an audit trail that explains actions
&lt;/h2&gt;

&lt;p&gt;Logging only the final API request is not enough.&lt;/p&gt;

&lt;p&gt;A useful audit record should connect:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The initiating user or scheduled workflow&lt;/li&gt;
&lt;li&gt;The agent identity&lt;/li&gt;
&lt;li&gt;The requested objective&lt;/li&gt;
&lt;li&gt;The tool and resource accessed&lt;/li&gt;
&lt;li&gt;The policy decision&lt;/li&gt;
&lt;li&gt;The resulting state change&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The goal is not to store every hidden reasoning token. It is to preserve enough evidence to reconstruct what the system attempted, what was authorized and what changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Design revocation and rollback before launch
&lt;/h2&gt;

&lt;p&gt;Every long-running agent needs a clear stop mechanism.&lt;/p&gt;

&lt;p&gt;Teams should be able to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Revoke the agent’s credentials&lt;/li&gt;
&lt;li&gt;Disable an individual tool&lt;/li&gt;
&lt;li&gt;Cancel active work&lt;/li&gt;
&lt;li&gt;Restore affected data where possible&lt;/li&gt;
&lt;li&gt;Prevent retries after a failed or denied action&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A kill switch without tested recovery procedures only solves half of the problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Avoid coupling permission policy to one model
&lt;/h2&gt;

&lt;p&gt;Model providers and model versions change. Permissions should not have to be redesigned every time the underlying model changes.&lt;/p&gt;

&lt;p&gt;Keep these layers separate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Model selection&lt;/li&gt;
&lt;li&gt;Business workflow&lt;/li&gt;
&lt;li&gt;Tool execution&lt;/li&gt;
&lt;li&gt;Permission policy&lt;/li&gt;
&lt;li&gt;Audit and recovery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This separation also makes it easier to evaluate another model without accidentally changing the agent’s authority.&lt;/p&gt;

&lt;h2&gt;
  
  
  A pre-launch checklist
&lt;/h2&gt;

&lt;p&gt;Before enabling an always-on agent, ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does it have a unique identity?&lt;/li&gt;
&lt;li&gt;Are read and write permissions separated?&lt;/li&gt;
&lt;li&gt;Are irreversible actions approval-gated?&lt;/li&gt;
&lt;li&gt;Can every external action be traced to a user and policy decision?&lt;/li&gt;
&lt;li&gt;Can access be revoked immediately?&lt;/li&gt;
&lt;li&gt;Has rollback actually been tested?&lt;/li&gt;
&lt;li&gt;Can the model be replaced without rewriting the permission layer?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The most capable agent is not automatically the most useful one.&lt;/p&gt;

&lt;p&gt;For production systems, trust comes from knowing what the agent can do, what it cannot do and exactly where it must stop and ask.&lt;/p&gt;

&lt;p&gt;Which action in your current workflow would require a mandatory human approval gate?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;AI disclosure: This article was developed with AI assistance and reviewed by the author before publication.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>architecture</category>
      <category>agents</category>
    </item>
    <item>
      <title>Managed Agent Runtimes Still Need a Control Plane</title>
      <dc:creator>shizhe Lim</dc:creator>
      <pubDate>Fri, 02 Oct 2026 03:41:22 +0000</pubDate>
      <link>https://dev.to/shizhe_lim_61b5948cb8081d/managed-agent-runtimes-still-need-a-control-plane-3mk</link>
      <guid>https://dev.to/shizhe_lim_61b5948cb8081d/managed-agent-runtimes-still-need-a-control-plane-3mk</guid>
      <description>&lt;p&gt;Hosted agent runtimes are making a lot of infrastructure feel like a solved problem.&lt;/p&gt;

&lt;p&gt;Long-running sessions, context compaction, tool execution, sandboxes, and subagent coordination can now be consumed as platform features. That is useful — especially for teams that would rather spend their time on a product workflow than on maintaining an agent loop.&lt;/p&gt;

&lt;p&gt;But I think we should separate the &lt;strong&gt;agent runtime&lt;/strong&gt; from the &lt;strong&gt;agent control plane&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A runtime is where work executes. A control plane is where a team can answer operational questions after something goes wrong.&lt;/p&gt;

&lt;p&gt;For a production agent, I would want the control plane to own at least:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Execution journal:&lt;/strong&gt; inputs, tool calls, outputs, and decisions that can be inspected later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Replay and recovery:&lt;/strong&gt; a failed run should be resumable or reproducible without guessing what happened.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Approval gates:&lt;/strong&gt; side-effecting actions need policy and a clear human-in-the-loop path.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evaluation corpus:&lt;/strong&gt; production failures should become regression cases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model-routing policy:&lt;/strong&gt; different steps may need different models, latency budgets, or cost ceilings.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A hosted runtime can still be the right choice. It may reduce operational burden dramatically. But “managed” should not mean “opaque.”&lt;/p&gt;

&lt;p&gt;My rule of thumb: let a platform operate the commodity infrastructure; keep evidence, governance, and decision policy portable enough that your team can investigate and improve the system.&lt;/p&gt;

&lt;p&gt;How are you drawing this boundary? Is there a component you would never hand to a hosted agent platform?&lt;/p&gt;

</description>
      <category>aiops</category>
    </item>
    <item>
      <title>Designing Permission Boundaries for Production AI Agents</title>
      <dc:creator>shizhe Lim</dc:creator>
      <pubDate>Wed, 30 Sep 2026 09:47:27 +0000</pubDate>
      <link>https://dev.to/shizhe_lim_61b5948cb8081d/designing-permission-boundaries-for-production-ai-agents-47mp</link>
      <guid>https://dev.to/shizhe_lim_61b5948cb8081d/designing-permission-boundaries-for-production-ai-agents-47mp</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;AI disclosure: This article was prepared with AI assistance. The author reviewed and edited the technical content and remains responsible for its accuracy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;AI agent permissions are often treated as a binary decision:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The agent can use a tool&lt;/li&gt;
&lt;li&gt;The agent cannot use a tool&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That may be sufficient for a prototype. It is usually too coarse for a production workflow.&lt;/p&gt;

&lt;p&gt;Reading a customer record, drafting an update, saving a draft, and sending the final message may all involve the same system. However, they do not have the same operational risk.&lt;/p&gt;

&lt;p&gt;A safer design separates capability from authority.&lt;/p&gt;

&lt;h2&gt;
  
  
  A four-layer action model
&lt;/h2&gt;

&lt;p&gt;One practical approach is to classify actions into four layers.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Observe
&lt;/h3&gt;

&lt;p&gt;The agent reads information without changing external state.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Retrieve a document&lt;/li&gt;
&lt;li&gt;Read an API response&lt;/li&gt;
&lt;li&gt;Inspect a repository&lt;/li&gt;
&lt;li&gt;Query a customer record&lt;/li&gt;
&lt;li&gt;Review system status&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read access should still be scoped. An agent rarely needs access to every record, directory, API field, or historical event.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Prepare
&lt;/h3&gt;

&lt;p&gt;The agent produces an output that has not yet affected another system or person.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Draft an email&lt;/li&gt;
&lt;li&gt;Generate a SQL query&lt;/li&gt;
&lt;li&gt;Propose a code change&lt;/li&gt;
&lt;li&gt;Prepare a support response&lt;/li&gt;
&lt;li&gt;Create an execution plan&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This layer is useful because it separates reasoning from execution. A person or another policy component can inspect the proposed action before anything changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Act reversibly
&lt;/h3&gt;

&lt;p&gt;The agent changes state, but the result can be reviewed and undone with limited cost.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a pull request&lt;/li&gt;
&lt;li&gt;Save a message as a draft&lt;/li&gt;
&lt;li&gt;Add an item to a review queue&lt;/li&gt;
&lt;li&gt;Create a temporary resource&lt;/li&gt;
&lt;li&gt;Update a record with version history&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reversible does not mean risk-free. The system still needs validation, logging, retry controls, and a defined rollback path.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Commit irreversibly
&lt;/h3&gt;

&lt;p&gt;The agent performs an action that is difficult, expensive, or impossible to reverse.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Send an external message&lt;/li&gt;
&lt;li&gt;Merge a pull request&lt;/li&gt;
&lt;li&gt;Delete production data&lt;/li&gt;
&lt;li&gt;Publish public content&lt;/li&gt;
&lt;li&gt;Submit a payment&lt;/li&gt;
&lt;li&gt;Change access permissions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These actions often need the strongest policy checks and, depending on the workflow, explicit human approval.&lt;/p&gt;

&lt;h2&gt;
  
  
  Put a policy check before every tool call
&lt;/h2&gt;

&lt;p&gt;Permission decisions should be based on more than the tool name.&lt;/p&gt;

&lt;p&gt;The same tool may support both low-risk and high-risk actions. For example, an email integration might read a message, save a draft, or send a final response.&lt;/p&gt;

&lt;p&gt;A simplified policy layer might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;ACTION_LEVELS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;read_record&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;observe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;draft_message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prepare&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;save_draft&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reversible&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;send_message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;irreversible&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;authorize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;level&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ACTION_LEVELS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_has_access&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User does not have access&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_valid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Input validation failed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;irreversible&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;human_approved&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Human approval required&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authorized&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A production policy will be more detailed, but the important idea is simple:&lt;/p&gt;

&lt;p&gt;The agent should not decide its own authority merely because it knows how to call a tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make retries safe
&lt;/h2&gt;

&lt;p&gt;Agent workflows frequently retry after timeouts, interrupted execution, or uncertain responses.&lt;/p&gt;

&lt;p&gt;Without retry protection, an agent may repeat an external action even though the first attempt already succeeded.&lt;/p&gt;

&lt;p&gt;Useful controls include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An idempotency key for each intended side effect&lt;/li&gt;
&lt;li&gt;An expected resource version&lt;/li&gt;
&lt;li&gt;A record of the previous attempt&lt;/li&gt;
&lt;li&gt;A clear completion state&lt;/li&gt;
&lt;li&gt;A rollback or compensation reference&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;action_request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;action&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;send_message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;idempotency_key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;case-1842-final-response&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;expected_version&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;requires_approval&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The idempotency key represents the intended action, not an individual retry. Repeating the request should not create a second side effect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Persist intent, not only the final result
&lt;/h2&gt;

&lt;p&gt;A useful execution record should explain what the agent intended to do and why it was allowed to continue.&lt;/p&gt;

&lt;p&gt;Consider storing:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User or system objective&lt;/li&gt;
&lt;li&gt;Plan version&lt;/li&gt;
&lt;li&gt;Selected tool and arguments&lt;/li&gt;
&lt;li&gt;Action classification&lt;/li&gt;
&lt;li&gt;Policy-check result&lt;/li&gt;
&lt;li&gt;Approval status and approver&lt;/li&gt;
&lt;li&gt;Idempotency key&lt;/li&gt;
&lt;li&gt;Tool response&lt;/li&gt;
&lt;li&gt;Final workflow state&lt;/li&gt;
&lt;li&gt;Resume position after interruption&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This information makes failures easier to diagnose and interrupted workflows easier to resume safely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make approval requests informative
&lt;/h2&gt;

&lt;p&gt;A human approval step should not be a generic “Allow” button.&lt;/p&gt;

&lt;p&gt;Before asking for approval, show:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The exact proposed action&lt;/li&gt;
&lt;li&gt;The destination or affected resource&lt;/li&gt;
&lt;li&gt;The relevant input values&lt;/li&gt;
&lt;li&gt;The expected external effect&lt;/li&gt;
&lt;li&gt;Whether the action is reversible&lt;/li&gt;
&lt;li&gt;A preview or diff when possible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A reviewer should be able to understand the consequence without reconstructing the entire agent session.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test permission boundaries directly
&lt;/h2&gt;

&lt;p&gt;Agent evaluation should include more than successful task completion.&lt;/p&gt;

&lt;p&gt;Test situations such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The agent requests data outside its allowed scope&lt;/li&gt;
&lt;li&gt;Input data changes after the plan is generated&lt;/li&gt;
&lt;li&gt;A tool call times out after completing the action&lt;/li&gt;
&lt;li&gt;The same action is retried&lt;/li&gt;
&lt;li&gt;Approval is denied or expires&lt;/li&gt;
&lt;li&gt;A workflow fails halfway through&lt;/li&gt;
&lt;li&gt;Execution resumes after a restart&lt;/li&gt;
&lt;li&gt;A reversible action cannot be rolled back&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These scenarios reveal whether the surrounding system remains safe when the agent, tool, network, or user behaves unexpectedly.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical release checklist
&lt;/h2&gt;

&lt;p&gt;Before allowing an agent to perform external actions, verify that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every tool has the minimum required scope&lt;/li&gt;
&lt;li&gt;Read and write permissions are separated&lt;/li&gt;
&lt;li&gt;Irreversible actions have explicit policy rules&lt;/li&gt;
&lt;li&gt;Duplicate retries cannot repeat a side effect&lt;/li&gt;
&lt;li&gt;Every external call can be traced&lt;/li&gt;
&lt;li&gt;Approval requests show the exact consequence&lt;/li&gt;
&lt;li&gt;Interrupted workflows can resume safely&lt;/li&gt;
&lt;li&gt;Recovery procedures have been tested&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;Agent autonomy is not defined by how many tools the system can access.&lt;/p&gt;

&lt;p&gt;It is defined by which actions the agent may perform, under what conditions, and with what evidence.&lt;/p&gt;

&lt;p&gt;A useful production agent does not need unlimited authority.&lt;/p&gt;

&lt;p&gt;It needs clearly designed permission boundaries.&lt;/p&gt;

&lt;p&gt;Which action in your agent workflow would you never allow without human approval?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>security</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Stop Reporting Only Average Agent Success</title>
      <dc:creator>shizhe Lim</dc:creator>
      <pubDate>Tue, 29 Sep 2026 09:31:46 +0000</pubDate>
      <link>https://dev.to/shizhe_lim_61b5948cb8081d/stop-reporting-only-average-agent-success-3e82</link>
      <guid>https://dev.to/shizhe_lim_61b5948cb8081d/stop-reporting-only-average-agent-success-3e82</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;AI disclosure: This article was prepared with AI assistance. The author reviewed and edited the technical content and remains responsible for its accuracy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An AI agent completes a task successfully during testing.&lt;/p&gt;

&lt;p&gt;The demo works. The result looks correct. The team records a pass.&lt;/p&gt;

&lt;p&gt;Then someone runs the same task again—and the agent chooses a different tool, changes an argument, follows another path, and fails.&lt;/p&gt;

&lt;p&gt;This is not necessarily a capability problem. It is a consistency problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Average success can hide unreliable behavior
&lt;/h2&gt;

&lt;p&gt;A recent IBM Research evaluation illustrates the difference.&lt;/p&gt;

&lt;p&gt;On the AppWorld benchmark, a ReAct agent using GPT-4.1 achieved a Mean@5 score of 77.4%. In other words, it completed 77.4% of the attempted task runs successfully.&lt;/p&gt;

&lt;p&gt;However, its Pass⁵ score was 53.0%. Only 53% of the tasks succeeded in all five repeated runs.&lt;/p&gt;

&lt;p&gt;Both numbers are correct, but they answer different questions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mean@k:&lt;/strong&gt; How often does the agent succeed on average?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pass^k:&lt;/strong&gt; For how many tasks does the agent succeed in every repeated run?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pass@k:&lt;/strong&gt; For how many tasks does at least one of the repeated runs succeed?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pass@k is useful when a system can safely retry and verify its own answer.&lt;/p&gt;

&lt;p&gt;Pass^k is more relevant when repeated failures are expensive, difficult to detect or unacceptable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Calculating the consistency gap
&lt;/h2&gt;

&lt;p&gt;Suppose evaluation results are stored as one Boolean list per task:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;task_1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;task_2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;task_3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can calculate the average success rate and the all-runs success rate separately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;task_runs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="n"&gt;total_runs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;runs&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;task_runs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;successful_runs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;runs&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;task_runs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;mean_at_k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;successful_runs&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;total_runs&lt;/span&gt;
&lt;span class="n"&gt;pass_power_k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;runs&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;task_runs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_runs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;consistency_gap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mean_at_k&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;pass_power_k&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Mean@k: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;mean_at_k&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Pass^k: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;pass_power_k&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Consistency gap: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;consistency_gap&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A large consistency gap means the agent can complete many tasks, but its success is not repeatable.&lt;/p&gt;

&lt;p&gt;That distinction is easy to lose when a leaderboard reports only one aggregate score.&lt;/p&gt;

&lt;h2&gt;
  
  
  What an Agent evaluation should record
&lt;/h2&gt;

&lt;p&gt;Repeating a task is useful only if the surrounding conditions are documented.&lt;/p&gt;

&lt;p&gt;At minimum, record:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Model and model version&lt;/li&gt;
&lt;li&gt;Prompt or instruction version&lt;/li&gt;
&lt;li&gt;Available tools and their schemas&lt;/li&gt;
&lt;li&gt;Tool permissions&lt;/li&gt;
&lt;li&gt;Agent framework version&lt;/li&gt;
&lt;li&gt;Temperature and other inference settings&lt;/li&gt;
&lt;li&gt;Number of attempts&lt;/li&gt;
&lt;li&gt;Evaluation or grader version&lt;/li&gt;
&lt;li&gt;Token and tool-call cost&lt;/li&gt;
&lt;li&gt;Failure stage and execution trace&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Without this context, two teams may report scores for the “same” model while evaluating meaningfully different systems.&lt;/p&gt;

&lt;p&gt;This is also why reproducible evaluation reporting matters. A model score without its inference budget, tool configuration and evaluation protocol is difficult to interpret—and even harder to reproduce.&lt;/p&gt;

&lt;h2&gt;
  
  
  Evaluate cost per consistent success
&lt;/h2&gt;

&lt;p&gt;Agent economics should not stop at cost per request.&lt;/p&gt;

&lt;p&gt;Consider measuring:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cost per consistent success =
total evaluation cost /
number of tasks that succeeded in every required run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A cheaper model may become expensive if it requires repeated attempts, human review or recovery from incorrect tool calls.&lt;/p&gt;

&lt;p&gt;A more capable model may also be a poor choice if its behavior varies too much across identical workflows.&lt;/p&gt;

&lt;p&gt;For multi-model systems, routing decisions should therefore consider at least:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Capability&lt;/li&gt;
&lt;li&gt;Repeatability&lt;/li&gt;
&lt;li&gt;Latency&lt;/li&gt;
&lt;li&gt;Total recovery cost&lt;/li&gt;
&lt;li&gt;Failure severity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The model with the best average benchmark score is not automatically the best production model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with three repeated runs
&lt;/h2&gt;

&lt;p&gt;Running every task dozens of times may be impractical.&lt;/p&gt;

&lt;p&gt;A reasonable starting point is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run each critical task three times&lt;/li&gt;
&lt;li&gt;Report Mean@3 and Pass³&lt;/li&gt;
&lt;li&gt;Investigate tasks with inconsistent outcomes&lt;/li&gt;
&lt;li&gt;Repeat after changing the model, prompt, tools or permissions&lt;/li&gt;
&lt;li&gt;Increase the repetition count for high-risk workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even three runs can expose instability that a single successful test would miss.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;A successful demo proves that an agent &lt;em&gt;can&lt;/em&gt; complete a task.&lt;/p&gt;

&lt;p&gt;A repeated-run evaluation helps show whether users can depend on it.&lt;/p&gt;

&lt;p&gt;Production reliability starts when we stop asking only:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Did the agent succeed?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and begin asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Will it succeed again under the same conditions?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Have you started measuring repeated-run consistency in your Agent evaluations?&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;IBM Research, “Your Agent Aced the Task. Will It Do It Again?”&lt;br&gt;
&lt;a href="https://huggingface.co/blog/ibm-research/altk-evolve-consistency" rel="noopener noreferrer"&gt;https://huggingface.co/blog/ibm-research/altk-evolve-consistency&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;UK AISI and EvalEval, reproducible evaluation reporting&lt;br&gt;
&lt;a href="https://huggingface.co/blog/evaleval-aisi" rel="noopener noreferrer"&gt;https://huggingface.co/blog/evaleval-aisi&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>testing</category>
      <category>machinelearning</category>
      <category>agents</category>
    </item>
  </channel>
</rss>
