---
title: "How Currents solves verification engineering"
description: "Writing code is no longer the bottleneck, proving it works is. How Currents handles the four parts of verification engineering: time to a verdict, trust in tests, evidence an agent can use, and the hand-offs between them."
canonical: "https://currents.dev/posts/how-currents-solves-verification-engineering"
updated: "2026-10-30"
---

# How Currents solves verification engineering

Published 2026-10-30 by Sumit Saurabh.

Canonical URL: https://currents.dev/posts/how-currents-solves-verification-engineering

Writing code is no longer the bottleneck, proving it works is. How Currents handles the four parts of verification engineering: time to a verdict, trust in tests, evidence an agent can use, and the hand-offs between them.

---


In my [previous article](/posts/software-engineering-has-changed-again), I'd shown how with the advent of agents, writing code is no longer the bottleneck in Software Engineering, it is proving that the code does what it is supposed to. I broke the bottleneck into four parts:

1. Time to a verdict
2. Trust in tests
3. Evidence an agent can use
4. Hand-offs between the steps

So the obvious next question is: what does a system that handles all four look like?

That's what I'll be tackling in this article.

Come to think of it, software has always served two users: humans and machines.

We had high level programming languages, machines had assembly. Our interface with software was UIs, for machines, it was the APIs. AI doesn't follow this classification. For the first time, We humans and AI (the machine) both need the terminal.

But because that transition hasn't fully completed (AGI wasn't here, last I checked!), verifying the change in code needs to touch three interfaces:

