bugzero

~/docs/getting-started

Getting started

bugzero is an AI bug-fixing agent and the control room to run it. When something breaks — reported by Sentry, PostHog or your own app through a webhook — the agent runs in your own GitHub Actions and opens a pull request with a fix; you steer it from one dashboard. Your code never leaves your infrastructure. Here's everything you need to set up, and why each step matters.

01 the loop

How an error becomes a pull request.

02 required setup

7 steps to your first fix.

[01]

Create your account

required

Sign up with your email and a password. You'll get a team workspace on the Free plan — 5 fixes a month, no card required.

// whyEverything in bugzero is scoped to a team, so you can invite colleagues later and share integrations, the agent's setup and billing. Free lets you see real fixes before you pay anything.
create your account →
[02]

Connect GitHub

required

On the Integrations page, install the bugzero GitHub App, choose the account or organization, and select the repositories bugzero may start fixes in.

// whyThe bugzero GitHub App has no access to your code — its only permission is to start the bugzero workflow in your own GitHub Actions. The fix and the pull request are made by that workflow, inside your runner. Nothing is merged or deployed automatically.
open integrations →
[03]

Connect an error source

required

On Integrations → Error sources, connect the error tracker you already use and pick the projects bugzero should watch, or send errors from your own app. You can use more than one source.

  • Sentry — connect your organization via OAuth.
  • PostHog — pick your region and paste a personal API key with the project:read, hog_function:write and query:read scopes.
  • Custom webhook — create an endpoint for each app and send errors to its secret URL from any language or tool; see Custom webhook below.
// whyNew errors are the trigger for everything bugzero does. For Sentry and PostHog, bugzero sets up the alert or webhook for each mapped project itself — no manual webhook or signing secret. A custom webhook works the other way around: it's a URL you call yourself whenever your app catches an error. Either way, you choose what's watched, so fixes stay on the services you care about.
open integrations →
[04]

Map each project to a repository

required

For every project you watch, choose the GitHub repository the agent should fix. You set this right next to each project on the Integrations page. A custom webhook endpoint gets its repository when you create it.

// whyThis is the link that makes the whole pipeline work. bugzero has to know which codebase belongs to which project — without a mapping, errors come in but no pull requests go out. It's the most commonly missed step.
open integrations →
[05]

Add the bugzero workflow

required

In Integrations → Runner setup, click Add workflow next to each repository. GitHub opens with .github/workflows/bugzero.yml prefilled — review it and commit it to your default branch. Then click Check again.

// whyThis workflow is what actually runs the fix. When an error fires, bugzero starts it in your own GitHub Actions runner, where the agent reads your code and opens the pull request — so your source never leaves your infrastructure. You add the file yourself because bugzero can't write to your repository.
open integrations →
[06]

Add your AI key as an Actions secret

required

In each connected repository, open Settings → Secrets and variables → Actions and add a new secret named ANTHROPIC_API_KEY (or OPENAI_API_KEY) holding your own AI key.

// whyThe agent uses this key while it runs inside your GitHub Actions runner, so you pay your AI provider directly and bugzero never sees the key. It stays a GitHub Actions secret in your repository and never touches our servers.
[07]

Let Actions open pull requests

required

In each connected repository, open Settings → Actions → General, scroll to Workflow permissions, tick Allow GitHub Actions to create and approve pull requests and save. If the option is greyed out, an organization owner has to allow it under the organization's own Settings → Actions → General first.

// whyGitHub keeps this off by default, and the workflow's own pull-requests: write permission can't override it. Without it the agent still pushes its fix to a branch, but GitHub refuses to open the pull request — so you'd get a branch instead of a PR.
03 optional

Optional, but recommended.

[08]

Limit to the right environments

optional

On each project mapping, tick the environments to react to — for example production only. Leave them all unticked to watch every environment. Custom webhook endpoints have the same optional filter.

// whyYou usually don't want fixes for local, dev, or staging noise. Restricting to production keeps runs focused on real, user-facing bugs and avoids burning your monthly run limit on errors that don't matter.
open integrations →
[09]

Configure the agent

optional

On the Agent page, pick the model and effort (the latest Claude or GPT models), write instructions with your team's conventions, and set a daily safety cap. Every time you publish instructions they become a new version — compare versions, see how each one performs, and roll back in one click.

// whyInstructions make fixes follow your conventions (“use our logger”, “add a regression test”, files to leave alone), and the model and effort let you trade speed and cost for depth. Your key isn't entered here — it stays an Actions secret in your repo, so bugzero only decides how the agent runs, never pays for or sees the tokens.
open agent →
[10]

Go Pro when you're ready

optional

Free includes 5 fixes a month. When you need more, upgrade to Pro — $9/month for unlimited fixes — from Billing, and manage or cancel through the customer portal.

// whyOnly runs that open a pull request count as a fix — failed runs are never charged against you. The AI tokens are billed by your provider at cost, so the plan is all you pay bugzero.
open billing →
[11]

Get your first fix

optional

When a new error hits a watched project and environment, bugzero starts a run that ends in a pull request. Track progress on the Runs page, then open the PR, read the diff and root-cause summary, and merge if it's right.

// whyThis is the payoff, and it stays under your control: every fix is a reviewable pull request — nothing is merged or deployed until you decide it's right.
view runs →
04 custom webhook

Send errors from anything.

Errors your tracker doesn't catch — a worker, a cron job, a script — or no error tracker at all? Send them to bugzero yourself: one HTTP request from any language or tool, no SDK.

On Integrations → Error sources, add a Custom webhook endpoint for each app: a name, the repository the agent fixes, its base branch and, optionally, the environments to react to. Each endpoint gets its own secret URL.

