# Your first feedback loop in Copilot CLI

One way to wire the earlier Copilot CLI pieces into a single loop from an agent-ready issue to a reviewed pull request, with learnings shipped back through a plugin.

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

This page shows one way to assemble the earlier Copilot CLI pages; it is not a prescribed factory design.

## At a glance

| | Copilot CLI |
|---|---|
| Term | No single feature: a workflow, `copilot -p --autopilot`, an `agentStop` hook and a custom agent |
| Configured in | `.github/workflows/`, `.github/hooks/`, `.github/agents/`, `.github/skills/`, the plugin repository |
| Loads / runs | The `agent-ready` label starts one headless run; each piece loads as its own page describes |
| Scope & precedence | Hooks combine; a repository `reviewer` or `add-migration` shadows the plugin's |

## Build the scenario

The repository, with the pieces you already built:

```text
ticket-service/
├── .devcontainer/            # sandboxing: devcontainer, init-firewall.sh
├── .github/
│   ├── copilot-instructions.md   # instruction-files
│   ├── instructions/db.instructions.md
│   ├── skills/add-migration/     # skills
│   ├── agents/reviewer.agent.md  # subagents
│   ├── hooks/{ticket-service,loop}.json + scripts/   # hooks, loops
│   ├── copilot/settings.json     # plugins: enabledPlugins
│   └── workflows/agent-ready.yml # headless-execution
└── src/ test/ docs/
```

