# Hand an issue to a coding agent

Every diagnosed issue has ONE canonical handoff packet
([schema](/schema/handoff-packet.json)) binding: the issue's stable
fingerprint, the diagnosis, bounded cited evidence (never the whole lake),
repository context, loop history (who tried what, did it hold), telemetry-
anchored success criteria, and the approval constraints.

The same canonical packet anchors every path, so they cannot drift:

## From the console

Open an Issue in **Needs you** → **Copy agent prompt** copies a short decision
pointer to its canonical id and project. Paste it into any MCP-capable harness;
the agent calls `loopops_issue` to read the fresh packet, summarizes the
bounded evidence and recommendation, and waits for your call. Record that call
with `loopops_issue_decide`. Only a `patch` receipt selects coding work; once
that work starts, the same slot shows the supervised state instead: which agent,
what stage, artifacts, who approved, and the one thing you do next.

## From MCP

```text
loopops_issue({ issue: "if_checkout_timeout" })
```

Accepts the console fingerprint (`if_…`), a diagnose candidate's
`cluster_id`, or an issue id. Reading it claims nothing and writes nothing —
record the disposition with `loopops_issue_decide`, then record actual work
with `loopops_improve` only when the latest receipt selects `patch`.

## The contract inside the packet

- **Success criteria** are stated against telemetry — "the cluster stops
  re-firing in the next window" — never "the PR merged".
- **Approval is constitutional**: never post issues/PRs or mutate anything
  external without explicit human approval; record it
  (`loopops_improve({ stage: "approved" })`) so the run itself carries who
  approved.
- **Evidence stays bounded**: resolve the cited `evidence_ids` and the
  cluster join; never pull the lake.

**Next:** [What the loop holds — data & trust →](/docs/data-scrubbing)