# Migrating from Anthropic Enterprise (/docs/migrating-from-anthropic-enterprise)



If you have an Anthropic Enterprise (or Anthropic for Work) contract,
you've already been through procurement, a security questionnaire, and
the vendor-side SSO/SAML and Zero Data Retention review. You should
not casually add a new vendor on top of that work. Pleach is
explicitly designed not to be one — it ships as an npm package and
writes to your existing Postgres. There is no Pleach SaaS to add to
your vendor list.

This page is for the team that built its first one to three LLM
features on the existing Anthropic Enterprise contract and is now
hitting one of three downstream walls: finance can't attribute cost
to a meaningful axis **inside a Workspace** — your end customers in a
SaaS product, or your employees, teams, and cost centers when the
Workspace is an internal-use deployment; compliance can't produce a
tamper-evident audit row from **their own database**; or
eval/regression can't replay a turn byte-identically against a
specific model snapshot. Pleach sits underneath the existing contract
and closes those three gaps without changing what Anthropic does for
you.

A note on shape: this page reads naturally for the multi-tenant SaaS
case (Acme Corp is your customer). The same row, the same hash chain,
and the same fingerprint cover internal-use deployments — set
`tenantId` to the employee, team, or cost-center identifier you want
to chargeback or audit against. The vendor contract still rolls up to
the Workspace; Pleach rolls up to whichever axis your finance and
audit teams actually report on.

## The architecture [#the-architecture]

```
┌──────────────────────────────────────────────────────────────┐
│  Anthropic Enterprise (your existing contract)               │
│  - SSO / SAML                                                │
│  - Zero Data Retention                                       │
│  - Workspaces (per-workspace API keys)                       │
│  - Admin API (per-workspace usage rollup)                    │
│  - Dedicated capacity / fine-tuned snapshots                 │
│  - Prompt caching, batches API, files API                    │
│                                                              │
│  ┌────────────────────────────────────────────────────────┐  │
│  │  Pleach SessionRuntime (npm + your Postgres)           │  │
│  │  - AuditableCall row → your Postgres                   │  │
│  │    keyed (sessionId, turnId, stageId, seqWithinTurn)   │  │
│  │    carrying tenantId, modelId, tokenUsage              │  │
│  │  - Family-lock at session start (snapshot pinned)      │  │
│  │  - Replay-deterministic StreamEvent via fingerprint    │  │
│  │  - prev_hash + row_hash chain                          │  │
│  │  - Subagent rollup to parent turnId                    │  │
│  │                                                        │  │
│  │  AnthropicSdkProvider                                  │  │
│  │  (wraps @anthropic-ai/sdk; uses your workspace key)    │  │
│  └────────────────────────────────────────────────────────┘  │
│                                                              │
└──────────────────────────────────────────────────────────────┘
```

Anthropic's Admin API is the **vendor-facing** rollup — what each
Workspace spent against your contract. Pleach's `AuditableCall`
ledger is the **downstream** rollup — which of *your* end customers
within that Workspace caused the spend, which turn they typed, what
the agent did with it, and what each tool call cost. The two ladders
compose: the Admin API tells you what the Workspace owed Anthropic;
Pleach tells you which of your customers inside that Workspace owes
you.

## The three walls [#the-three-walls]

The Anthropic Enterprise contract is comprehensive at the *vendor*
layer. The three walls below are the places it stops — not because
the contract is incomplete, but because each one is a downstream
concern about your product's behavior that only your own
infrastructure can answer.

### Wall 1: Per-end-customer cost attribution inside a Workspace [#wall-1-per-end-customer-cost-attribution-inside-a-workspace]

What the contract gives you: the Admin API exposes per-Workspace
usage and per-API-key usage. If you provisioned one Workspace per
end customer, you already have rollup at end-customer granularity.

The gap: most enterprise deployments don't carve one Workspace per
end customer. A single Workspace serves N tenants in your product
because that's how your auth, your rate limits, and your
prompt-caching prefixes are organized. The Admin API reports the
Workspace's total — it does not know which of your tenants inside
that Workspace caused which turn, which subagent spawned, or which
tool called the LLM again.