The agent step of `agent-ready.yml`. The job, token, checkout and push steps stay as on the [headless execution](https://ai-sw-factory.mellicci.dev/fundamentals/headless-execution/copilot-cli) page.

```yaml
      - name: Run Copilot CLI
        env:
          COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_PAT }}
          GITHUB_COPILOT_PROMPT_MODE_REPO_HOOKS: "true"
          N: ${{ github.event.issue.number }}
        run: |
          mkdir -p .agent && touch .agent/loop-active
          copilot -p "Implement issue #$N (read it with issue_read). Use the /add-migration skill for schema changes. Before finishing, run the reviewer agent on the diff; if any criterion fails, fix it and run the reviewer again. Call task_complete only when pnpm test passes and the reviewer passes." \
            --autopilot --max-autopilot-continues 10 --max-ai-credits 200 \
            -s --no-ask-user --share=agent-run.md \
            --add-github-mcp-tool=issue_read --allow-tool='github-mcp-server(issue_read)' \
            --allow-tool='write, shell(pnpm:*), shell(git add:*), shell(git commit:*)' \
            --deny-tool='shell(git push), shell(rm), shell(curl), shell(wget)'
```

## Specifics

### The pieces and where they live

| Piece | File | Loads / runs when | Page |
|---|---|---|---|
| Trigger and run | `.github/workflows/agent-ready.yml` | Label `agent-ready` is applied | [Headless](https://ai-sw-factory.mellicci.dev/fundamentals/headless-execution/copilot-cli) |
| Allow/deny baseline | Flags on `copilot -p` | Every run; flags don't persist | [Security model](https://ai-sw-factory.mellicci.dev/fundamentals/security-model/copilot-cli) |
| Boundary | `.devcontainer/`, `sandbox` in `settings.json` | Container start; sandbox enabled once | [Sandboxing](https://ai-sw-factory.mellicci.dev/fundamentals/sandboxing/copilot-cli) |
| Issue access | Built-in `github-mcp-server` | Session start, narrowed by flags | [MCP](https://ai-sw-factory.mellicci.dev/fundamentals/mcp/copilot-cli) |
| Conventions | `.github/copilot-instructions.md`, `.github/instructions/` | Session start | [Instruction files](https://ai-sw-factory.mellicci.dev/fundamentals/instruction-files/copilot-cli) |
| Migration procedure | `.github/skills/add-migration/SKILL.md` | Matched by description or named in the prompt | [Skills](https://ai-sw-factory.mellicci.dev/fundamentals/skills/copilot-cli) |
| Guard, format, log | `.github/hooks/ticket-service.json` | `preToolUse` and `postToolUse` | [Hooks](https://ai-sw-factory.mellicci.dev/fundamentals/hooks/copilot-cli) |
| Green gate | `.github/hooks/scripts/gate.sh` | `agentStop` | [Loops](https://ai-sw-factory.mellicci.dev/fundamentals/loops/copilot-cli) |
| Reviewer | `.github/agents/reviewer.agent.md` | When the prompt or main agent delegates | [Subagents](https://ai-sw-factory.mellicci.dev/fundamentals/subagents/copilot-cli) |
| Shipping setup changes | `ticket-service-kit` plugin | Install or update | [Plugins](https://ai-sw-factory.mellicci.dev/fundamentals/plugins/copilot-cli) |

### The CI run, end to end

| # | What happens | Piece |
|---|---|---|
| 1 | A maintainer adds `agent-ready`; the workflow starts and pushes nothing yet | Workflow |
| 2 | `copilot -p --autopilot` starts in the devcontainer with the CI baseline | Flags, sandbox |
| 3 | The agent reads the issue with `issue_read` | Built-in MCP |
| 4 | Instruction files load; the agent picks `add-migration` for schema work | Instructions, skill |
| 5 | Every tool call is logged and checked; edits are formatted | Hooks |
| 6 | The agent tries to stop; `gate.sh` runs `pnpm test` and blocks on failure | `agentStop` |
| 7 | The reviewer returns pass or fail per criterion; failures go back to the agent | Custom agent |
| 8 | The run ends; the workflow pushes `agent/issue-<n>` and opens the PR | Workflow |
| 9 | A person reviews and merges | Human |

The documentation doesn't specify how to run an Actions job inside a devcontainer; the pages used here show the container and the workflow separately.

### Gates and the reviewer

| Gate | Enforced by | Bounded by |
|---|---|---|
| `pnpm test` green | `agentStop` hook returns `decision: "block"` with a reason | 8 consecutive blocks, `--max-autopilot-continues`, `--max-ai-credits`, `timeout-minutes` |
| Reviewer verdict | The prompt only; the model decides to delegate | Same caps |
| Dangerous commands | `guard.sh` and `--deny-tool` | `--deny-tool` beats any allow |
| Merge | A person | Branch protection |

The hook is the one check that runs outside the model. The reviewer step is an instruction, so a run can skip it. Check the verdict in `agent-run.md` during human review.

<note>

An autopilot run ends at `task_complete` or at a cap, not at a green build. Read `agent-run.md` when a run stops at a cap.

</note>

### Feeding learnings back

| Step | What you do | Where |
|---|---|---|
| 1 | Find a repeated failure in `agent-run.md`, `.agent/logs/tool-calls.jsonl` or PR comments | CI artifacts |
| 2 | Pick the smallest fix: an instruction line, a skill step, a stricter `guard.sh` | Matching file |
| 3 | Bump `version` in `plugin.json` and republish | `ticket-service-kit` |
| 4 | Update with `copilot plugin update ticket-service-kit` | Each machine and runner |
| 5 | Watch whether the failure stops recurring | Next runs |

Once the plugin ships the skill, hooks and reviewer, remove the repository copies, or they shadow the plugin's. The plugin does not ship instruction files, so those stay in the repository.

### What to check first when it fails

| Symptom | Piece | Where to look |
|---|---|---|
| Agent ignores conventions | Instruction files | `copilot instruction list`, `/instructions` |
| Skill never used | Skills | `/skills list`, `/skills info add-migration`; sharpen the description |
| Cannot read the issue | MCP, token | `/mcp show github-mcp-server`; `COPILOT_GITHUB_TOKEN` |
| Hooks did nothing | Hooks, trust | `GITHUB_COPILOT_PROMPT_MODE_REPO_HOOKS`; `tool-calls.jsonl` |
| Stops with red tests | Gate | `.agent/loop-active` exists; `timeoutSec` on `gate.sh`; `.agent/last-test.log` |
| Run stops early or drifts | Caps, permissions | `agent-run.md`; continues and credit flags |
| Reviewer never ran | Subagents | `agent-run.md`; `.github/agents/` profile loaded, prompt names it |
| Denied command | Security model | `agent-run.md` for the denied tool; the `--deny-tool` list |

## Gotchas

- Hooks load in `-p` mode only for a trusted folder or with `GITHUB_COPILOT_PROMPT_MODE_REPO_HOOKS=true`. Without it the guard, format and gate hooks silently don't run.
- The gate fails open when it exceeds `timeoutSec`, and the docs give both 5 and unlimited as the default for continues. Set every cap.
- The reviewer has `execute`, so "read-only" is an instruction. Keep the CI deny list in place.
- Unattended autopilot needs permissions that can delete files; keep the devcontainer, firewall and deny rules.
- The documentation doesn't specify whether plugin hooks load in `-p` mode, so test the plugin-only setup before removing repository copies.
