GPU Compute / Integrations
Build a coding-agent platform on Badgr
How to use Badgr's Agent Job — one of several job types on the Compute API — to build a product like Stripe's Minions: a Slack command or GitHub issue goes in, a reviewable pull request comes out. Badgr runs the coding agent in an isolated environment; you own the trigger, the prompt, and what happens with the result.
1. What is an Agent Job?
An Agent Job is a managed coding-agent run. Give Badgr a repository, an instruction, an agent, and a check; Badgr runs it in an isolated environment and returns the result — status, cost, logs, and the diff the agent produced.
Badgr supplies
- Isolated execution environment (disposable VM)
- Repository checkout (public GitHub URL + ref)
- Agent runtime (cline, claude, codex, or playwright)
- Credential resolution and injection
- Cost cap, runtime cap, cancel
- Logs, status, git patch capture
- Teardown and billing settlement
You supply
- Trigger (Slack command, GitHub issue, web UI)
- Instruction / prompt construction
- Which agent and which check to run
- Approval / policy rules
- Applying the patch and opening the PR
- Your own product UI
agent is one job type among several on the same Jobs API — custom.run, model.serve, train.lora, and comfy.batch cover other workloads. See /docs/compute-api for the rest — this guide covers agent only.
2. Create one
badgr job <agent> "<instruction>" --check "<command>"POST /v1/jobs — type: "agent"aibadgr.com/dashboard/jobs/new?type=agentcurl https://aibadgr.com/v1/jobs \
-H "Authorization: Bearer $BADGR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "agent",
"input": {
"repository": "https://github.com/acme/payments",
"ref": "main",
"agent": "claude-code",
"instruction": "Fix ISSUE-482 and add a regression test.",
"check": "npm test"
},
"policy": { "max_cost": 5, "max_runtime_minutes": 30 }
}'
# => 201
# { "job_id": "job_abc123", "type": "agent", "status": "queued", ... }Required: repository (a github.com URL), instruction, agent, and check. agent accepts claude-code (aliased to claude), claude, codex, or cline for coding, and playwright for browser tasks. Model credentials resolve server-side from your account by default (cline needs no credential at all); pass an explicit provider to override — claude only accepts anthropic. policy.max_cost defaults to $2.00, policy.max_runtime_minutes to 30 — the job tears down automatically once either is hit.
3. What happens during execution
The job is queued, a VM is provisioned, Badgr clones repository at ref, injects the resolved model credential as an env var, runs the agent against the instruction, then runs your check command — the job only reports success if the agent finished and the check exited 0. The runner captures a git patch of whatever the agent changed, then tears the environment down and settles billing.
queuedAccepted, waiting for a VMprovisioningVM being allocatedrunningAgent running, then the check commandcompletedAgent + check both finished; billing stoppedfailedAgent errored or check exited non-zerocanceledStopped via POST /v1/jobs/{id}/cancel4. Monitor it
Poll GET /v1/jobs/{id} for status, cost, and progress — there's no webhook delivery yet, so polling is the integration pattern today (the CLI does the same thing under badgr job's wait behavior).
curl https://aibadgr.com/v1/jobs/job_abc123 \
-H "Authorization: Bearer $BADGR_API_KEY"
# {
# "job_id": "job_abc123",
# "type": "agent",
# "status": "running",
# "stage": "running",
# "elapsed_seconds": 192,
# "charged_usd": 0.18,
# "files": null, # populated once the agent has made changes
# "receipt": {
# "ai_provider": "anthropic",
# "ai_model": "claude-sonnet-...",
# "billing_source": "byok"
# }
# }
curl https://aibadgr.com/v1/jobs/job_abc123/logs \
-H "Authorization: Bearer $BADGR_API_KEY"
# → { "job_id": "job_abc123", "logs": "..." } (credentials redacted)Cancel a running job (and stop billing) with POST /v1/jobs/{id}/cancel.
5. Retrieve the result
The useful output isn't "the agent finished" — it's the patch. Changed file paths come back inline on the job; the full diff is a separate endpoint because it can be large:
curl https://aibadgr.com/v1/jobs/job_abc123 \
-H "Authorization: Bearer $BADGR_API_KEY"
# → "files": ["src/checkout.ts", "tests/checkout.test.ts"]
# → "output": { "exit_code": 0 } # 0 means the check command passed
curl https://aibadgr.com/v1/jobs/job_abc123/diff \
-H "Authorization: Bearer $BADGR_API_KEY"
# → { "job_id": "job_abc123", "patch_text": "diff --git a/src/checkout.ts ..." }From the CLI, the equivalent is badgr pull <id> — it downloads the patch, checks whether your local files touch the same lines, and refuses to overwrite a conflict by default (--diff-only to inspect, --branch to apply on a new local branch).
6. Retries and follow-ups
If a job fails or needs another pass, submit a new job with parent_job_id — any field you omit is copied from the parent (repository, ref, agent, provider, model, check, instruction). The original job is immutable — never modified by a retry.
curl https://aibadgr.com/v1/jobs \
-H "Authorization: Bearer $BADGR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "agent",
"parent_job_id": "job_abc123",
"retry_reason": "retry_more_time",
"input": { "instruction": "The tests still fail on the async path — fix that too." },
"policy": { "max_cost": 5, "max_runtime_minutes": 45 }
}'retry_reason is required with parent_job_id and must be one of retry, retry_more_time, follow_up.
7. Build something real: a Slack-triggered fix
The end-to-end shape: a Slack command or GitHub issue triggers a job, you poll it to completion, then apply the patch and open your own PR.
# 1. Trigger arrives: "@bot fix ISSUE-482"
job=$(curl -s https://aibadgr.com/v1/jobs \
-H "Authorization: Bearer $BADGR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "agent",
"input": {
"repository": "https://github.com/acme/payments",
"agent": "claude-code",
"instruction": "Fix ISSUE-482 and add a regression test.",
"check": "npm test"
},
"policy": { "max_cost": 5, "max_runtime_minutes": 30 }
}')
job_id=$(echo "$job" | jq -r .job_id)
# 2. Poll until terminal
while true; do
status=$(curl -s https://aibadgr.com/v1/jobs/$job_id \
-H "Authorization: Bearer $BADGR_API_KEY" | jq -r .status)
[[ "$status" =~ ^(completed|failed|canceled)$ ]] && break
sleep 5
done
# 3. Pull the patch and open your own PR (your GitHub integration, not Badgr's)
curl -s https://aibadgr.com/v1/jobs/$job_id/diff \
-H "Authorization: Bearer $BADGR_API_KEY" | jq -r .patch_text > fix.patch
git checkout -b fix/issue-482
git apply fix.patch
git commit -am "Fix ISSUE-482"
git push origin fix/issue-482
# → open the PR with your own GitHub API call, then reply in Slack with the link8. Badgr's boundary
Badgr
execution + isolation + credentials + limits + artifacts
You
trigger + orchestration + approvals + PR workflow + product UI
Two things this doesn't do today: Badgr never opens the PR for you (fetch the patch and push it yourself), and there's no human-takeover / live-terminal access into a running job — an agent job is unattended start to finish.