# What a twin is

A twin is a local, stateful replica of one vendor's API. Your real SDK talks to it exactly as it
talks to the vendor, with a fake key, and gets the selected implementation's answer back. This page explains the contract,
in three parts, and the limits that come with it.

## It speaks the vendor's API

A twin implements the vendor's paths, request and response shapes, errors and pagination for
the operations it supports. Your app keeps its real SDK; the World routes the selected vendor
to that implementation. The release's catalog assessment says which operations and journeys
were exercised and under what conditions. Coverage and fidelity must be checked for your workflow.

What it does not model, it does not fake. A route the twin has not built fails the way the
vendor would fail an unknown request, with a vendor-shaped status and error, never as a silent
success. That is why a 404 or a 400 from a twin is information: either your app is wrong, or the
twin is incomplete. The [coverage](../reference/coverage.md) page says, vendor by vendor, what
fraction of the vendor's spec the twin serves, and each twin's README says which operations it
does not serve yet.

## It is stateful

A write you make is visible on the next read. A customer you create can be charged, listed,
updated and deleted, with the vendor's rules about what is allowed when. Reads reflect writes
because the twin keeps writes in a log and serves its state over that history. A scenario can
script lookup results, model answers and faults. It must never stand in for a successful stored
mutation; records go through the implementation's vendor API.

The state is yours to control. A fresh world starts from the twin's default data; your app's
writes land on top of it; `reset` returns to the defaults; a branch records its own changes over the same history.
[Seed and reset](../guides/seed-and-reset.md) and [the model](./the-model.md) say how.

## It is deterministic

A simulated twin's answer follows the request, its state, scripted behavior and the World clock.
Repeat the same requests from the same starting state with the same frozen clock and advances
to compare responses, ids and timestamps. Without an explicitly frozen clock, the runtime uses
wall time. A reset alone does not establish identical replay conditions.

This is a promise about what a twin will never do. A simulated twin never reaches its vendor at serve time. A real-system root performs writes
through the kernel and records receipts, as [the model](./the-model.md) describes. Simulation
never runs a language model. A generative vendor such as OpenAI or Anthropic serves a clearly
labeled deterministic stub, or a scenario you script, so a test can prove that the call happened,
that the tool calls and usage were shaped correctly, that state persisted and that the failure
path works. It cannot prove anything about the quality of a real model's answer, and a twin that
tried would stop being a test you can rerun.

## What that means for you

- **Trust the wire, check the coverage.** If your app uses an operation, look for it in the
  twin's README before you rely on the twin for it.
- **Read refusals as data.** A refused route is either an app bug or a gap, never a twin
  pretending.
- **Assert on behavior, not on prose.** For generative vendors, test the plumbing.
- **Expect the same answer twice.** A differing result needs investigation of the test, twin
  state and runtime; determinism is a contract to verify, not proof that a twin cannot have a bug.