What Pleach closes: every LLM call writes an `AuditableCall` row
carrying `tenantId`, `turnId`, `subagentDepth`, `modelId`, and
`tokenUsage`, keyed `(sessionId, turnId, stageId, seqWithinTurn)`.
A single SQL query against your Postgres gives you per-end-customer
rollup; the Admin API gives you the matching Workspace total to
reconcile against.

### Wall 2: A tamper-evident audit row in your own database [#wall-2-a-tamper-evident-audit-row-in-your-own-database]

What the contract gives you: Zero Data Retention means Anthropic
does not retain your inputs or outputs past the inference window.
The contract documents this and is auditable through Anthropic's
SOC 2 / ISO process.

The gap: ZDR is a statement about what the *vendor* stores. It is
not a statement about what *you* store, and it is not the row your
downstream auditor will ask for when they want to see what your
product told a specific customer on a specific day. If your
compliance program needs a tamper-evident record of decisions
*your product* made — which tool the agent invoked, which model
snapshot answered, which subagent spawned — that record has to
live in your database, not the vendor's.

What Pleach closes: the `AuditableCall` row in your Postgres
carries a `prev_hash` + `row_hash` chain. Any reordering or
deletion of a row breaks the chain at the next verifier pass. The
ZDR contract continues to govern what Anthropic stores; Pleach
governs what you store and how you defend the chain when asked.

### Wall 3: Replay determinism across model snapshots [#wall-3-replay-determinism-across-model-snapshots]

What the contract gives you: dedicated capacity and pinned model
snapshots (`claude-sonnet-4-5`, `claude-opus-4-7`) let you control
which model version serves your traffic. You can hold a snapshot for
the length of a contract term.

The gap: holding a snapshot doesn't make a turn replayable. A
recorded turn replayed two months later against the same snapshot
can still drift if any input changed — prompt cache invalidation,
tool definition reordering, a system-prompt edit. The vendor
contract gives you the snapshot; it does not give you a cache key
that says "this exact input produced this exact output."

What Pleach closes: every turn produces a `Fingerprint` covering
the prompt, tool schemas, family, snapshot id, and runtime config.
A recorded turn replays byte-identically when the fingerprint
matches; when it diverges, the diff tells you which input changed.
This is the substrate eval and regression testing run against
before a new snapshot rolls out to production.

## The code shape [#the-code-shape]

```typescript
import {
  createPleachRuntime,
  AnthropicSdkProvider,
  type StreamEvent,
} from "@pleach/core";
import { SupabaseAdapter } from "@pleach/core/sessions";

// Your existing Anthropic Enterprise workspace key. SSO, ZDR, and
// the rest of the vendor contract continue to govern this key
// exactly as before — Pleach reads it, doesn't replace it.
const WORKSPACE_API_KEY = process.env.ANTHROPIC_WORKSPACE_API_KEY!;

const runtime = createPleachRuntime({
  // tenantId is YOUR end customer inside the Workspace. The Admin
  // API doesn't see this field; Pleach stamps it on every row.
  tenantId: "acme-corp",
  userId:   "alice@example.com",
  storage:  new SupabaseAdapter({ client: supabase }),
  provider: new AnthropicSdkProvider({
    apiKey:    WORKSPACE_API_KEY,
    model:     "claude-sonnet-4-5",
    maxTokens: 4096,
  }),
});

// Family-lock pins tokenizer, prompt-cache key, tool-call dialect,
// and refusal pattern to the snapshot at session start. A
// long-running session never silently widens to a different
// snapshot mid-conversation — important when you run sonnet-4-5
// for one tier of customer and opus-4-7 for another.
const session = await runtime.sessions.create({
  provider: { type: "anthropic" },
  model:    { id: "claude-sonnet-4-5" },
});

for await (const event of runtime.executeMessage(
  session.id,
  "Summarize last quarter's filings.",
)) {
  // event: StreamEvent — paired with an AuditableCall row in your
  // Postgres carrying tenantId, turnId, modelId, tokenUsage.
}
```

The per-end-customer rollup falls out of one SQL query against your
own database:

