Feedback Agent¶
An automated agent that triages the feedback Eefje files in the
Voorman/freezedesign-feedback repo and
turns clear bugs into draft PRs, features into proposals, and open questions into
routed asks — while a human stays firmly in the loop.
Design principle
The AI proposes, a human disposes. The agent never merges and never deploys. It opens
draft PRs against staging; you merge — that is the gate. Its operating contract lives
in .github/feedback-agent/AGENT.md.
How it runs¶
| Workflow | .github/workflows/feedback-agent.yml |
| Trigger | schedule — daily 07:00 UTC (~09:00 NL) + workflow_dispatch (manual) |
| Engine | anthropics/claude-code-action@v1, model claude-sonnet-5 (override on manual run) |
| Reads | open status:needs-triage issues in the feedback repo |
| Writes | draft PRs + comments/labels — never merges, never touches main/secrets/.env |
Scheduled workflows run from main
The daily cron only fires once this workflow is on main. On staging it exists but is
dormant — you can still trigger it manually (workflow_dispatch) from any branch. It also
no-ops unless both secrets below are set, so it fails soft until you deliberately switch it on.
What Eefje vs Ivar get asked¶
The agent classifies who owns each question and routes accordingly:
| Question type | Goes to | How | Label |
|---|---|---|---|
| Product / UX / preference | Eefje | plain-Dutch comment on the feedback issue | status:awaiting-eefje |
| Technical / design / architecture / risk | Ivar | ADR-style (options + trade-offs + recommendation) on the draft PR or as a dev-addressed comment | status:awaiting-ivar |
State machine¶
flowchart TD
A[status:needs-triage] --> B[status:ai-triaged]
B -->|product Q| E[status:awaiting-eefje]
B -->|design/tech Q| I[status:awaiting-ivar]
B -->|clear bug| F[status:ai-fixing → draft PR]
B -->|feature/large| P[status:proposed]
F --> AP[status:awaiting-approval]
E -->|Eefje answers| B
I -->|Ivar answers| B
AP -->|👤 Ivar merges PR| R[status:retest-pending]
R -->|Eefje verifies on staging| C[closed]
The human gates are awaiting-eefje/awaiting-ivar (someone must answer) and
awaiting-approval (you must merge the draft PR).
Enabling it (one-time, your steps)¶
-
Add repo secrets (Settings → Secrets and variables → Actions):
Secret Value ANTHROPIC_API_KEYAn Anthropic API key (billing = your account) — the only new secret you must add FEEDBACK_REPO_TOKENAlready exists (used by the retest flow). It must reach both repos: feedback repo Issues: RW, webshop repoContents: RW+Pull requests: RW. If it's currently feedback-only, widen its fine-grained scope (or swap in a dedicated PAT). -
(Recommended) Branch protection on
staging: require 1 approving review, so nothing the agent opens can reach staging without your click. - Promote to
mainso the daily cron activates (until then: manual runs only). - Test it: Actions → Feedback Agent → Run workflow (optionally pick a stronger model).
Tuning & cost¶
- Cadence: edit the
cron(currently daily). Model: defaultclaude-sonnet-5; bump toclaude-opus-4-8for harder fixes via the manual-run input or theclaude_argsdefault. - Budget:
--max-turns 40andtimeout-minutes: 30cap a run. A run handles the currentneeds-triagebacklog top-down; anything it doesn't reach staysneeds-triagefor the next run. - Disable: Actions → Feedback Agent → ··· → Disable workflow (or remove the
schedule).
Guardrails (enforced by the contract)¶
- Draft PRs only; never merge/deploy; never push to
main; never touch secrets/.env/infra. - Two repos only. Features are never auto-built — proposal + greenlight first.
- Idempotent: skips already-triaged issues; batches questions in one round.
Prefer event-driven later
This is the polling (daily) version — simplest to trust first. Once its judgement is proven,
it can be re-triggered on GitHub issues events for near-instant response, reusing the same
contract and labels.