Repository navigation
Completion receipts for Stagehand workflows: validating outcomes after act() and extract()
#2640
Replies: 2 comments
|
The receipt idea holds up, and there is one boundary worth drawing explicitly inside it, because it cost us a run to find. A receipt records the evidence that made the workflow accept an outcome. That evidence is almost always gathered on the object your code is holding — the extracted value, the page state, the drafted message. What actually reaches the world can be something else. We build an email agent where 18 lines of plain code decide whether an AI-drafted reply may be sent: every fact in it has to exist in a file a human wrote. On a filmed run, six drafts, six cleared, every fact cited. Then we read the message back out of Sent Mail and diffed it against the body the gate had approved: The send node appends attribution after the node's parameters resolve — which is after every check in the workflow. Same feature on the HTML path of an earlier build added 312 bytes including a tracked link with a campaign parameter. Nothing malicious, and no test inside the workflow could have caught it, because the workflow is upstream of the thing that modified the message. So the distinction I would bake into the receipt format: is this evidence about what we decided, or about what actually happened? For Two smaller things that made ours useful in practice:
|
|
I would separate the number of evidence matches from the number of accepted artifacts, and keep an unresolved result distinct from a failed one. In our 10 October check of a public resource listing, the returned HTML contained three anchors to the expected project host. All three belonged to one listing page. We recorded one verified public page with three matching anchors, rather than three completed outcomes: {
"artifact_url": "https://thedevtoolsdir.com/product/browsesprint/",
"evidence_scope": "anonymous returned HTML",
"observed_http_status": 200,
"matching_anchor_count": 3,
"verified_artifact_count": 1,
"outcome": "verified"
}That result establishes the public-HTML goal only; it does not establish indexing, traffic, or private backend state. Our dated field notes include the read-only Python check and its limits. For submissions, I would add a verification deadline and an Disclosure: I maintain BrowseSprint and its free browser-task diagnostic guide. These are our resource-publication observations. I have not tested this as a Stagehand integration, and no speed improvement is claimed. This reply was prepared with AI assistance. |
Uh oh!
There was an error while loading. Please reload this page.
Stagehand gives developers several useful levels of control:
act()for a focused action,agent()for a multi-step task, andextract()for structured output. In production, I still want one more boundary after those calls: a small completion receipt that records what evidence made the workflow acceptable.This is not a Stagehand plugin or a replacement for its execution model. It is a provider-neutral pattern for preventing “the browser call returned” from becoming “the business task succeeded.”
Keep execution and acceptance separate
Consider a workflow that opens a repository page and extracts the author and title. The browser may navigate successfully while landing on a login wall, stale mirror, or repository with a similar name. The extraction can also return syntactically valid fields whose values came from the wrong page.
I represent the final check as a receipt with four parts:
{ "task_id": "repository-metadata-v1", "execution": { "operation": "extract", "attempts": 1, "final_url": "https://example.com/expected-repository" }, "evidence": { "author": "expected-owner", "title": "expected-repository" }, "assertions": [ { "name": "expected_origin", "passed": true }, { "name": "required_fields_present", "passed": true }, { "name": "repository_identity_matches", "passed": true } ], "verdict": "pass" }Stagehand owns browser execution. The receipt is produced by deterministic application code after the result returns. A downstream agent receives the extracted data only when every required assertion passes.
Preserve evidence before retrying
Retries are much easier to diagnose when each failed attempt keeps its URL, operation, extracted fields, assertion results, latency, and failure reason. A self-healed action may be useful, but it should not erase the evidence from the selector or page state that failed first.
I use a small failure vocabulary rather than a generic exception:
wrong_originunexpected_auth_wallmissing_required_fieldidentity_mismatchtimeout_before_evidenceThat vocabulary can drive retry policy. A timeout may justify another attempt. An authentication wall should usually stop. An identity mismatch should fail closed rather than ask the browser to improvise.
Test the receipt against fixed tasks
The useful benchmark is not whether one demo completed. It is whether the same versioned tasks keep producing valid receipts across page changes, model updates, and execution environments. Keep quality, successful-call latency, and cost separate so a fast invalid result does not receive credit for speed.
We use this separation in a public evaluation methodology for web-access services. The portable idea is simple: execution produces evidence; application-owned checks produce the verdict.
For Stagehand users, which evidence would you include in a completion receipt:
observe()candidates, action history, final DOM fragments, screenshots, extracted schemas, or something else?Disclosure: I am affiliated with NativePort. This post was drafted with AI assistance and reviewed against Stagehand's current public README and the linked methodology.
All reactions