Skip to Content
webagent docs
QA testing

Reading results

What each webagent tool returns, what the stop reasons mean, and how long evidence links last.

Open as .md

Your agent gets back a test report, a task result or a skill run. It tells you what it saw. This page helps you check it.

ToolsResultUse for
smoke_test, get_reportA test report: one verdict, the steps, console errors and failed network callsA pass/fail check of a page or flow
run_task, get_taskA task: a goal the browser agent worked throughExploring, or a flow you want the agent to judge
skill_<name>, run_skill, get_skill_runA skill run: the raw record of a saved checkReading a skill's own result
Any tool, on failureAn error: [code] messageA call that did not run

get_report also reads the report of a task or a skill run, so every result can be turned into a test report.

The test report

smoke_test and get_report answer with a short text and the whole report as structuredContent. The same report is at GET /v1/skill-runs/:id/report.json and GET /v1/tasks/:id/report.json. It looks the same for a skill run and for a task.

This is the whole report of a real smoke test of a Test Arena address that does not exist, with only the ids and links replaced. The page answered 404, so the second step failed and the network call is listed:

{
  "id": "run_us_xxxxxxxxxxxxxxxxxxxxxxxx",
  "kind": "skill_run",
  "sessionId": "sess_us_xxxxxxxxxxxxxxxxxxxxxxxx",
  "name": "smoke-uat@1.2.1",
  "verdict": "fail",
  "outcome": "failed",
  "summary": "Smoke test of https://webagent-test-web.pages.dev/missing-page FAILED in 1 s: 1 of 2 steps passed. Step 2 \"assert 2 conditions\" failed: Page responded without an error status. 1 failed network call (GET /missing-page 404).",
  "url": "https://webagent-test-web.pages.dev/missing-page",
  "finalUrl": "https://webagent-test-web.pages.dev/missing-page",
  "startedAt": "2026-11-12T00:10:56.386Z",
  "endedAt": "2026-11-12T00:10:57.319Z",
  "durationMs": 933,
  "counts": { "steps": 2, "failedSteps": 1, "findings": 0, "consoleErrors": 0, "networkFailures": 1 },
  "steps": [
    { "index": 0, "title": "navigate https://webagent-test-web.pages.dev/missing-page", "kind": "navigate", "status": "pass", "ms": 423 },
    {
      "index": 1,
      "title": "assert 2 conditions",
      "kind": "assert",
      "status": "fail",
      "error": "Page responded without an error status",
      "ms": 4,
      "screenshotUrl": "https://..."
    }
  ],
  "findings": [],
  "consoleErrors": [],
  "networkFailures": [
    { "kind": "http_error", "method": "GET", "url": "https://webagent-test-web.pages.dev/missing-page", "status": 404 }
  ],
  "evidence": {
    "reportPath": "/v1/skill-runs/run_us_xxxxxxxxxxxxxxxxxxxxxxxx/report",
    "reportSignedUrl": "https://...",
    "recordingPath": "/v1/sessions/sess_us_xxxxxxxxxxxxxxxxxxxxxxxx/recording",
    "logsPath": "/v1/sessions/sess_us_xxxxxxxxxxxxxxxxxxxxxxxx/logs",
    "urlsExpireAt": "2026-11-12T00:15:58.494Z"
  },
  "notes": []
}

A test with steps and an expectText lists every step: the page checks (navigate, check basic-a11y, check broken-links), one act step for each of your steps, check console-errors, then the expectation checks. A check you did not ask for (for example expectUrl when you set only expectText) is listed with status: "skipped". A real report lists up to 50 steps.

The verdict

verdictMeaningWhat to do
passThe test ran and every check passed. For a task: the agent says it is done.Nothing. For a task, see the note below
failThe test ran and found a problem in the page or the flow. Read summary and the failed steps.Fix the app, or the test
errorThe test could not run to a result: the run was cancelled, denied a permission, or the browser failed. For a task: the agent could not test (CAPTCHA, a blocked address, an internal error).This is not a bug in your app. Fix the cause and run again
runningNot finished. The summary says to call get_report with the id.Call get_report again