create an endpoint →

Authenticate

The token at the end of the endpoint's URL identifies it. Call the URL as it is, or send the token in the Authorization header to the stable URL instead — better if your tooling logs URLs.

request.http
# token in the URL
POST https://bugzero.dev/api/webhooks/custom/bzc_…

# or: token in a header
POST https://bugzero.dev/api/webhooks/custom
Authorization: Bearer bzc_…

Payload

Send a JSON object with Content-Type: application/json, up to 256 KB. Only message is required.

messagestring · required
The error message.
typestring
The error class, e.g. TypeError. Default: Error.
titlestring
Replaces the default title, type: message.
stacktracestring | array
A string, or an array of lines or frames { file, line, column, function }, most recent call first.
environmentstring
Matched against the endpoint's environment filter. Events without one always pass.
fingerprintstring
Groups events of the same error (see “One fix per error” below). Default: derived from the type, the message and the top stack frame.
urlstring
A link to the error in your system (http or https), shown on the run and in the pull request.
contextobject
Any extra details for the agent (request, user, tags…), sent as JSON and clipped to 4,000 characters.
testboolean
A dry run: reports what would happen and starts nothing.

Unknown fields are ignored, null counts as absent and long text is clipped.

Examples

With curl, from a terminal or a script:

$ curl
curl -X POST "$BUGZERO_WEBHOOK_URL" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "order.customer is undefined",
    "type": "TypeError",
    "environment": "production",
    "stacktrace": [
      { "file": "src/orders/receipt.ts", "line": 42, "function": "sendReceipt" },
      { "file": "src/orders/checkout.ts", "line": 88, "function": "completeOrder" }
    ],
    "url": "https://logs.example.com/errors/8812",
    "context": { "orderId": "ord_8812", "plan": "pro" }
  }'

From Node.js, for example in a catch block:

report-error.js[ node 18+ ]
export async function reportError(error, context = {}) {
  await fetch(process.env.BUGZERO_WEBHOOK_URL, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      type: error.name,
      message: error.message || String(error),
      stacktrace: error.stack,
      environment: process.env.NODE_ENV,
      context,
    }),
    signal: AbortSignal.timeout(5000),
  }).catch(() => {});
}

try {
  await completeOrder(order);
} catch (error) {
  await reportError(error, { orderId: order.id });
  throw error;
}

One fix per error

The agent starts once per error: after the first event, events with the same fingerprint on the same endpoint are skipped, even if that run failed. If it did, fix the setup (say, a missing workflow or AI key) and click Retry on the run page.

By default, numbers and ids in the message are ignored, so “User 123 not found” and “User 456 not found” are the same error. Want a fresh fix when an error comes back in a later release? Send a fingerprint that includes the release, e.g. "send-receipt@2.4.1". It replaces the default one, so keep the rest stable — no ids or timestamps.

Test it

Add "test": true to check the URL and your payload without starting anything. The response tells you whether a real event would start the agent and, if not, why:

$ curl[ test ]
curl -X POST "$BUGZERO_WEBHOOK_URL" \
  -H "Content-Type: application/json" \
  -d '{"message": "order.customer is undefined", "test": true}'
{
  "ok": true,
  "outcome": "test",
  "wouldStart": true,
  "fingerprint": "5d0c41a7e2b9f8c3a1d6e4b2c9f07a18",
  "title": "Error: order.customer is undefined"
}

Responses

Every response is JSON. Retry only on a 5xx: the same error never starts the agent twice, so retrying is safe.

202 outcome: "started"
The agent started. The body includes the run's runId and status.
200 outcome: "skipped"
Nothing started; reason says why (see below).
200 outcome: "test"
A dry run; nothing started (see “Test it”).
400 error: "invalid_json"
The body isn't valid JSON.
400 error: "invalid_payload"
A field is missing or has the wrong type; issues lists each problem with its path.
401 error: "unauthorized"
Unknown token: check the URL — or the endpoint got a new URL or was deleted.
413 error: "payload_too_large"
The body is over 256 KB.
5xx
Something failed on our side. Safe to retry.
reason: "duplicate"
This error was already handled; runId is its run.
reason: "environment"
The event's environment isn't in the endpoint's filter.
reason: "repo_not_connected"
The endpoint's repository isn't selected in the GitHub card.
reason: "limit"
The monthly Free limit or the daily safety cap was reached; code is free_limit or daily_cap.

Keep the token secret

  • Send events from your server only, never from a browser — anyone could read the token there.
  • If your proxies or logs record URLs, send the token in the Authorization header instead.
  • If the URL leaks, generate a new one for the endpoint; the old one stops working immediately.
  • Everything you send is stored with the run and shown to the AI agent, so leave out passwords, keys and personal data.
05 troubleshooting

Set everything up but no pull requests?

Almost always one of these:

$ bugzero doctor[ 8 checks ]
  • No project → repo mapping yet (step 04) — the single most common cause.
  • The bugzero workflow isn't on the default branch, or the ANTHROPIC_API_KEY / OPENAI_API_KEY secret is missing (steps 05 and 06). Failed runs show the reason on the run page.
  • The fix was pushed to a branch but no pull request opened — GitHub doesn't let Actions create them (step 07).
  • The error's environment isn't in your watched list (step 08).
  • No new error has occurred yet — bugzero reacts to new issues, not historical ones.
  • You've used Free's 5 fixes this month, or the daily safety cap was reached — check the Dashboard.
  • The repository isn't selected in the GitHub card (step 02).
  • Sending errors to a custom webhook? Its JSON response says why an event was skipped; add "test": true to check without starting anything.
next

Ready to set up?

Create your account and connect your first repository — Free includes 5 fixes a month.