Natural language
Write “log in as the finance user, open the invoice list and check the totals add up” rather than a selector for every button along the way.
An agent drives a real browser inside your own network, and judges the outcome.
Self-hostable · AGPL-3.0 · Bring your own model provider
The api contract, the database schema and the runner protocol all still change. Production images and a Helm chart already exist.
See what's shippedWrite “log in as the finance user, open the invoice list and check the totals add up” rather than a selector for every button along the way.
Runs happen on a runner you install yourself, so the browser can reach an application the internet cannot.
AGPL-3.0, a Helm chart and signed images. Running it inside your company asks nothing of you.
How it works
Describe the case in prose, the way you would explain it to someone joining the team.
A model parses your prose into atomic instructions — each one an action, an assertion or a routine. Edit, reorder or disable any of them.
A runner inside your network claims the job, drives Chromium and reports progress back. Nothing dials in.
Pass or fail, with a screenshot, the model's reasoning, timings and token counts for every step.
Product
Authoring
A test case keeps the prompt you wrote and the instructions it parsed into. Edit an instruction inline, reorder it, mark it optional, disable it, or change the prompt and regenerate the lot. There is nothing to keep in sync when the markup changes, because there is no markup in the test.
Reuse
Logging in should not be re-derived by a model on every run. A routine is a named, deterministic sequence — navigate, click, fill, wait — with declared inputs resolved at run time. Test users hold the personas those inputs come from: credentials, roles and whatever metadata your app needs.
Scale
Order the members, choose whether each starts in a fresh browser or shares one, and decide whether a failure stops the suite or lets the rest continue. Weights and capacity keep a large suite from swamping a small runner — a suite is never too big for a runner, only slower on a small one.
Results
A run is not just a red or green bar. Open any step to see the screenshot the agent was looking at, the reasoning it gave, how long it took, how many tokens it spent and how many computer-use iterations it needed to get there.
Operations
Create a runner and you get a token, shown once, and a docker run command ready to paste. Groups decide which runners may take an application's work — a runner in the DMZ cannot reach an application behind the VPN, and groups are how you say so.
Security
A runner never accepts a connection. The only thing your firewall has to allow is outbound HTTPS to asserty.
Model calls are proxied through the api and credentials are injected server-side, so no api key is ever on a machine in your network — and no model endpoint has to be allow-listed either.
The runner holds no database, no driver and no volume. The container is disposable; recreating it changes nothing.
It cannot be read back after creation — the server keeps only a hash. Rotation is the revocation mechanism, and the old token dies immediately.
Separation between organizations is enforced by a Hibernate @TenantId discriminator at the persistence layer, not by a check each controller has to remember to make.
Every image ships with a signature, a build provenance attestation and an SPDX SBOM. One gh attestation verify tells you what you are about to run inside your network.
A corporate proxy is the ordinary case here, not an edge case. HTTPS_PROXY and NO_PROXY are honoured by both the api connection and the browser, and your corporate root CA is added to the standard trust store, never substituted for it.
Self-host
asserty is AGPL-3.0. Running it — for yourself, inside your company, against whatever applications you like — asks nothing of you. There is a Helm chart, a deployment runbook and published images for every component.
Start a runner
docker run -d --restart unless-stopped \
-e ASSERTY_API_URL=https://app.asserty.ai \
-e ASSERTY_RUNNER_TOKEN=<your-token> \
ghcr.io/grnrb/asserty-runner:latest The token is shown once when you create the runner, and the app hands you this command with it already filled in.
FAQ
Only to allow outbound HTTPS to asserty, if you do not already. The runner opens the connection and holds it; nothing from outside ever dials into your network, and there is no tunnel and no exposed environment.
The run stays pending. Nothing is lost, and it starts the moment a runner connects. Waiting is the point — the alternative is executing it somewhere that cannot reach the application.
OpenAI, Azure OpenAI and Anthropic. You supply the key, it is stored write-only and never read back, and you can map a different provider to each application.
There is no markup in the test, so there is nothing to keep in sync when the markup changes. A test describes intent; the agent works out how to satisfy it against whatever is on screen.
Yes. Each application declares the domains the browser is allowed to navigate to, along with a ceiling on computer-use iterations and per-instruction, connection and request timeouts.
Yes, and today that is the main way to run it. The repository ships a Helm chart and a deployment runbook covering Kubernetes, ingress, TLS and a managed Postgres.
There is no pricing yet. asserty is pre-1.0 and self-hosting is free under the AGPL — your only cost is the infrastructure you run it on and the model provider key you bring.
Not yet. asserty is pre-1.0: the api contract, the database schema and the runner protocol all still change between releases. Production images and a Helm chart do exist, and upgrades to the runner happen on your schedule, not ours.
Start in the hosted app, or clone the repository and run the whole stack yourself.