> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pome.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# How we pick what a twin covers

> Why a digital twin implements some upstream endpoints deeply, some only by shape, and rejects the rest loudly — and what to do when the one you need isn't there.

Every digital twin simulates a slice of its upstream API, not the whole thing. GitHub alone
exposes hundreds of REST routes; no twin needs all of them to be useful, and building all of
them would mean spending fidelity budget on routes agents never call. We pick the slice
deliberately, using the same rubric across every twin.

## The three heat tiers

We sort every upstream endpoint into one of three tiers, ranked by how often an autonomous
agent actually reaches for it. This is the same **heat** axis (`hot` / `warm` / `cold`) that
each twin's `FIDELITY.md` carries in its `Heat` column, and that
[`packages/sdk/ENDPOINT-TIERS.md`](https://github.com/pome-sh/digital-twins/blob/main/packages/sdk/ENDPOINT-TIERS.md)
defines the rubric for — this page restates that rubric for readers who haven't found the
engine-level doc yet.

* **Hot path** — the endpoint sits on a task an agent routinely performs against this API:
  collecting a payment, triaging an issue, posting a message to a channel. If a hot-path
  endpoint were shallow, an eval run against the twin would silently diverge from what
  happens against the real service — the failure mode we care most about avoiding. A twin
  implements its hot path with full behavior: state changes, side effects, and error
  semantics that match the live service, backed by tests.
* **Warm path** — adjacent to a hot path: a context read, an occasional cleanup step, or a
  real chain that's too long or too rare to justify full behavioral modeling yet. A warm-path
  call never fails loudly by surprise, but you shouldn't build an agent that depends on its
  side effects. A twin implements its warm path so the response shape matches the live
  service, without necessarily reproducing every stateful consequence.
* **Cold path** — not plausibly on an autonomous agent's task chain: browser redirect flows,
  admin and enterprise surfaces, or anything outside a twin's product scope. A twin does not
  implement its cold path at all. Calling a cold-path route returns a loud, structured error
  instead of a silent 200 — see [what happens if you call an unimplemented
  endpoint](#calling-something-outside-the-hot-or-warm-path).

We decide which band an endpoint falls in the same way for every twin: enumerate the tasks
agents actually run against that API, then cross-check against the upstream vendor's own
default-enabled agent tooling where one exists. Endpoints on a real task chain are hot even
if a vendor's tooling doesn't expose them; the task chain wins disagreements.

## This is a different axis from fidelity tiers

Each twin ships a `FIDELITY.md` in the
[`pome-sh/digital-twins`](https://github.com/pome-sh/digital-twins) repo that classifies
every implemented endpoint into a fidelity tier — `semantic`, `shape`, or `unsupported` —
describing how faithfully that endpoint's *behavior* reproduces the real service. Heat
and fidelity tier answer different questions and should not be read as two names for the
same thing:

| Axis                                               | Question it answers                         |
| -------------------------------------------------- | ------------------------------------------- |
| **Heat** (hot / warm / cold)                       | How much do agents reach for this endpoint? |
| **Fidelity tier** (semantic / shape / unsupported) | How faithfully do we reproduce it?          |

They correlate — a hot-path endpoint is expected to reach `semantic` fidelity, a warm-path
endpoint `shape`, a cold-path endpoint stays `unsupported` — but the words aren't
interchangeable. In particular, **cold is not a synonym for unsupported**: cold describes an
endpoint we chose not to model because agents don't plausibly need it, while unsupported
describes the measured fidelity of an endpoint today, whatever its heat. A warm-path
endpoint can also be `unsupported` while work is in flight, and that's tracked as a gap, not
a scope decision.

For the endpoint-by-endpoint tier tables, see the `FIDELITY.md` in that twin's package
directory in [`pome-sh/digital-twins`](https://github.com/pome-sh/digital-twins) — for
example `packages/twin-github/FIDELITY.md`.

## How much of each API is covered

Exact counts change as twins add surface area, so we don't hand-type them here — they'd go
stale the next time a twin ships a new endpoint. [status.pome.sh](https://status.pome.sh) is
an uptime page (Operational / Degraded / Down per twin), not a coverage inventory — it
doesn't break endpoint counts out by fidelity tier. For the current per-endpoint tier
tables, see the twin's `FIDELITY.md` linked above.

## Calling something outside the hot or warm path

If your agent calls a cold-path (or not-yet-implemented) endpoint, the twin returns a loud
501 instead of a silent success — but the exact envelope shape isn't universal across twins.
Each twin mimics the error shape of the upstream it clones, so the `unsupported` signal lives
in different places:

* **GitHub** and **Slack** nest it under a `_twin` namespace:

  ```json theme={"dark"}
  {
    "message": "This endpoint is not supported by this GitHub twin clone.",
    "_twin": {
      "fidelity": "unsupported",
      "supported_surfaces": ["..."]
    }
  }
  ```

* **Stripe** nests `fidelity` and `supported_surfaces` on its native `error` object instead
  of `_twin`.

* **Linear** puts a top-level `fidelity` field alongside its GraphQL-style `errors` array, with
  no `_twin` namespace.

* **Gmail** mirrors Google's `UNIMPLEMENTED` error shape and carries no `fidelity` marker or
  `supported_surfaces` list at all.

Don't hardcode a check against `_twin.fidelity === "unsupported"` — it only holds for the
GitHub and Slack twins. Check the twin's own 501 shape (each twin's `FIDELITY.md` documents
it) or key off the HTTP status code (501) instead, and treat it the way you'd treat a real
404 on a route that doesn't exist: not retry into it.

If the endpoint you need isn't covered, file it against the twin's repo
([`pome-sh/digital-twins`](https://github.com/pome-sh/digital-twins)) with the route or MCP
tool name and the task you're trying to run — that's exactly the input we use to move an
endpoint onto a warm or hot path, or to raise an existing one's fidelity tier.
