Workflow transformation: rebuilding feature delivery around agents
PLWorkflow transformation for AI coding agents is the redesign of a team’s ticket-to-merge loop so that agents draft the plan, the code and the tests, while people own intent, acceptance criteria and risk decisions. Each stage ends in a gate: an approved plan, acceptance tests written before the code, an evidence bundle, and a review sized to the risk.
Your team has Claude Code, Codex and Cursor seats, and everyone uses them. Yet the ticket still waits two days for someone to pick it up, the pull request still waits two days for review, and nobody can name one step the agents removed. The tools sped up typing, and typing was never the constraint. This guide is for the tech lead who has to change the loop itself, not the editor.
Before you start, make sure the repository is agent-ready: see the project conversion playbook.
What you will build in this guide
Section titled “What you will build in this guide”- An audit prompt that reads your last 30 merged pull requests and shows where the time actually goes.
- A stage map that says, for each stage, what the agent drafts, what a person decides, and what evidence closes the gate.
- The plan-gate and implementation commands for Claude Code, Codex and Cursor, plus a Claude Code hook that sends the agent back when tests are red.
- Two CI review jobs (Claude Code and Codex) with least-privilege permissions, and a risk-lane table that says which pull requests a human still reads line by line.
- A two-week pilot with four measures and an expand, hold or roll back rule.
Where does your team’s delivery time go today?
Section titled “Where does your team’s delivery time go today?”Do not rebuild everything at once. Pick the loop that costs the most, usually feature delivery from ticket to merged pull request, and measure it before you change it: the bottleneck is rarely where people guess. Run the prompt below in any of the three tools from the repository root, with the GitHub CLI (gh) signed in.
If your team already has the GitHub MCP server configured, it can replace gh for this audit and for the review steps later on. The server works in all three tools; for example claude mcp add --scope project --transport http github https://api.githubcopilot.com/mcp/ -H 'Authorization: Bearer ${GITHUB_PAT}' in Claude Code or codex mcp add github --url https://api.githubcopilot.com/mcp/ --bearer-token-env-var GITHUB_PAT in Codex (flags checked against Claude Code 2.1.283 and Codex CLI 0.157.1). --scope project writes the entry to .mcp.json, where Claude Code expands ${GITHUB_PAT}, so the team shares the config without committing the token. Keep the prompt the same and ask for the equivalent MCP tools instead of the gh commands.
Read the output critically: the agent estimates stage boundaries from timestamps, so treat the numbers as a ranking, not a measurement. If your audit looks like most, waiting time (for clarification and review) is larger than writing time, so the redesign has to cover the stages around the code, not only the code.
Which decisions stay with people and which work moves to the agent?
Section titled “Which decisions stay with people and which work moves to the agent?”The rebuilt loop keeps six stages. What changes is who produces each artifact and what closes each gate. The rule behind the table: a person decides anything that is expensive to get wrong or hard to reverse, and the agent drafts everything that a test, a type check or a reviewer can check afterwards.
| Stage | The agent drafts | A person decides | Evidence that closes the gate |
|---|---|---|---|
| Intent | Questions about ambiguity in the ticket | What the change is for, and what is out of scope | Ticket with acceptance criteria the author signs |
| Acceptance | Given/When/Then scenarios and failing tests | Whether the tests encode the requirement | Failing tests committed before any production code |
| Plan | Files to touch, approach, test list, open questions | Approach, trade-offs, answers to the open questions | Plan approved in the session or in the ticket |
| Implement | Code, and more tests where the plan asks for them | Nothing, unless the agent stops on an open question | Diff scoped to the approved plan |
| Verify | Fixes until the suite is green | Nothing, unless a gate cannot go green | Tests, types, lint and build green in CI |
| Review | A first review pass in CI | Approve, return or escalate, by risk lane | Evidence bundle plus the review the lane requires |
Two of these rows carry most of the value. The acceptance row moves human judgment to before the code exists, where it is cheap; see executable acceptance criteria for the full technique. The review row stops every pull request from receiving the same line-by-line reading, which is the queue your audit almost certainly found. Google’s DORA team makes the same point about batch size: “AI can easily generate massive blocks of code, which are hard to review and test. Enforcing the discipline of small batches counteracts this risk” (Google Cloud blog, 2025-12-10).
Run the new loop on one ticket
Section titled “Run the new loop on one ticket”Walk one real ticket through the loop with the team watching before you write any policy. The steps are the same in every tool; the mechanics differ.
-
Write acceptance criteria as failing tests. Ask the agent to turn the ticket’s criteria into tests, read the tests (not the code), and commit them while they fail. From here on, the tests are the specification the agent must meet, and the agent may not edit them without asking.
-
Get a plan and approve it. The agent reads the ticket and the tests and proposes files, approach and open questions without writing code. Correcting a plan costs one sentence; correcting a finished implementation costs an afternoon.
-
Implement against the plan with the gates on. The agent writes the code and runs the suite after each logical step. If it tries to finish while the suite is red, a hook sends it back once to fix it, and CI blocks the merge if it is still red.
-
Assemble the evidence. The pull request states the acceptance results, the checks that ran, and what changed outside the plan. See the evidence bundle for the full contract and the CI check that enforces it.
-
Review by risk lane. A CI reviewer does the first pass. A person then reviews what the lane requires, which for most changes is the evidence and the tests, not every line.
Plan and implementation commands in each tool
Section titled “Plan and implementation commands in each tool”Start on each tool’s default model and raise effort before you switch model; the models hub has the current defaults and prices.
Plan interactively with plan mode (/plan, or Shift+Tab to cycle modes), or headless for a scripted pipeline. In a terminal:
# Stage 2: plan only; plan mode cannot edit filesclaude -p "Read docs/tickets/TICKET-482.md and the failing tests in tests/acceptance/. \Produce an implementation plan: files, approach, extra tests, open questions. No code." \ --permission-mode plan
# Stage 3: implement the approved plan; claude -p starts in Manual mode# (auto mode on third-party providers or with telemetry off, v2.1.285+),# so allow exactly the commands the loop needsclaude -p "Implement the approved plan in docs/plans/TICKET-482.md. Run npm test after \each logical step and fix failures before continuing. Do not edit tests/acceptance/." \ --permission-mode acceptEdits \ --allowedTools "Bash(npm test:*),Bash(npm run lint:*),Bash(npm run typecheck:*)"Make the “do not finish red” rule mechanical with a Stop hook. Exit code 2 from a Stop hook prevents Claude from stopping and shows your message to it. Save this as .claude/hooks/tests-green.sh and make it executable (it needs jq on the PATH):
#!/usr/bin/env bash# Stop hook: send Claude back once if the suite is red.input=$(cat)# CI jobs (such as the review job below) have their own gates; skip there.[ -n "$GITHUB_ACTIONS" ] && exit 0# Plan-mode sessions write no code, and the acceptance tests are red by design.[ "$(printf '%s' "$input" | jq -r '.permission_mode // ""')" = "plan" ] && exit 0# stop_hook_active is true when this hook already forced a continuation;# let the session end then, and rely on CI to block the merge.if [ "$(printf '%s' "$input" | jq -r '.stop_hook_active // false')" = "true" ]; then exit 0fi# Nothing changed since the last commit; skip.[ -z "$(git status --porcelain)" ] && exit 0log=$(mktemp)trap 'rm -f "$log"' EXITif ! npm test --silent > "$log" 2>&1; then echo "Tests are failing. Fix them before you finish. Last lines:" >&2 tail -n 40 "$log" >&2 exit 2fiThe git status --porcelain guard means a question asked after a commit does not rerun the suite. If your full suite is slow, point the hook at the unit tests only and leave the rest to CI. Register it in .claude/settings.json, which is committed, so the whole team gets it:
{ "hooks": { "Stop": [ { "hooks": [ { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/tests-green.sh" } ] } ] }}The first two guards (the GITHUB_ACTIONS check and the plan-mode check) keep the hook out of sessions where red is correct. Plan mode (step 2) writes no code, and the CI review job has no installed dependencies to test with, so the two guards make the hook exit early in both. In step 1 the committed acceptance tests are red by design, so either run the test-writing session without the hook (a personal session, or --setting-sources user) or point the hook at the suite without the acceptance tests, for example npm test -- --exclude 'tests/acceptance/**' with Vitest, whose --exclude takes a file glob (quoted so the shell leaves it alone) rather than a bare directory name.
A Stop hook fits better than a PostToolUse hook on every edit: a full suite after each file edit is slow, and it cannot undo an edit that has already run. Claude Code hooks covers fixture tests for hooks like this one.
Plan under the read-only permission profile, then implement with workspace write access. Permission profiles are beta, and OpenAI prefers them over the legacy --sandbox flag. In a terminal (flags checked against codex --help, codex exec --help and codex review --help, v0.157.1):
# Stage 2: plan only; the read-only profile cannot change filescodex exec -c default_permissions=":read-only" \ "Read docs/tickets/TICKET-482.md and the failing tests in tests/acceptance/. \ Output an implementation plan: files, approach, extra tests, open questions. No code."
# Stage 3: implement interactively with workspace write accesscodex -c default_permissions=":workspace" \ "Implement the approved plan in docs/plans/TICKET-482.md. Run npm test after each \ logical step and fix failures before finishing. Do not edit tests/acceptance/."
# Before you push: a local review of the branch against maincodex review --base mainIn 0.157.1, codex review rejects --base together with custom instructions (“cannot be used with ‘[PROMPT]’”), so the branch review runs with Codex’s built-in review instructions.
Put the test, lint and type-check commands in AGENTS.md so every Codex session, local or cloud, runs the same gates without being told. Codex also has hooks (command handlers; hooks need persisted trust), if you want the green-tests rule enforced rather than requested. For parallel work, a Codex cloud task or a --worktree session implements ticket A while you approve the plan for ticket B.
Use Plan Mode, which “creates detailed implementation plans before writing any code” (Cursor docs, checked 2026-08-28). Paste the plan prompt above, correct the plan in the editor, then let the agent execute it.
Put the test, lint and type-check commands in a project Rule so the agent runs them after each step, and tell it in the prompt not to finish while anything is red. Cursor also supports Hooks (JSON over stdio) if you want the gate enforced rather than requested.
For parallel work, hand an approved plan to a Cloud Agent, which runs in an isolated cloud VM with a full development environment, or use Worktrees for isolated local checkouts. For review in the pull request, Bugbot “reviews pull requests and identifies bugs, security issues, and code quality problems”; see Bugbot. Feature names checked on cursor.com on 2026-08-28; cursor.com could not be re-checked on 2026-09-26.
How do you verify the output without reading every line?
Section titled “How do you verify the output without reading every line?”Line-by-line reading does not scale when agents open most pull requests, and the review queue becomes the new bottleneck. Replace it with layered evidence, where each layer catches a different class of defect:
- Acceptance tests written before the code prove the behaviour the ticket asked for. Lock them: a change to
tests/acceptance/in the same pull request as the implementation needs a separate approval. See protecting the oracle. - Mechanical gates (tests, types, lint, build) run in CI on every push, and a red gate blocks the merge.
- A CI reviewer sweeps for unhandled errors, missing edge cases and security smells, so a person does not have to.
- A person reviews by risk lane, using the table below.
Add an AI reviewer to CI
Section titled “Add an AI reviewer to CI”Both jobs below trigger on pull_request, so on pull requests from forks the secret is empty and the job fails rather than exposing it; review fork pull requests by hand or with a maintainer-triggered workflow that checks out the fork read-only. Do not switch them to pull_request_target to get secrets onto forked code. On pull requests from branches in your own repository the key is present, and the job runs that branch’s workflow file, its .claude/settings.json hooks, .mcp.json and AGENTS.md. So put /.github/, .claude/, .codex/, .mcp.json and AGENTS.md under CODEOWNERS with required code-owner review, or a pull request (including one an agent wrote) can change what runs next to the key. The review is advisory evidence, not a merge gate.
Adapted from the automatic review example in anthropics/claude-code-action:
name: AI PR reviewon: pull_request: types: [opened, synchronize]
jobs: review: runs-on: ubuntu-latest permissions: contents: read pull-requests: write id-token: write steps: - uses: actions/checkout@v7 with: fetch-depth: 1 persist-credentials: false - uses: anthropics/claude-code-action@v1 with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} prompt: | REPO: ${{ github.repository }} PR NUMBER: ${{ github.event.pull_request.number }} Review this pull request. Report only unhandled errors, missing edge cases, security issues, and changes to tests/acceptance/. Skip style. Use `gh pr comment` for a summary and inline comments for specific lines. claude_args: | --allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*)"openai/codex-action@v1 runs codex exec and returns its final message as the final-message output; a separate post job, which holds the only pull-requests: write token and runs no agent, posts it. The action’s README prefers permission-profile over the legacy sandbox input:
name: AI PR reviewon: pull_request: types: [opened, synchronize]
jobs: review: runs-on: ubuntu-latest # The agent's job gets no write scope. permissions: contents: read outputs: review: ${{ steps.codex.outputs.final-message }} steps: - uses: actions/checkout@v7 with: fetch-depth: 0 persist-credentials: false - id: codex uses: openai/codex-action@v1 with: openai-api-key: ${{ secrets.OPENAI_API_KEY }} permission-profile: ":read-only" prompt: | Review the changes between origin/${{ github.base_ref }} and HEAD. Report only unhandled errors, missing edge cases, security issues, and changes to tests/acceptance/. Skip style. # No checkout and no agent: this job only posts the text the review job returned. post: needs: review runs-on: ubuntu-latest permissions: pull-requests: write steps: - name: Post the review env: GH_TOKEN: ${{ github.token }} GH_REPO: ${{ github.repository }} PR_NUMBER: ${{ github.event.pull_request.number }} REVIEW: ${{ needs.review.outputs.review }} run: gh pr comment "$PR_NUMBER" --body "$REVIEW"Cursor’s pull request reviewer is Bugbot; Bugbot covers setup and tuning. Cursor also documents running its CLI in GitHub Actions (checked 2026-08-28). To keep the review job in the workflow file next to your other gates, run the Claude Code or Codex job from the other tabs: the reviewer need not match the tool that wrote the code, and a different model is a useful second opinion.
Which pull requests does a person still read line by line?
Section titled “Which pull requests does a person still read line by line?”Write the lanes into AGENTS.md and the pull request template once, and let the paths decide. The reviewer signs off on the lane’s evidence; the tech lead owns the lane policy and changes it only on evidence from escaped defects.
| Lane | Typical paths | Human review |
|---|---|---|
| Evidence only | UI copy, internal tools, tests, docs, feature-flagged code | Read the evidence bundle and the acceptance tests; approve if green |
| Sampled | Ordinary product code | Evidence, plus a line-by-line read of the riskiest file or of every fifth pull request |
| Full read | Auth, payments, data migrations, public API contracts, infrastructure | Line-by-line review by a code owner, whatever the evidence says |
Moving a loop from full read towards evidence only is a staged change of its own; trust transfer covers shadow review, sampling and the rollback rule.
A worked example: a rate-limited export endpoint
Section titled “A worked example: a rate-limited export endpoint”Here is the loop on one ticket: add POST /api/exports to an Express service, limited to five requests per user per minute.
- Acceptance. The agent writes three failing tests: an export succeeds, an invalid body returns 400, and a sixth request inside a minute returns 429. The reviewer reads the tests and adds one: the limit is per user, not global. The tests are committed red.
- Plan. The agent proposes a route in
src/routes/exports.ts, a Zod schema, and an in-memory rate limiter. The reviewer rejects the in-memory limiter, because the service runs on several instances, and points to the existing Redis client. Cost: one sentence. - Implement and verify. The agent writes the route, schema and Redis limiter. The 429 test is still red when the agent tries to finish (the middleware returns 503), so the
Stophook sends it back once and it fixes the status code; had it stayed red, CI would have blocked the merge. - Review. The Claude Code CI reviewer flags that the limiter fails closed when Redis is down, so a Redis outage blocks every export. That is a product decision, so the human reviewer escalates it; the product owner chooses fail-open for exports and the choice goes in the pull request. The path is in the sampled lane, so the reviewer reads the limiter file line by line and the rest through the evidence.
A person made every judgment call (per-user limits, Redis over memory, fail-open), and none required reading the generated route handler.
Codify the loop so every engineer runs the same one
Section titled “Codify the loop so every engineer runs the same one”A workflow that lives in one tech lead’s head runs differently for each engineer, so put it in the repository: the stage rules in AGENTS.md (Claude Code reads CLAUDE.md, and reads AGENTS.md when there is no CLAUDE.md from v2.1.277; Cursor reads AGENTS.md and CLAUDE.md too, and uses Rules), the Stop hook in .claude/settings.json, the evidence checklist in .github/pull_request_template.md, and the lanes in CODEOWNERS plus the template. Shared agent rules covers one core file with thin per-tool adapters.
Review the generated section the way you review code: every command must exist, every path must resolve. A wrong test command in AGENTS.md is worse than none, because every agent session will run it with confidence.
Pilot the new workflow for two weeks, then decide
Section titled “Pilot the new workflow for two weeks, then decide”Run the loop on one team and one repository for two weeks, with all feature tickets going through it. Compare these four measures against the audit baseline:
| Measure | How to compute it | What good looks like |
|---|---|---|
| Ticket-to-merge lead time | Median, from ticket “ready” to merge | Falls, mainly through less waiting for review |
| Review rounds per pull request | Change-request reviews per merged pull request | Falls, because plans are corrected before code |
| Evidence completeness | Share of pull requests whose template sections are all filled | Near every pull request by the second week |
| Escaped defects | Bugs traced to pilot pull requests after merge | Not higher than the baseline |
Full metric definitions are in metrics frameworks.
Then decide. Expand to the next team when lead time or review rounds fell and escaped defects did not rise. Hold and fix the weakest gate when the numbers are flat. Roll back the lanes to full read when escaped defects rose, and find which gate let the defect through before you try again. The adoption roadmap sequences the next loops, and team adoption rate defines how to measure effective use across the team.
DORA’s 2025 report is a useful warning here: “AI doesn’t fix a team; it amplifies what’s already there” (Google Cloud blog, 2025-09-23). A pilot on a team with flaky tests and unclear tickets will amplify those first, so fix the gates before you blame the agents.