```sql
-- Per-end-customer cost rollup inside a single Anthropic Workspace.
-- Reconcile the SUM against the Admin API's per-workspace total for
-- the same window.
SELECT
  tenant_id,
  COUNT(DISTINCT turn_id)                  AS turns,
  SUM((token_usage->>'input_tokens')::int) AS input_tokens,
  SUM((token_usage->>'output_tokens')::int) AS output_tokens
FROM harness_auditable_calls
WHERE created_at >= now() - interval '30 days'
  AND model_id   =  'claude-sonnet-4-5'
GROUP BY tenant_id
ORDER BY output_tokens DESC;
```

Three things this pattern gives you that the Anthropic Enterprise
contract alone doesn't:

1. **End-customer cost rollup inside a shared Workspace.** The Admin
   API tells you what the Workspace spent. Pleach's
   `(workspace_key, tenant_id, turn_id, token_usage)` row tells you
   which of your customers inside that Workspace spent it, joinable
   to your billing pipeline today.
2. **A hash-chained audit row in your own Postgres.** ZDR continues
   to govern what Anthropic retains. Pleach's `prev_hash` /
   `row_hash` chain governs what your downstream auditor sees when
   they ask what your product told a customer on a specific day.
3. **Replay-deterministic eval across snapshots.** Before promoting
   `claude-sonnet-4-5` to `claude-opus-4-7` for a regulated tier,
   you can replay last quarter's recorded turns against both
   snapshots and read the divergence diff. The fingerprint is the
   cache key; the `StreamEvent` log is the replay record.

