# Your first feedback loop in Codex

One way to wire the earlier Codex pieces into an unattended loop from the agent-ready label to a pull request, with gates, a reviewer and a path for learnings back into the setup.

Source: https://ai-sw-factory.mellicci.dev/fundamentals/your-first-feedback-loop/codex

This page shows one way to assemble the pieces from the earlier Codex pages; it is not a prescribed factory design. It adds only the glue and links the pieces.

## At a glance

| | Codex |
|---|---|
| Term | A `codex-action` workflow (non-interactive `codex exec`) that uses `AGENTS.md`, a skill, hooks, an MCP server and a custom agent |
| Configured in | `.github/workflows/agent-ready.yml`, `.codex/`, `.agents/skills/`, `AGENTS.md` files |
| Loads / runs | Each labeled issue starts one CI run; the pieces load as the run starts or when the model reaches for them |
| Scope & precedence | Repo files apply to every run; the CI baseline (sandbox, approvals, network) comes from the workflow. Project `.codex/` layers load only in trusted projects |

## Build the scenario

Repository layout for everything involved:

```text
ticket-service/
├── AGENTS.md                      # commands, layout, conventions
├── src/db/AGENTS.md               # database rules
├── .agents/skills/add-migration/  # SKILL.md, references/, scripts/
├── .codex/
│   ├── config.toml                # [mcp_servers.github]
│   ├── hooks.json                 # guard, format, log
│   ├── hooks/                     # guard.sh format.sh log.sh loop-check.sh
│   ├── agents/reviewer.toml       # read-only reviewer
│   └── rules/ticket-service.rules # allow test/lint, forbid rm -rf
├── .github/workflows/agent-ready.yml
└── .agent/                        # tool-calls.jsonl, loop-notes.md
```

