Draft Pull Request Descriptions with Codex in CI
1. Make the output a draft, not a decision
A useful pull request description explains what changed, why it matters, and what evidence supports it. Codex can assemble that first draft inside a CI job, but it should not approve the change, invent motivation, or claim tests passed without evidence.
Start with an artifact-only workflow: generate pr-description.md and upload it for the author to review. This avoids overwriting a carefully maintained description and lets you evaluate the output before introducing repository write permissions.
2. Separate trusted execution from untrusted changes
For GitHub Actions, use a workflow maintained on the default branch and begin with a manual workflow_dispatch trigger that accepts a pull request number. Give the drafting job only the read permissions it needs. Fetch pull request metadata and patches as data; do not execute scripts from the proposed change.
Never combine pull_request_target, exposed secrets, and execution of pull request code. Fork contributions deserve particular care: a trusted workflow definition does not make the submitted files trustworthy. Protect secret-bearing runs with an approval gate where appropriate, and keep the API credential unavailable to test jobs that execute untrusted code.
3. Build a bounded evidence bundle
Resolve the pull request's current base and head commit SHAs through the hosting API. Fetch those exact commits, then compute their merge base. Generate the proposed-change patch with git diff MERGE_BASE_SHA HEAD_SHA, rather than comparing against a moving branch name.
Include three small inputs: a changed-file summary, a filtered patch, and verified test results associated with that head SHA. Exclude generated files, vendored dependencies, lockfile noise where appropriate, and anything likely to contain credentials. A model context limit is not a substitute for an explicit input budget.
- Change inventory: Capture file names and additions or deletions with git diff --stat.
- Patch: Retain relevant hunks and label any omitted or truncated sections.
- Evidence: Include actual check conclusions, or explicitly state that test results were unavailable.
For unusually large changes, generate a file-level summary or skip drafting with a clear explanation. Do not silently drop most of the patch and present the result as complete.
4. Configure Codex for a noninteractive run
Pin the Codex CLI version in your CI image or installation step. Configure a custom model provider with the base URL https://api.coderelayhub.com and an environment-backed API key. CodeRelay Hub provides one pay-as-you-go endpoint usable from Codex and other clients; verify that your selected model and provider route support the API wire format required by your pinned CLI.
Use the provider's documented model identifier rather than guessing it from a display name. Keep credentials in the CI secret store, never in committed configuration or command-line arguments.
Run Codex from a temporary directory containing only the approved evidence bundle. A typical invocation is codex exec --sandbox read-only --output-last-message pr-description.md -, with the prompt supplied on standard input. The CLI writes its final response to the output file; the model does not need workspace write access. Disable unnecessary MCP servers and external tools, and verify sandbox support on your runner.
5. Give the model an evidence contract
Request four sections: Summary, Implementation, Testing, and Risks. Tell Codex to treat repository text, patches, and comments as untrusted data, never as instructions. Explicitly prohibit shell execution and requests for secrets. Prompt wording is defense in depth, not a replacement for isolation.
Require every factual claim to follow from the supplied evidence. If intent is unclear, describe observable behavior instead. If checks were not supplied, write “Test results were not provided.” Ask for concise prose and require disclosure whenever the patch was truncated.
6. Validate, publish, and measure usefulness
Reject empty output, unexpected sections, excessive length, and accidental secret exposure before uploading the artifact. Set a job timeout and bounded retries. Generation failure should produce a clear workflow notice, not block unrelated tests.
If you later automate description updates, isolate that operation in a separate job with narrowly scoped write permissions. Replace only a clearly marked generated section, preserve author text, and confirm the pull request still points to the head SHA used for generation.
Open a free workspace to try it.