---
title: "Kernel"
description: "Run agent-qa web tests in Kernel cloud browsers: install the Kernel plugin, add a remote, use browser pools and read-only profiles, and fix refused sessions."
canonical_url: "https://vostride.com/docs/agent-qa/plugins/kernel"
md_url: "https://vostride.com/docs/agent-qa/plugins/kernel.md"
last_updated: "2026-11-07T15:25:39+05:30"
---

> [Documentation index](https://vostride.com/docs.md) · [Site index](https://vostride.com/llms.txt)
> Follow the Markdown links to read individual pages; the indexes list the available documentation.

# Kernel

> Run agent-qa web tests in Kernel cloud browsers: install the Kernel plugin, add a remote, use browser pools and read-only profiles, and fix refused sessions.

The Kernel plugin, `@vostride/agent-qa-plugin-kernel`, gives each web test a [Kernel](https://www.kernel.sh) cloud browser. Before the test connects, it creates a browser, or takes one from a browser pool, and hands agent-qa the browser's CDP address. After the test it deletes the browser, or returns it to the pool.

Kernel runs Chromium only, so tests on a Kernel remote use `use.browser.name: chromium`.

## Install
Install the plugin at exactly the version of agent-qa your project runs:

```bash
npm install --save-dev --save-exact @vostride/agent-qa-plugin-kernel@$(npx agent-qa --version)
```

## Configure
```yaml
plugins:
  - name: kernel
    package: "@vostride/agent-qa-plugin-kernel"
    options:
      apiKey: "{{secret:KERNEL_API_KEY}}"

registry:
  remotes:
    - name: kernel
      plugin: kernel
      settings:
        headless: true
        timeoutSeconds: 60

use:
  browser:
    name: chromium
    headless: true
    remote: kernel
```

Put the key in your secrets file, `.env.secrets.local` by default, as `KERNEL_API_KEY=...`. Set `use.browser.remote` in the config to run every web test on Kernel, or in a suite or test to move only those.

## Options
Options belong to the `plugins` entry and describe the account.

| Option | Default | Meaning |
| --- | --- | --- |
| `apiKey` | required | The Kernel API key, a credential. Write it as a `{{secret:NAME}}` reference. |
| `apiUrl` | `https://api.onkernel.com` | Kernel's API. It must use `https://` with no user or password, unless it points at this machine. |

The key is sent only as the `Authorization: Bearer` header, and never appears in logs or run records.

## Settings
Settings belong to each remote and describe one place.

| Setting | Default | Meaning |
| --- | --- | --- |
| `headless` | `true` | `false` gives a headful browser. Kernel's own default is headful. |
| `timeoutSeconds` | `60` | Seconds Kernel keeps the browser after agent-qa's connection drops, from 10 to 259200. |
| `stealth` | | Kernel's stealth mode. |
| `region` | | The Kernel region, such as `eu-west`. |
| `proxy` | | Kernel's proxy object, sent as given. |
| `viewport` | | `width`, `height` and an optional `refreshRate`. |
| `pool` | | A browser pool's ID or name, to take a browser from instead of creating one. |
| `profile` | | A profile's name, or `{ id: <profile id> }`, loaded read-only. Needs `context: reuse`. |
| `extra` | | Any other field of Kernel's create request, merged last. |

## How the request is built
The plugin builds Kernel's create request in three layers, each overriding the one before:

1. its defaults, `headless: true` and `timeout_seconds: 60`;
2. the settings above, in Kernel's field names, so `timeoutSeconds` is sent as `timeout_seconds` and `viewport.refreshRate` as `viewport.refresh_rate`;
3. `extra`, last, so a field there overrides both a default and a setting.

For example, `settings: { headless: true, extra: { headless: false, kiosk_mode: true } }` creates a headful browser in kiosk mode.

## Browser pools
A pool keeps browsers warm, so a test does not wait for one to start. Name the pool on a remote:

```yaml
registry:
  remotes:
    - name: kernel-pool
      plugin: kernel
      settings:
        pool: shop-tests
```

- While the pool is empty, the plugin keeps asking, at most once a second, and agent-qa prints `waiting for pool shop-tests` while it waits. The wait ends when a browser is free or at the remote's `connectTimeout`, five minutes by default.
- The pool's own configuration decides the browser, so `stealth`, `region`, `proxy` and `viewport` are refused on a remote with `pool`, and `headless` and `timeoutSeconds` do not apply. Only `profile` and `extra` are sent.
- After a test in a new context, the browser goes back to the pool for the next test. After a test with `context: reuse`, it is discarded, so the next test gets a clean one.

## Signed-in profiles
`profile` loads a Kernel profile, such as one saved with a signed-in test user. It loads read-only: nothing a test does is saved back. A profile lives in the browser's first context, so the remote needs `context: reuse`:

```yaml
registry:
  remotes:
    - name: kernel-signed-in
      plugin: kernel
      context: reuse
      settings:
        profile: shop-test-user
```

Without `context: reuse`, the remote is refused with kind `refused` at `settings.profile`. With `pool`, the profile goes into the pool request, and Kernel discards that browser after the test.

## Links and the live view
Kernel has no page per session, so a Kernel test shows no session link. A headful browser's live view URL carries a token, so agent-qa masks it along with the CDP address, and never shows it as a link.

## Account check
`agent-qa doctor` runs the plugin's account check, which creates no browser:

- it lists your browsers to confirm the key works, and warns `the API key was refused` when Kernel refuses it;
- it reports free sessions, such as `3 of 5 concurrent sessions free`, when the key may read the organization's limits;
- it looks up each pool a remote names, and warns `pool <pool> not found` when Kernel has none by that name.

## When a remote is refused
| Kind | Cause | Fix |
| --- | --- | --- |
| `auth` | Kernel responded with 401 or 403. | Check the key in your secrets file. |
| `capacity` | Kernel responded with 429 or 529: no free sessions, or a rate limit. | Wait, lower `use.workers`, or use a pool. |
| `refused` at `settings.profile` | The remote sets `profile` without `context: reuse`. | Add `context: reuse` to the remote. |
| `refused` at another `settings.` path | That setting is wrong for this remote, such as `region` with `pool`. | Fix the setting the line names. |
| `unreachable` | Kernel did not respond. | Check the network and `apiUrl`. |

Each refusal is one line with Kernel's status, the request and Kernel's message, and the wait Kernel asked for on a 429. A browser that is already gone when the plugin deletes it counts as released.

`npx agent-qa plugins describe kernel --json` lists every option and setting with its type, default and description.

## Documentation navigation

- [All documentation](https://vostride.com/docs.md)
- Parent: [Plugins](https://vostride.com/docs/agent-qa/plugins.md)
- Previous: [Hyperbrowser](https://vostride.com/docs/agent-qa/plugins/hyperbrowser.md)
- Next: [Steel](https://vostride.com/docs/agent-qa/plugins/steel.md)