* People still need to see what happened,
* Machines (CI, chat, ticketing) need events and APIs to communicate, and
* Agents need to read evidence and act on it, without a person opening a dashboard (AI doesn't care for our fancy, pixel-perfect dashboards) for them.

And this is precisely where Currents comes in. In this article, I'll go through each of the four parts I talked about in my last article and show you what Currents does about it. I'll, in fact link each to the relevant page in our docs so you (or your agent) can check it out for yourselves.

## It all starts with a record

Before Currents can explain, filter or speed up anything, it needs data. For simplicity, every feature in this article will read from the same record.

When your Playwright tests run in CI with Currents as reporter, it stores:

* Test steps, errors, results and timing
* Playwright traces, screenshots, videos, and the terminal stdout and stderr
* The CI context: commit SHA, branch, author, commit message, PR details and build ID
* The machine: OS, memory and CPU

At the volume of code produced by agents, two things matter:

1. **Results stream in while the tests run.** Most Playwright reporters write their results after the run ends. The Currents reporter [streams each step](https://docs.currents.dev/guides/parallelization-guide/step-level-reporting) as soon as it is available, so "even if an execution crashes, Currents will capture the last step that caused the failure." Unlike a traditional CI machine that dies halfway, Currents takes the evidence with it.
2. **Every result joins a history.** [Test History](https://docs.currents.dev/dashboard/tests/test-history) shows one test across runs and branches, over 7, 14, 28 or 45 days. Each attempt is marked as passed, failed, flaky, skipped or ignored.

This record is what answers the questions from the previous article:

* Did this test fail before this change?
* Does it fail only in CI?
* Did other tests fail with the same error?

Without a record, nobody, human or agent, can answer those. One record of every run feeds people, machines as well as agents:

![CI sends results to Currents, whose record feeds people, machines and agents](/img/posts/how-currents-solves-verification-engineering/one-record-feeds-people-machines-and-agents.png)

Now, let's have a look at each of the 4 bottlenecks one by one:

## Bottleneck 1: Time to a verdict

This is the easiest to guess metric that now limits throughput. It measures the time from a push to a pass/fail that you can trust. This is because while a developer might push a few times a day and do other things while CI runs, agents don't have that choice and after pushing, they have to wait for the results before doing anything useful.

So the first job is to get that verdict back faster, without dropping tests to do it (if you don't have tests, you pass all the tests!).

Currents works on this from four sides:

* [**Test Orchestration**](https://docs.currents.dev/guides/test-orchestration):
  * Playwright [parallelism](https://playwright.dev/docs/test-parallel) helps a bit in reducing the bottleneck, but they aren't as efficient as they could be. Sharding splits test files based on the lexical order of file paths, leading to unbalanced workloads.
  * Currents Orchestrator fixes that by balancing the load using historical execution data, continuously creating the most optimal execution order for test runs.
  * It keeps a live queue of pending tests and dynamically assigns them to machines as they become available. This allows continuous communication and coordination across all nodes, improving overall throughput.
* [**Load balancing strategy**](https://docs.currents.dev/guides/ci-optimization/load-balancing):
  * By default, Currents Orchestrator orders tests by expected duration.
  * You can even switch to sorting by failure rate, so that the tests most likely to fail run first and the bad news arrives sooner.
* [**Fail fast**](https://docs.currents.dev/guides/ci-optimization/fail-fast-strategy): When the number of failed tests passes a threshold (you can even set it to 1), Currents cancels the run on every machine. You set it in the project settings or with the CLI flag `--pwc-cancel-after-failures <number | false>`. If a PR is already broken at test 12, there's no point in running the other 2,000.
* [**Re-run only failed tests**](https://docs.currents.dev/guides/ci-optimization/re-run-only-failed-tests): Playwright 1.44+ has a `--last-failed` flag, and Currents makes it work across sharded and orchestrated runs. A re-run then takes as long as it takes to run the failed tests, not the whole suite.

Then there's cost. More agents means more CI runs, and more CI runs means a bigger cloud bill. [Spot instances](https://docs.currents.dev/guides/ci-optimization/ci-tests-on-spot-instances) are much cheaper, but the cloud provider can take them back mid-run.

With `pwc-p run --pwc-reset-signal SIGUSR1`, Currents moves the tests from a machine that is about to go away to healthy machines. You do have to catch the eviction notice and send the signal yourself, but the tests don't get lost.

In fact, one of our customers [FundGuard](/posts/currents-and-fundguard) moved to Currents Orchestration, taking its end-to-end pipeline from ~80 minutes to ~40 (and had a 70% reduction in CI/CD costs). For an agent, that's two CI rounds in the same time as it used to take for one!

## Bottleneck 2: Trust in tests

When tests decide what merges (as they do in the age of verification engineering), a flaky test does one of two things. Either it blocks a good PR, or it sends an agent off to "fix" code that was never broken. To stop that, you need three things: know which tests are flaky, take them out of the gate in a controlled way, and know why tests fail.

1. Know which tests are flaky
   * With retries on, Currents [marks a test as flaky](https://docs.currents.dev/dashboard/tests/flaky-tests) when it fails its first attempt and passes on a later one. No setup needed.
   * [Test Explorer](https://docs.currents.dev/dashboard/test-suite-performance-explorer/tests-explorer) ranks tests by flakiness rate. Its "% Flaky Trend" column and "Trending Flaky" preset show you the tests that are getting worse, not only the ones that were always bad.
   * [Test Flakiness analytics](https://docs.currents.dev/dashboard/analytics/test-flakiness) shows flakiness across the whole suite over time.
   * If you'd rather have a flaky test fail the run, `failOnFlakyTests` does exactly that. It needs Playwright 1.52+ and `@currents/playwright` 1.12.3+.
2. Flaky tests no longer block the pipeline
   * This is what [Currents Actions](https://docs.currents.dev/guides/currents-actions) are for. An action (skip/quarantine, add tag) is a rule that changes what happens to the tests it matches.
   * [Conditions](https://docs.currents.dev/guides/currents-actions/reference/conditions) can match on file, test title, tag, project, error message, git branch, git author and more, combined with AND or OR. So a rule like "quarantine this test, on `main` only, when the error message includes `net::ERR_CONNECTION_RESET`" is one form in the dashboard.
   * Every action can have an [expiry date](https://docs.currents.dev/guides/currents-actions/using-currents-actions), after which it stops applying. [Lifecycle notifications](https://docs.currents.dev/guides/currents-actions/lifecycle-notifications) go to Slack or email when an action is created, disabled, or due to expire in the next 12 hours. The [Affected Tests](https://docs.currents.dev/guides/currents-actions/affected-tests) tab lists every test an action touches, and only users with the Admin or Actions admin role can create or change actions.
   * That is the "quarantine with an owner and an expiry date" rule from the previous article, available by default in Currents. An expiring quarantine can't turn into a permanent skip.
3. Know why tests fail
   * Currents' [Error Explorer](https://docs.currents.dev/dashboard/test-suite-performance-explorer/errors-explorer) classifies every Playwright failure by **Category**, **Action** and **Target**.
   * It then counts occurrences, affected tests and affected branches for each error. For example, when 40 tests fail with the same timeout on the same selector, you see one problem, not 40.
   * To drive this point home, here's a case study in which n8n's flaky-test rate went from about 2 to 3% down to about 0.3% during its move from Cypress to Playwright with Currents ([case study](/posts/currents-and-n8n))

## Bottleneck 3: Evidence an agent can use

This is the bottleneck that changed the most with agents. A dashboard is great for a person or a team. But an agent needs the same evidence (screenshots, video, the Playwright trace, page snapshots and logs), in pieces small enough for its context window, through an interface it can call. Some call it the agentic layer, others call it verification layer.

Nomenclature aside, Currents has four parts to that layer:

### 1. The MCP server

The [Currents MCP server](https://docs.currents.dev/ai/reference/mcp-server) connects your agent to your test data. It's hosted at `https://mcp.currents.dev/mcp`, and you connect with a sign-in or an API key. The tools map directly to the questions an agent has to answer before it can fix a failing end-to-end test:

| The agent's question | MCP tool | What it returns |
| -- | -- | -- |
| Did this test fail before this change? | `currents-get-test-results` | The history of one test |
| Why did this run fail? | `currents-get-context` | The errors, steps and files of a run, a spec file or a test |
| What did the page show? | `currents-get-test-evidence` | The screenshots, videos, traces and attachments of each test in a run |
| Did other tests fail with the same error? | `currents-get-errors-explorer` | Errors grouped and counted across runs |
| Which tests are the flakiest or slowest? | `currents-get-tests-performance` | Tests ranked by failures, flakiness or duration |

Agents can also act through MCP. Write tools create, update, enable and disable Currents Actions, and create or link Jira issues. So an agent that finds a flaky test can create a quarantine action and file a Jira ticket for its owner, in the same session. Talk about Hand-off!

### 2. Fix with AI

[Fix with AI](https://docs.currents.dev/ai/agentic-testing/fix-failing-tests) packages everything about a failed test into one context:

* spec, title, status, attempt and duration
* repo, branch, PR and commit
* the error message and stack trace
* the accessibility tree of the page at the moment of failure
* console and network requests
* the trace error analysis
* steps, stdout and stderr
* links to the trace, screenshots, videos and attachments
* the other attempts of the same test

You get to it from wherever you already are:

* **Dashboard**: "Fix with AI" on a failed test, or "Fix" on a whole run. It opens straight in Claude, Claude Code, Codex, Conductor, Cursor, GitHub Copilot or Zed.
* **Slack**: a "Fix with AI" button on failure notifications.
* **GitHub**: the "Fix with AI" section of the run comment on the PR, with a link for you and a prompt for your agent.
* **Your editor**: "Fix with agent" in the [IDE extension](https://docs.currents.dev/ai/connect/ide-extension) for VS Code and Cursor.
* **Your agent**: ask it, through MCP, to get the details of a run and fix the failures.

A Fix link lasts 1 day by default, or 3 or 7 days if you choose. Add `.md` to the link, and the agent gets the whole context as plain Markdown with no credentials. AI-maxxing FTW!

### 3. The Trace API

The Playwright trace is the single best piece of evidence for a failed end-to-end test. It's also a data rich zip file that can be heavy in size. Paste the whole thing into a prompt and you waste tokens. Paste only the stack trace and you get generic fixes.

That's why Currents [Trace API](https://docs.currents.dev/ai/reference/trace-api) lets an agent read a trace one piece at a time. It starts with `/digest` for a summary, then pulls only what it needs:

* `/snapshots/failure` for the page at the moment of failure, as text, ARIA or DOM
* `/frames/failure` for what the screen looked like
* `/requests` for the network log, and the body of any single request

In our [launch example](/changelog/agentic-trace-explorer), an agent got what it needed in 4 calls and about 1,600 tokens. If you had pasted all the files in that trace, it would come to about 20,000.

### 4. Guardrails

Although agents are amazing tools, I think we all agree that there should be some guardrails for agentic actions, lest they turn into a time sink rather than a productivity boost. Currents handles this with [personal access tokens](https://docs.currents.dev/authentication/personal-access-tokens). Each token has fixed scopes, like `results:read`, `analytics:read` or `actions:write`, and expires within a year at most.

Give your agent a token with read scopes only, and it can look at everything and change nothing.

Scope matters, because some MCP tools are destructive. In fact, the delete action `currents-delete-run` cannot be undone, and we do not ask for confirmation. So, you can give your agent the scopes you like and thereby choose how much liberty they need for the job at hand.

## Bottleneck 4: Hand-offs between the steps

Verification doesn't end when a test fails. Someone still has to decide what the failure is, quarantine it or file it, and tell the owner. Before agents, that someone was the engineer on CI duty.

At agent volume, nobody can open every failed run, decide what it is, and pass it on.

So Currents puts each result where the next person or agent already works. Say an agent opens a PR at 2 AM and a test fails. Here is what unfolds next:

* **On the PR.** The [GitHub App](https://docs.currents.dev/resources/integrations/github/github-app) sets a commit status of **Pending** while the tests run, then **Failed** or **Passed** when they finish. That status check is what lets your tests be the merge gate.

  ![Currents test statuses failing a pull request's GitHub checks](/img/posts/how-currents-solves-verification-engineering/github-commit-status.png)
* It also posts a run summary as a PR comment: the counts for each group, the failed test, its error, and its history over the last 30 days. You can post it on every run, or only when there are failures.

  ![Currents run summary on a pull request, with the failed test, its error and its 30-day history](/img/posts/how-currents-solves-verification-engineering/github-pr-run-summary-comment.png)
* **In Slack.** The [Slack App](https://docs.currents.dev/resources/integrations/slack/slack-app) posts the run results to a channel. You pick when: **always**, **only on failures**, **only on failed or flaky tests**, or **only when everything passes**. Failed-test messages carry the "**Fix with AI"** button, of course.

  ![Slack App settings: send run results only when there are failures on main](/img/posts/how-currents-solves-verification-engineering/slack-run-results.png)
* **To an agent.** The Github run comment and the Slack failed-test messages both have **Fix with AI:** a link for you and a prompt for your agent. The agent reads the full failure context from that link, without needing any credentials from you.

  ![Fix with AI on a run comment: a link for you, a prompt for your agent](/img/posts/how-currents-solves-verification-engineering/fix-with-ai-github-comment.png)
  * What this means in practice is that
    * **Your agent fetches the evidence itself**: it gets the run's errors and steps, the test's history, and its traces, screenshots, videos and attachments. It reads the trace one piece at a time through the [Trace API](https://docs.currents.dev/ai/reference/trace-api). Nobody opens a dashboard or pastes a stack trace for it.
    * **It fixes, pushes and checks again.** The agent pushes a fix, CI runs, and Currents records the new run. The agent finds that run by its branch and reads the result. If a test still fails, it goes again, until the run is green.
    * **Green means something:** Currents keeps the suite reliable, so the agent can trust the verdict. Rules quarantine known flakes, and test history separates a new failure from an old flake. So the agent fixes real bugs, and a green run is a result you can actually trust.
* **In your tracker.** From a failed test, you create a [Jira](https://docs.currents.dev/resources/integrations/jira) or [Linear](https://docs.currents.dev/resources/integrations/linear) issue, or link the failure to an existing one. The issue gets the error, the commit and branch, and links back to Currents.

  ![An issue created from a failed test, with its error, commit and branch](/img/posts/how-currents-solves-verification-engineering/create-jira-issue-from-failed-test.png)
* **Everywhere else.** [HTTP webhooks](https://docs.currents.dev/resources/integrations/http-webhooks) send an event when a run starts, finishes, times out or is canceled. Each event has the commit, branch, author, and the pass, fail and flaky counts. The [REST API](https://docs.currents.dev/api/readme) covers everything else for your own scripts.
* [Automated reports](https://docs.currents.dev/dashboard/automated-reports) email the failure rate, duration and flakiness of each spec and test, daily, every 3 days, or weekly, based on what you choose.

A human still makes the calls that need judgment: is it a bug, should the agent fix it, should it merge. But nobody has to open a failed run just to route it, so verification keeps up, even at agent volume.

## One failure, end to end

Features in a list are one thing but how these Currents features work together?
Here's what that looks like, on a single failed test in an agent's PR.

![A failed test is either quarantined as a known flake or fixed by an agent, then merges on evidence](/img/posts/how-currents-solves-verification-engineering/one-failure-end-to-end.png)

A failed test takes one of two paths, and neither needs a human:

* **It's a known flake:** A quarantine rule keeps it out of the gate until its expiry date. The owner gets a notification, and the run passes on the tests that matter.
* **It's a real failure:** The 'Fix with AI' link lands on the PR and in Slack. The agent reads the context through MCP and the Trace API, pushes a fix, and CI runs again, with fail fast and orchestration keeping that round short.

People still come in at two points. Either when someone sets the quarantine rule and its expiry, or approves one that an agent proposed, or when someone reviews the PR if it touches anything on the high-risk list.

## The 5 changes, with Currents in play

I ended my previous article with 5 changes that engineering teams can make today, without any new tools. They still hold, but now Currents makes each one easier to keep:

| The change | What Currents gives you | Docs |
| -- | -- | -- |
| Write down which changes still need a human review | The GitHub commit status makes the test run the merge gate for everything that isn't on the list. The list itself is your call. | [GitHub App](https://docs.currents.dev/resources/integrations/github/github-app) |
| Give the test suite an owner and targets | Analytics charts run duration and flakiness over time. Automated reports send failure rate, duration and flakiness to the owner every day, every 3 days, or every week. | [Analytics](https://docs.currents.dev/dashboard/analytics), [Automated reports](https://docs.currents.dev/dashboard/automated-reports) |
| Measure the loop, not the output | Run duration, run status and flakiness charts filter by branch, author and tag, and export to CSV or JSON. Agents can read the same metrics through the MCP tool `currents-get-project-insights`. | [Analytics](https://docs.currents.dev/dashboard/analytics), [MCP server](https://docs.currents.dev/ai/reference/mcp-server) |
| Quarantine flaky tests with an owner and an expiry date | Quarantine actions with an expiry date, notifications before they expire, the Affected Tests tab, and an Actions admin role. | [Currents Actions](https://docs.currents.dev/guides/currents-actions/using-currents-actions) |
| Review test changes separately from code changes | This one is mostly outside Currents. Use [CODEOWNERS](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners) on your test folders. | [Test History](https://docs.currents.dev/dashboard/tests/test-history) |

One detail for that last row: Test History matches a test by its spec file, project and title. If an agent renames a test or moves it to another file, that test starts a fresh history, and its flaky past disappears from view. So treat a rename as a test change, and send it to a human like any other.

## Where this leaves you

In the previous article, I said that the value of humans in the software loop has shifted:

* from writing code to describing what needs to be done
* from reading diffs to making sure the evidence matches
* from fixing failing tests to building systems that handle hand-offs without a human

Currents is purpose-built for this. It keeps the record of every run, gets the verdict back faster, keeps flaky tests from deciding what merges, hands the evidence to whoever acts next, person or agent, and runs the routine hand-offs by rule.

The first part, describing what to build, is still yours. And to be fair, that's the part of the job worth keeping!

This is the new phase of Software Engineering. Do it right and you'll be able to scale to thousands of PRs a week. Those teams that will make this leap will reap the benefits of the productivity increase, those that don't will become dinosaurs.

That is what the future holds.

And from where we're at, it is incredibly, incredibly exciting!


---

## About the author

**Sumit Saurabh**, Senior DevRel. Sumit Saurabh is our Senior Developer Relations Engineer who writes hands-on guides for developers. He covers CI pipelines, test automation and the tooling that keeps them fast and affordable.

LinkedIn: https://www.linkedin.com/in/sumitsaurabh927/
