Skip to main content

Copy this into your coding agent

Paste into Cursor, Codex, Claude Code, or another coding agent in your project.
CI runs your tests automatically when someone opens or updates a pull request. Bench can record these runs and check application outcomes in all four languages. Installing the SDK does not create a CI workflow or a required PR check.

Prepare the test suite

Complete your language setup and commit its dependency lockfile. Use the public installation command from your language guide. Keep the same SDK version locally and in CI. For JavaScript and TypeScript, create the cases and application adapter described in real app testing. Keep the same cases, business criteria and test data when comparing a change. Include at least one normal task, one reproduced failure and one previously working behavior. The following ESM script expects your tests/bench-suite.mjs to export createBenchSuite(bench). That is your application adapter, not an SDK export. It returns contextRevision, cases, run, and, when needed, observe and timeoutMs. Pass the same Bench instance to your instrumented application. Save as scripts/bench-ci.mjs:
For scripted conversations, call bench.simulateSystem with your session adapter instead. The report and pass/fail gate have the same shape. A failed check can still have summary.status: 'completed', so checking that field alone is not enough.

Add a GitHub Actions job

Set BENCH_API_KEY as a repository secret and BENCH_API_BASE_URL as a repository variable using the values from Bench. The default SDK key is sufficient for tracing and saving application reports. These operations do not consume Bench evaluations. Your application’s model calls can still have provider costs. Save as .github/workflows/bench.yml, alongside your existing tests:
The source revision records the commit actually checked out by CI. On a pull request, that can be GitHub’s test merge commit. Add this job as a required check in your repository rules if failed outcomes should block merging. GitHub does not supply repository secrets to forked pull requests or Dependabot runs. This script fails clearly when the key is missing. Use a reviewed, trusted run for those contributions; never switch to pull_request_target to execute untrusted PR code with secrets. See GitHub’s secrets documentation.

Python, Go and Rust

Call the native real app test or simulation helper from your existing test runner. Read actual test database or tool state, assert that the report passed, and save the redacted report as a CI artifact. Use the same cases and revisions when comparing a change. Set the client environment to ci. For Python, require report["summary"]["status"] == "completed" and every case to have status == "passed". In Go, require report.Passed(); in Rust, require report.passed(). Check errors returned by the helper before accepting a report. A failed, cancelled, timed-out or incomplete suite must fail the job. You can also keep ordinary tracing around existing tests. Flush those traces before exit and inspect delivery statistics separately from test assertions.

Verify the setup

  1. Run a correct fixture and confirm the job passes.
  2. Change one expected outcome and confirm the job fails with a saved report.
  3. Remove an assertion or force a timeout and confirm incomplete work cannot pass.
  4. Restore the case, rerun, and inspect the saved report artifact.
To display a report under Real app testing, explicitly publish it with your language’s report helper and the correct system ID. Uploading an Actions artifact alone does not publish it to Bench. See real app testing for the language guides, report limits and examples. Real app test helpers capture spans inside the report in all four languages. Flushing does not upload those spans as production events. Ordinary tracing outside the helper sends events you can find in Bench’s ci environment.