There is a small moment in almost every browser task when an agent is tempted to declare victory too early.
It has found the right page, filled in the fields, and clicked Save. The plan is complete. Every action returned without an obvious error. From the agent’s perspective, the work appears finished.
But did the value actually change?
Perhaps the form rejected a field further up the page. Perhaps the session expired. Perhaps the server is still processing the request. Perhaps the click landed, but nothing happened.
The agent knows what it tried to do. It does not yet know what happened.
That gap—between action and outcome—is where many apparently capable agents become unreliable.
The last click is not the finish line
Imagine asking an agent to change the billing address on an account. A reasonable plan might be:
- 01Find the account.
- 02Open the billing settings.
- 03Enter the new address.
- 04Click Save.
- 05Report success.
The problem is not the plan. The problem is treating the plan as evidence.
Clicking Save proves that the agent attempted to save the address. It does not prove that the application accepted it. To establish that, the agent must inspect what came next: a confirmation message, the updated address on the page, or the same value after reopening the record.
An action is something the agent does.
An outcome is a change in the world.
Plans are useful—and provisional
Planning helps an agent keep its bearings. It turns a vague request into manageable steps and gives long tasks some structure. But a plan is still a prediction. It describes how the agent expects the task to unfold.
The web is rarely so cooperative.
Pages re-render. Buttons move. Sessions expire. Modals appear over the interface. A server rejects an apparently valid request. A single-page application changes state without navigating anywhere. Sometimes a success message appears even though the underlying record has not changed.
A browser agent cannot simply execute a plan and count completed steps. It must repeatedly return to the environment and ask: What is true now?
The plan proposes the next move. The page supplies the evidence.
Act, then look again
A dependable browser agent follows a simple rhythm: observe, act, check.
The agent reads the current state, chooses an action, performs it, and then inspects what changed. If the result matches the intended outcome, it can continue. If it does not, the agent must recover, replan, or explain what blocked it.
The strength of the check should match the importance of the action. Opening a navigation menu may require little more than confirming that the menu appeared. Updating a customer record should involve reading the saved value back. Placing an order calls for stronger evidence: an order number, a confirmation page, or a new entry in the order history.
Useful evidence can be:
- A saved value read back from the application
- A record appearing in the expected list
- A status changing from one state to another
- A server-generated confirmation number
- An item disappearing after deletion
- The same result confirmed from another view
What matters is that the evidence comes from the environment, not from the agent’s confidence in its own actions.
Completion is a typed decision
This principle is not only a prompt handed to the model. It appears in the runtime as a boundary the model cannot talk its way around.
The first step is to give completion more than two possible answers. OpenSidebar distinguishes a supported result from a failed result, a result that still needs checking, and a result the available evidence cannot settle.
export type CompletionEvaluation =
| {
status: "accepted";
reason: string;
contract: CompletionContract;
evidence: CompletionEvidence[];
}
| {
status: "rejected";
reason: string;
contract: CompletionContract;
evidence: CompletionEvidence[];
}
| {
status: "needs_verification";
reason: string;
hint: string;
contract: CompletionContract;
evidence: CompletionEvidence[];
}
| {
status: "inconclusive";
reason: string;
contract?: CompletionContract;
evidence: CompletionEvidence[];
};
The vocabulary matters. “Needs verification” is not silently collapsed into success, and “inconclusive” is not disguised as failure. Every answer carries its evidence.
Naming those states is useful; enforcing them is what changes the behavior. When the agent proposes completion, a guard checks the evidence required by the task contract. Missing evidence turns the proposal into a rejection and sends the agent back to verify.
export function assessMissingEvidenceGuard(
ctx: CompletionGuardContext,
): GuardOutcome {
const preflight =
evaluateCompletionRequiredEvidencePreflight({
missingRequiredEvidence: ctx.missingRequiredEvidence,
});
if (preflight.status === "valid") {
return { kind: "pass" };
}
const missing = preflight.missingRequiredEvidence;
const reason =
`Missing required typed evidence: ${missing.join(", ")}.`;
return {
kind: "reject",
guardId: "missing_evidence",
reason,
// Recovery instructions and trace effects follow.
};
}
“Done” is a proposal, not a command. If the proof required by the contract is missing, execution continues with a concrete reason to re-check the page.
Because reliability claims should be inspectable. These are excerpts from the same completion runtime exercised by OpenSidebar’s tests—not a separate diagram invented for the article.
Plausible behavior is not functional correctness
This distinction also appears in browser-agent research.
WebArena evaluates whether web tasks are functionally correct after execution. Its validators inspect the resulting application state rather than awarding success because an agent followed a convincing sequence of steps.
WorkArena brings the same principle to enterprise work in ServiceNow. The agent succeeds when the requested outcome exists in the application—not when its activity merely looks reasonable.
That difference matters in both directions. A clumsy process can occasionally produce the correct result, while an elegant process can end in failure. If we evaluate only the sequence of actions, we can misjudge both.
Traces explain; validators decide
A trajectory—or trace—is the record of an agent’s run: what it observed, which tools it used, what those tools returned, where it hesitated, and how it responded to errors.
Traces are essential. When an agent fails, the trace can show whether it misunderstood the page, acted on stale information, missed an error message, or simply stopped too soon. Without that record, debugging becomes guesswork.
But a trace is not proof of success.
An agent can produce a beautifully coherent account of a task it did not complete. It can explain why each action made sense. It can even state, with confidence, that the objective was achieved. None of that changes the application state.
Validators decide whether the required outcome exists.
Traces explain why it does—or why it does not.
Anthropic’s guidance on agent evaluations draws a similar distinction between evaluating outcomes and evaluating transcripts. Both matter, but they answer different questions.
The model does not contain a “done” detector
It is tempting to treat premature completion as a model problem: perhaps the agent needs a better prompt, a stronger model, or another reminder to be careful. Sometimes that helps. It is not the whole answer.
Reliable completion comes from the system around the model: clear goals, useful browser tools, fresh observations, verification rules, approval gates, recovery paths, and traces. Together, these form the agent’s harness.
Addy Osmani describes harness engineering as the work of improving that surrounding system whenever an agent exposes a recurring failure. If agents regularly stop after clicking Save, the durable solution is to make post-action checking part of the normal execution loop.
The goal is not to make the agent sound less certain. It is to give certainty a better foundation.
Sometimes the honest answer is “I don’t know yet”
Not every outcome can be verified automatically.
A background operation may take longer than expected. A website may offer no readable confirmation. Another person may need to approve the request. The action may have succeeded even though the page failed to update.
In those cases, the agent should not turn missing evidence into invented confidence.
Evidence shows the objective was achieved.
Evidence shows the objective was not achieved.
The available evidence supports neither conclusion.
Uncertainty is not a weakness. It is a faithful description of the situation.
The boundary matters. Verification should stop at the edge of the user’s objective. If the task is to send a message, evidence that the application accepted and delivered it may be enough. Whether the recipient reads it, understands it, or acts on it is a later outcome—unless the user explicitly made that part of the goal.
The agent may need to observe again, check another part of the application, wait for an external result, or ask the user what to do next. For consequential or irreversible actions, human confirmation may be the correct final validator.
This principle extends beyond browser automation. NIST’s guidance on trustworthy AI emphasizes objective evidence, ongoing monitoring, and the ability for humans to intervene when a system cannot detect or correct its own errors.
Further reading
- WebArena: A Realistic Web Environment for Building Autonomous Agents ICLR, 2024
- WorkArena: How Capable Are Web Agents at Solving Common Knowledge Work Tasks? ServiceNow Research, 2024
- Demystifying evals for AI agents Anthropic Engineering
- Agent Harness Engineering Addy Osmani
- AI Risks and Trustworthiness NIST AI Risk Management Framework