Skip to content

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)

  1. Add repo secrets (Settings → Secrets and variables → Actions):

    Secret Value
    ANTHROPIC_API_KEY An Anthropic API key (billing = your account) — the only new secret you must add
    FEEDBACK_REPO_TOKEN Already exists (used by the retest flow). It must reach both repos: feedback repo Issues: RW, webshop repo Contents: RW + Pull requests: RW. If it's currently feedback-only, widen its fine-grained scope (or swap in a dedicated PAT).
  2. (Recommended) Branch protection on staging: require 1 approving review, so nothing the agent opens can reach staging without your click.

  3. Promote to main so the daily cron activates (until then: manual runs only).
  4. Test it: Actions → Feedback Agent → Run workflow (optionally pick a stronger model).

Tuning & cost

  • Cadence: edit the cron (currently daily). Model: default claude-sonnet-5; bump to claude-opus-4-8 for harder fixes via the manual-run input or the claude_args default.
  • Budget: --max-turns 40 and timeout-minutes: 30 cap a run. A run handles the current needs-triage backlog top-down; anything it doesn't reach stays needs-triage for 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.