A note on prompt caching: Anthropic's `cache_control: { type:
"ephemeral" }` breakpoints on system prompts and tool definitions
**keep working unchanged** — the SDK speaks to the API, Pleach does
not intercept the request body. Pleach's own
[fingerprint](/docs/fingerprint) is the cache key for *replay*, a
different concern from vendor-side prefix reuse. See
[Prompt caching](/docs/prompt-caching) for the distinction.

## What stays the same [#what-stays-the-same]

Pleach does not replace any of these. Your existing contract and
the vendor primitives it governs continue to work unchanged:

* **SSO / SAML** for Console access.
* **Zero Data Retention** as negotiated.
* **Workspaces** and per-Workspace API keys.
* **Admin API** for per-Workspace usage rollup.
* **Dedicated capacity** and **fine-tuned snapshots**.
* **Prompt-caching breakpoints** (`cache_control: { type: "ephemeral" }`).
* **Batches API**, **files API**, **tool-use beta flags**.
* **Extended thinking** (surfaced through Pleach as `thinking.delta`
  `StreamEvent`s, content unchanged).

## What changes [#what-changes]

|                                                   | Before Pleach                                                            | With Pleach                                                  |
| ------------------------------------------------- | ------------------------------------------------------------------------ | ------------------------------------------------------------ |
| End-customer cost rollup inside a Workspace       | Admin API gives Workspace total; per-tenant split is your code's problem | `SELECT … GROUP BY tenant_id` against your Postgres          |
| Audit row for what your product decided           | Anthropic's request log (vendor-shaped)                                  | `AuditableCall` row in your DB with `prev_hash` + `row_hash` |
| Replay a recorded turn against a new snapshot     | Re-run and eyeball                                                       | Fingerprint match → byte-identical; divergence → diff        |
| Multi-snapshot deployment without silent fallback | Manual discipline                                                        | locked at `runtime.sessions.create({ provider, model })`     |
| Subagent cost attribution to the parent turn      | Manual                                                                   | `SpawnTreeState` rolls up to parent `turnId`                 |

## No new vendor [#no-new-vendor]

Pleach is `npm install @pleach/core` plus the Postgres you already
run. There is no Pleach SaaS, no new ZDR contract to negotiate, no
new security questionnaire, no new SOC 2 review to wait on, and
nothing for your procurement team to onboard. The license is
[FSL-1.1-Apache-2.0](/docs/versioning) — source-available, usable
in production, auto-transitions to permissive Apache 2.0 two years
after first stable publish.

## Where each is load-bearing [#where-each-is-load-bearing]

| Concern                                      | Anthropic Enterprise's slot      | Pleach's slot                                            |
| -------------------------------------------- | -------------------------------- | -------------------------------------------------------- |
| SSO / SAML for Console access                | yes (vendor primitive)           | None — out of scope                                      |
| Zero Data Retention contract                 | yes (vendor primitive)           | None — governs vendor, not your DB                       |
| Per-Workspace usage rollup                   | Admin API                        | None — composes with Admin API                           |
| Per-end-customer rollup inside a Workspace   | None                             | `AuditableCall` row keyed on `tenantId`                  |
| Dedicated capacity / fine-tuned snapshots    | yes (vendor primitive)           | None — referenced by `modelId` on the row                |
| Prompt-caching breakpoints                   | yes (`cache_control: ephemeral`) | None — passes through unchanged                          |
| Tools API, batches, files, extended thinking | yes (vendor primitive)           | None — surfaced as `StreamEvent`s                        |
| Tamper-evident audit row in YOUR database    | None                             | `prev_hash` + `row_hash` chain                           |
| Family-locked, snapshot-pinned routing       | Single-vendor by construction    | locked at `runtime.sessions.create({ provider, model })` |
| Replay-deterministic eval                    | None (snapshot only)             | Fingerprint replays byte-identical `StreamEvent`s        |
| Subagent cost rollup to parent `turnId`      | None                             | `SpawnTreeState`                                         |
| OTel spans threaded by `tenantId`            | None                             | `runtime.spans` facet                                    |

The two coverage maps barely overlap. The Anthropic Enterprise
contract is the right tool for everything the vendor owes you;
Pleach is the right tool for everything your product owes its own
downstream auditors and finance team. Neither does the other's job.

## When you don't need Pleach [#when-you-dont-need-pleach]

* Single-tenant enterprise app where finance doesn't need a
  per-end-customer rollup, the Admin API's per-Workspace total is
  the answer they want, and there's no downstream auditor asking
  for a row in your own database. The Anthropic Enterprise contract
  is sufficient.
* One Workspace per end customer, no subagents, no replay
  requirement, eval is "we eyeball the latest snapshot." The
  vendor-side primitives carry the load.
* Internal tooling where the SDK's request log is a good-enough
  audit trail and you're not going to run regression replay across
  snapshots.

## Sibling SKUs that ride alongside the contract [#sibling-skus-that-ride-alongside-the-contract]

Two SKUs reach the same Enterprise-contract reader through
adjacent doors. Neither is required by the migration above; both
get raised by the same buying conversation.

* **`@pleach/coding-agent`** — the sandboxed coding-agent surface
  for the internal dev-tools team that often sits inside the same
  Enterprise contract footprint. The typed `CodingAgentRuntime`
  contract ships today at `0.2.0-alpha.0` on the `/runtime`
  subpath; method bodies and sandbox-provider wiring land in the
  next phase. The audit row is the same row, the `tenantId` axis
  is the same axis — an internal coding-agent's per-employee or
  per-team spend rolls up under the same `GROUP BY` as the rest
  of your Workspace traffic. See [Coding agent](/docs/coding-agent).
* **Language-agnostic contract.** The runtime substrate is wire
  shapes (HTTP+SSE, `StreamEvent`, `AuditableCall`, checkpoint
  envelope, version vector), not a TypeScript surface. A Go
  implementation round-trips a shared corpus of recorded turns
  against the contract today; the official `@pleach` Go runtime
  SKU is the next planned published implementation. This is the
  procurement-visible answer when Enterprise IT asks "is this
  TypeScript-only?" — the same contract supports a Java or
  Python runtime built against the same wire shapes. See
  [Language-agnostic contract](/docs/language-agnostic-contract).

## Where to go next [#where-to-go-next]

<Cards>
  <Card title="Pleach + Anthropic SDK" href="/docs/with-anthropic-sdk" description="The developer-direct case — you imported @anthropic-ai/sdk on a self-serve API key, no enterprise contract yet." />

  <Card title="The AuditableCall row" href="/docs/auditable-call-row" description="The schema of the row that lands in your Postgres on every LLM call, and what you can join it against." />

  <Card title="The tenant facet" href="/docs/tenant-facet" description="How runtime.tenant stamps tenantId on every row, span, and outbound HTTP — the substrate for per-end-customer rollup." />

  <Card title="Fingerprint" href="/docs/fingerprint" description="The replay-determinism primitive — what's in the cache key and why it's separate from vendor-side prompt caching." />
</Cards>