outcome is the raw result under the verdict: the skill status (passed, failed, error, cancelled, denied) or the task stoppedBy (done, stuck, budget and so on). isError on the tool call is true only for verdict error.

A task pass is not a check

A task has no assertions. For a task report, pass only means the agent says it is done, and the report says so in notes. To check that a text, an address or a result is really there, use smoke_test with expectText, expectUrl or expectNoText.

The fields

FieldMeaning
id, kindThe run id (run_…, kind skill_run) or the task id (tsk_…, kind task)
sessionIdThe browser session the test ran in
namesmoke-uat@1.2.1 for a skill run. The goal, cut to 300 characters, for a task
summaryPlain sentences you can pass on as they are: what was tested, how many steps passed, the first failed step with its reason, the findings and the console and network totals
urlThe page under test. For a task it is the first page the browser opened, taken from the session log
finalUrlWhere the browser ended. From the session log, so it is missing until the log is saved
startedAt, endedAt, durationMsWhen it started and ended, and how long it took. endedAt and durationMs appear when it has ended
countsThe real totals before the lists below are cut: steps, failedSteps, findings, consoleErrors, networkFailures
stepsUp to 50 steps in order. Each has index (from 0), title, kind, status (pass, fail or skipped), error, ms and, for a failed step of a skill run, a screenshotUrl. When there are more than 50, failed steps come first and a note says how many are shown
findingsUp to 30 problems the checks found (a broken link, an accessibility issue), worst first. Each has severity (info, low, medium, high, critical), title, and often rule, url, fix and detail. A task has none
consoleErrorsUp to 15 browser console errors and uncaught page errors: source (console or pageerror), text and url
networkFailuresUp to 20 failed requests: kind (http_error for a 4xx or 5xx answer, request_failed when nothing came back), method, url, status or error
evidenceLinks to the proof. See below
notesUp to 8 sentences on what is missing and why. Read them when a list looks too empty

A task step has only the action and its target (for example click e12). It has no page address, screenshot or readable label. A report of a skill run has all of these for its steps.

If counts.consoleErrors is larger than the list, only the first entries are shown. Use logsPath for the full log.

Console and network errors come from the session log

Console errors and failed network calls are read from the session log. The log is saved when the session ends. A report read while the session is still open has empty lists, no finalUrl, and this note: "The session log is not available (it is stored when the session ends), so console errors, failed network calls and URLs are missing." That does not mean the page had no errors. Read the report again after the session has ended. For a task that left its session open (keepOpen) that means after stop_session. smoke_test, get_report after a skill run and a run_task that closes its own session have the log at once; in CI, read the report once more a few seconds later if evidence.logsPath is missing, as the script in Smoke tests in CI does.

FieldWhat it isLifetime
evidence.reportSignedUrlThe HTML report as a link that opens without a keyThe links stop working at urlsExpireAt. This is about 5 minutes after you asked for the report
steps[].screenshotUrlA screenshot of a failed stepThe same time
evidence.reportPathSkill runs only. GET this path with your API key: it redirects to the HTML reportThe redirect lasts 5 minutes
evidence.recordingPathThe replay video of the session. Only when the session was recorded: always for smoke_test, and for run_task only with record: trueThe path needs your key. The video is saved when the session ends
evidence.logsPathThe full console and network log of the sessionNeeds your key. Present when the log was read

Call get_report again to get new links. Download what you need to keep. See Evidence.

Task results

run_task answers with a short text, and the same data as structuredContent:

Here is a task that could not finish, because the page was an interstitial and not the app. The text:

Task stopped (blocked) in 2 steps, $0.0044, 10 s.
Reason: The AI model could not find a way forward (50% sure): The page is an ngrok interstitial. ...
Session sess_us_xxxxxxxxxxxxxxxxxxxxxxxx was closed.

