Skip to content

OpenAI Codex

The Codex SDK is a local Node.js library that shells out to the codex binary, with no remote API to call. Beeps integrates with Codex by triggering a workflow_dispatch GitHub Actions run in your repository; the workflow uses openai/codex-action to run Codex, opens a PR, and beeps polls the workflow run and resolves the PR by branch.

  • A GitHub repository where Codex can run and open PRs.
  • A workflow file in that repo (template below).
  • An OPENAI_API_KEY stored as a GitHub Actions secret in the repo. (Codex Web / Codex Cloud requires ChatGPT login and is not supported here; only the API-key path is.)
  • A fine-grained GitHub PAT with these permissions on the target repo:
    • actions: write (to trigger the workflow)
    • actions: read (to poll the workflow run)
    • pull-requests: read (to resolve the PR URL)

Drop this into .github/workflows/codex-beeps.yml. The run-name line is required so beeps can locate the run it triggered:

name: Codex (Beeps)
run-name: "Beeps codex run ${{ inputs.dispatchId }}"
on:
workflow_dispatch:
inputs:
prompt:
required: true
type: string
branch:
required: true
type: string
dispatchId:
required: true
type: string
alertId:
required: false
type: string
jobs:
codex:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: openai/codex-action@v1
with:
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
prompt: ${{ inputs.prompt }}
- name: Open PR with changes
uses: peter-evans/create-pull-request@v6
with:
branch: ${{ inputs.branch }}
title: "Codex: ${{ inputs.alertId }}"
body: |
Triggered by beeps alert `${{ inputs.alertId }}`.
${{ inputs.prompt }}
commit-message: "fix: codex response for ${{ inputs.alertId }}"

Create a fine-grained PAT scoped to the repo with the permissions listed in Prerequisites. Save it; you’ll paste it into beeps as apiKey.

Create the integration with the PAT and repo coordinates:

const codexIntegration = await client.integration.create({
name: "Codex - acme/monorepo",
provider: "codex",
apiKey: process.env.GITHUB_PAT,
metadata: {
githubOwner: "acme",
githubRepo: "monorepo",
workflowFileName: "codex-beeps.yml",
defaultBranch: "main",
branchPrefix: "codex-beeps",
},
});

Reference it from a relay rule. Workflow runs typically take a few minutes, so push pollInterval higher than the cloud-API agents:

await client.relay.rules.create(relayId, {
name: "Codex Auto-Fix",
ruleType: "agent",
config: {
agentType: "codex",
integrationId: codexIntegration.id,
pollInterval: 60000,
maxPollAttempts: 60,
},
});
FieldTypeRequiredDefaultDescription
githubOwnerstringyesGitHub org or user that owns the repo
githubRepostringyesRepo name
workflowFileNamestringyesWorkflow filename, e.g. codex-beeps.yml
defaultBranchstringnomainBranch to dispatch the workflow against
branchPrefixstringnocodex-beepsPrefix for the branch name beeps generates per dispatch

The rule needs agentType: "codex" and integrationId. The shared polling and storm-control fields are documented in Relay Rules.

Beeps reports “workflow run not found”. Your workflow file is missing the run-name: "Beeps codex run ${{ inputs.dispatchId }}" line. Without it, beeps falls back to “most recent workflow_dispatch run” matching, which is flaky under concurrency.

The PR URL never appears on the alert responder. Beeps resolves the PR by querying GET /repos/{owner}/{repo}/pulls?head={owner}:{branch}, so your workflow needs to open the PR using the inputs.branch value beeps passed in.