The agent step. Extra prompt lines go into the `Build prompt` step of the [headless workflow](https://ai-sw-factory.mellicci.dev/fundamentals/headless-execution/codex); the run step is the CI baseline from the [security model](https://ai-sw-factory.mellicci.dev/fundamentals/security-model/codex):

```yaml
printf '\nUse the github MCP server for the issue; follow AGENTS.md and the add-migration skill.\n'
printf 'Goal: pnpm test passes. Stop after 10 rounds or if a test fails the same way twice.\n'
printf 'Before finishing, ask the reviewer agent to check each acceptance criterion; fix failures.\n'
# ---- Run Codex step
- uses: openai/codex-action@v1
  env: { GITHUB_MCP_TOKEN: "${{ secrets.ISSUES_READ_TOKEN }}" }
  with:
    openai-api-key: ${{ secrets.OPENAI_API_KEY }}
    prompt: ${{ env.PROMPT }}
    sandbox: workspace-write
    codex-args: '["-c","approval_policy=never","-c","sandbox_workspace_write.network_access=false"]'
    output-file: codex-output.md
```

## Specifics

### The pieces and where they live

| Piece | File | Loads / runs when | Page |
|---|---|---|---|
| Trigger and CI baseline | `.github/workflows/agent-ready.yml` | Issue gets the `agent-ready` label | [Headless](https://ai-sw-factory.mellicci.dev/fundamentals/headless-execution/codex), [Security](https://ai-sw-factory.mellicci.dev/fundamentals/security-model/codex) |
| Instructions | `AGENTS.md`, `src/db/AGENTS.md` | At start; the launch directory decides which load | [Instruction files](https://ai-sw-factory.mellicci.dev/fundamentals/instruction-files/codex) |
| Skill | `.agents/skills/add-migration/SKILL.md` | Name and description listed at start; full text when selected | [Skills](https://ai-sw-factory.mellicci.dev/fundamentals/skills/codex) |
| Issue access | `.codex/config.toml` | Server starts with Codex | [MCP](https://ai-sw-factory.mellicci.dev/fundamentals/mcp/codex) |
| Guard, format, log | `.codex/hooks.json`, `.codex/hooks/*.sh` | `PreToolUse` and `PostToolUse`, after the hooks are trusted | [Hooks](https://ai-sw-factory.mellicci.dev/fundamentals/hooks/codex) |
| Loop bound | Prompt text, `Stop` hook, `timeout-minutes` | Each turn end; job time limit | [Loops](https://ai-sw-factory.mellicci.dev/fundamentals/loops/codex) |
| Reviewer | `.codex/agents/reviewer.toml` | When the prompt or `AGENTS.md` asks for it | [Subagents](https://ai-sw-factory.mellicci.dev/fundamentals/subagents/codex) |
| Packaging | `ticket-service-kit` plugin | Installed, then in a new session | [Plugins](https://ai-sw-factory.mellicci.dev/fundamentals/plugins/codex) |

### The CI run, end to end

| # | What happens | Who |
|---|---|---|
| 1 | The label triggers the workflow; checkout and `pnpm install` run before Codex, because network is off inside it | Workflow |
| 2 | `codex-action` runs `codex exec` with the prompt, `workspace-write`, `approval_policy=never` | Harness |
| 3 | Codex reads the issue through the `github` server and loads the `AGENTS.md` chain | Model, harness |
| 4 | It selects `add-migration`, edits, and runs `pnpm test` | Model |
| 5 | Hooks run on each tool call once trusted (untrusted ones are skipped): guard can deny, format rewrites results, log appends to `.agent/logs/` | Harness |
| 6 | Codex asks the reviewer for a verdict, fixes failing criteria, re-tests | Model |
| 7 | The push step fails on an empty diff, opens the PR with `codex-output.md` in the body; a person reviews | Workflow, you |

### Gates and the reviewer

| Gate | Enforced by | Stops the change when |
|---|---|---|
| `guard.sh` | Harness (hook) | A command matches a deny pattern |
| `pnpm test` | Prompt, optionally a `Stop` hook | Tests fail; the `Stop` hook's `block` reason continues the turn |
| Reviewer | Model follows the prompt | A criterion fails; the verdict returns to the agent |
| Empty diff | Workflow step | Nothing changed |
| Human review | Branch protection, you | The PR is not approved |

What bounds the loop: the "10 rounds" sentence is an instruction the model follows, since the documentation describes no round limit. `/goal` is documented for the desktop app, the interactive CLI and the IDE, not for `codex exec`. For a count the harness enforces, use the `loop-check.sh` pattern from [loops](https://ai-sw-factory.mellicci.dev/fundamentals/loops/codex); the documentation doesn't say whether `Stop` hooks fire under `codex exec`, so test it. `timeout-minutes` is the hard stop.

The reviewer runs in a separate thread with `sandbox_mode = "read-only"`; subagents inherit the parent's runtime approval and sandbox choices. In a non-interactive run, an action that needs new approval fails and the error returns to the parent. A reviewer's `description` alone does not start it, so the prompt names it.

### Feeding learnings back

| You see in PRs | Change the setup | File |
|---|---|---|
| Agent runs the wrong command | Add the line | `AGENTS.md` |
| Same multi-step procedure gets improvised | Extend or add a skill | `.agents/skills/` |
| A rule is broken and must not recur | Add a hook or `forbidden` rule | `.codex/hooks/`, `.codex/rules/` |
| Reviewer misses the same thing | Edit its `developer_instructions` | `.codex/agents/reviewer.toml` |
| Several repositories need the fix | Release a new plugin version | `ticket-service-kit` |

Ship through a plugin what it can carry: the skill, the hooks and the MCP server. The reviewer stays in `.codex/agents/` because the documentation doesn't list custom agents as a plugin component. Plugin hooks run only after trust in `/hooks`, and the documentation doesn't say how to establish that in a fresh CI checkout, so the repository files above are the dependable CI path. Changes to these files are reviewed as code in a pull request.

### What to check first when it fails

| Symptom | Piece | Where to look |
|---|---|---|
| Agent ignores a convention | Instructions | Ask "List the instruction sources you loaded."; check 32 KiB cap and launch directory |
| No issue access, 401 at tool call | MCP | `/mcp verbose`; token variable set in the Codex step; project trust |
| Skill never used | Skill | Description wording; `/skills` |
| Guard or format never fired | Hooks | `/hooks` trust state; `.agent/logs/tool-calls.jsonl` |
| Command blocked or prompting | Rules, sandbox | `codex execpolicy check --pretty --rules ... -- <cmd>`; `output-file` artifact |
| Run ends with no changes | Sandbox | `sandbox: workspace-write` set; push step log |
| No reviewer verdict | Reviewer | Prompt names it; `/agent` in an interactive repro |
| Loop runs long | Bound | Prompt wording; `loop-check.sh` state in `.agent/`; job timeout |

## Gotchas

- **Nothing is interactive in CI.** Trust prompts and approvals can't be answered, so anything that needs them fails or is skipped (the docs name `--dangerously-bypass-hook-trust` for automation that vets hook sources elsewhere); reproduce locally with the same flags.
- **One config file or the other.** The action's `sandbox` input sets `sandbox_mode`, so permission profiles that protect `.env*` and migrations don't apply; review those in the PR.
- **The loop cap is yours.** The model counts rounds; only a hook or the job timeout enforces one.
- **The reviewer is advice with context.** It shares the repo with the author; a different `model` gives a second opinion, but a person still approves.
- **Setup changes are code.** A hook or rule added after a failure runs with the agent's rights; review it like any change.