And the data, trimmed:

{
  "sessionId": "sess_us_xxxxxxxxxxxxxxxxxxxxxxxx",
  "sessionClosed": true,
  "task": {
    "ok": false,
    "stoppedBy": "blocked",
    "reason": "The AI model could not find a way forward (50% sure): The page is an ngrok interstitial. ...",
    "steps": [
      { "op": "wait", "provider": "claude:claude-haiku-5-5", "ok": true, "ms": 3200, "costMicros": 140 }
    ],
    "costMicros": 4400,
    "ms": 10000,
    "text": "..."
  }
}
FieldMeaning
oktrue only when the agent stopped because it was done (stoppedBy: done).
answerWhat the agent says it found. Present when it finished.
stoppedByWhy the task ended. See the table below.
reasonA plain sentence about why it stopped, when it did not finish.
limitWhich limit ended it, when one did: maxSteps, maxCostUsd or allowHosts.
stepsOne entry per action: op (click, type, navigate…), the element ref, ok, time in ms, cost and error.
costMicros, msCost in millionths of a dollar, and total time in milliseconds.
textThe final page diff or snapshot text, cut short.
sessionClosedWhether the tool closed the browser. run_task closes a session it opened, unless you passed keepOpen.

A goal task has no assertions of its own. ok: true means the agent believes it reached the goal. It does not prove your page is correct. Ask for a specific thing to check in the prompt, such as the exact text that must appear, and read answer. For a check with a fixed pass or fail, use smoke_test. To get a report for a task, call get_report with its taskId: the answer ends with that hint.

Still running

A task that takes longer than the wait (90 seconds for run_task, 30 seconds by default for get_task) is not an error. The tool answers:

{ "sessionId": "sess_us_...", "taskId": "tsk_...", "status": "running", "note": "still running: call get_task ..." }

The browser keeps working and the session stays open. Call get_report with the taskId, or get_task with the sessionId and taskId, until it has finished. Neither closes the session: call stop_session when you are done.

get_task answers with status: finished and the stored task. Its steps and cost have the same meaning as above.

Stop reasons

stoppedByMeaningTreat as
doneThe agent finished and gave an answer.Pass or fail, from the answer
blockedThe agent could not go on. For example a login wall it has no login for, or an address webagent refused to open. reason says which. limit: allowHosts means a site allowlist refused a navigation.Could not test, unless the block is the app's fault
stuckSeveral steps in a row left the page unchanged or failed, or the agent kept repeating itself.Often a real problem on the page: read reason and the failed steps
budgetThe task hit its step or cost cap. limit says which.Could not test. Raise maxSteps (1 to 50) or split the goal
captchaThe page showed a CAPTCHA. Webagent does not solve CAPTCHAs.Could not test
pausedA person took over the session.Could not test
errorSomething failed inside the agent or the browser.Could not test
abortedThe task was stopped from outside, for example the session was closed.Could not test
unansweredA question to the user waited with no answer. Over MCP the agent cannot answer, so this should not happen.Could not test

"Could not test" is not a bug in your app. An agent that reports a CAPTCHA or a budget stop as "the app is broken" is wrong. The agent setup snippet asks your agent to keep the two apart.

ok: false and isError

A task that stops without finishing is still a normal tool result in most cases. isError is set only when the agent could not test: stoppedBy is captcha, blocked, error, aborted or paused (or a capacity or timeout stop). A task that ended stuck, budget or unanswered has ok: false and no isError. Always read ok and stoppedBy, not only isError. get_report turns the same rule into a verdict: error for the first group, fail for the second.

Skill runs

skill_smoke_uat and the other skill_<name> tools start the run, wait for the verdict (30 seconds by default, options.waitSeconds up to 120) and answer with a summary and the raw run. For a test, smoke_test is easier: it answers with the test report instead. This is what a skill tool answers:

smoke-uat@1.2.1 run run_us_xxxxxxxxxxxxxxxxxxxxxxxx: failed in 7916 ms.
7 links checked (0 broken), 0 accessibility issues, 0 console errors
Reason: step 10 (assert 1 condition) failed: Expected text "Nonexistent heading" is not on the page
Counts: steps 13, cdpCalls 7, findings 0, warnings 0, assertions 6, failedSteps 1, findings.low 0, httpRequests 7, findings.high 0, findings.info 0, findings.medium 0, failedAssertions 1, findings.critical 0.
Failed steps (1):
- 9 assert 1 condition: Expected text "Nonexistent heading" is not on the page
Report (short-lived link): https://...
Full detail in structuredContent (no inline media); REST: GET /v1/skill-runs/run_us_...
For a pass/fail report call get_report with run_us_...

This is the output of a real run on the Test Arena pricing page. The Reason: line counts steps from 1 and the Failed steps list counts from 0: the same step is "step 10" and "9". A run that passes has no Reason: and no failed steps, for example passed in 1229 ms. and the 7 links checked ... line.

Field in structuredContentMeaning
statusrunning, passed, failed, error, cancelled or denied
summary, countsOne line and the totals: steps, failed steps, assertions, findings by severity
result.stepsEach step: label, ok, ms and error
result.findingsProblems the checks found, each with a severity and often a one-line fix
result.reasonWhy the run did not pass
reportUrlA signed link to the HTML report, with screenshots of failed steps
hasReportWhether a report exists

What the statuses mean:

statusMeaning
passedEvery check passed.
failedThe test ran and found a problem. Read the failed steps and findings.
errorThe run could not finish, for example the browser or session failed.
deniedThe run needed a permission it was not given.
cancelledThe run was stopped.
runningNot finished yet. Call get_skill_run with the runId. It waits up to the waitSeconds you give (up to 120).

Results leave out inline screenshots and video, and cut long text, so they fit in your agent's context. The full run is in GET /v1/skill-runs/<runId> and the report.

A skill tool or get_skill_run sets isError only for error, denied and cancelled: the runs that could not test. A failed run is a normal result: the app has a problem. For the verdict with console errors and failed network calls, call get_report with the runId.

Errors

A call that does not run comes back as a tool result with isError: true. The text is [code] message, and structuredContent.error holds the same as an object.

[navigation_blocked] ...
CodeWhat to do
navigation_blockedThe address is not allowed: a private or localhost address. Use a public URL or a tunnel.
capacity_exceededToo many sessions open, or no browser capacity. Stop old sessions with stop_session, or wait.
invalid_inputThe tool arguments were wrong. The message names the field.
session_closedThe session already ended. Start a new one.
not_foundNo such session, task or run in this workspace.
unauthorized, wrong_regionThe key is bad, or it belongs to another region.
rate_limitedToo many requests. Wait a moment and retry.

The full list is in the error reference.

Evidence and how long it lasts

EvidenceHow you get itHow long
Live viewDashboard, Sessions, open the sessionOnly while the session is open. run_task closes its own session at the end unless you set keepOpen.
Test reportsmoke_test or get_reportRead it again any time. The links inside it work for about 5 minutes. See Evidence and when links stop working
Skill report (HTML)reportSignedUrl in the test report, or reportUrl in a skill resultThe link works for about 5 minutes. Open or save it right away.
Failed-step screenshotsscreenshotUrl of a failed step in the test report, and inside the HTML reportThe same time
Replay videoAlways for smoke_test. For run_task and create_session, only with record: trueSaved when the session closes
Event logGET /v1/sessions/<id>/logs after the session endsREST only; see Evidence for how long it is kept
Share linkPOST /v1/sessions/<id>/share: a link anyone can openBetween 1 minute and 7 days, as you choose

A task result has no screenshots or console errors in it. The task report adds console errors and failed network calls from the session log. If you need proof with screenshots for a developer, run smoke_test: its report has a screenshot of every failed step and a recording. For a task, pass record: true to run_task to get a recording. Evidence has the full picture.

On this page