Region-pinned agent
An agent that pins region, family, and model per call class — with parity-validation suites and deterministic failover discipline a procurement reviewer can read.
A region-pinned agent is the shape an enterprise reaches for when the AI program is already in production and the question stops being "does it work" and starts being "is the inference auditable under the contract." Region of execution is fixed per call class. The model family is fixed per call class. Failover stays inside the vetted list. A parity-validation suite proves the substitute behaves the same as the primary.
This page walks the four pieces a procurement reviewer asks about: region and family pinning at session start, parity validation across the failover list, attestation of which model served which call, and the audit row a regulator reads.
Related shapes. Regulated-domain agent if the domain itself (HIPAA, FedRAMP, PCI, 21 CFR Part 11) drives the constraint. Multi-tenant SaaS agent if one runtime serves many region-pinned customers. Cloud-routed agent if the inference runs through AWS Bedrock, Azure OpenAI Service, or GCP Vertex AI rather than the lab's direct API.
What you're building
A turn loop whose routing decisions are pre-declared, not discovered at runtime. The shape is the same regardless of which lab is the primary:
- A session locks one family per call class — utility, reasoning, converse, synthesize each pin to a vetted family at construction.
permittedFamiliesconstrains the cascade to the families the contract clears. Out-of-list providers can't be reached even as a last-resort fallback.- A parity-validation suite runs the substitute family against the primary on a held-out fixture set. The diff is what proves the failover is safe to take.
- Every call writes one ledger row carrying the family, the model, the call class, and the region.
Lock the permitted family set at session start
permittedFamilies locks the set of provider families a session
can ever reach. The cascade walks rungs inside that set only;
which family serves each call class is decided by the model-family
matrix (family × callClass), never widened past the locked set.
// lib/runtime.ts
import { SessionRuntime, definePleachPlugin } from "@pleach/core";
export function buildPinnedRuntime(req: AuthedRequest) {
return new SessionRuntime({
provider: anthropicProvider,
storage: new SupabaseAdapter({ client: supabase }),
checkpointer: new SupabaseSaver({ client: supabase }),
plugins: [definePleachPlugin("cleared-tools", { tools: clearedTools })],
// The reachable family set is locked at session start. Which family
// serves each call class (synthesize / reasoning / converse / utility)
// is governed by the model-family matrix (family × callClass), not a
// per-session field — the cascade only ever walks families in this set.
permittedFamilies: new Set(["anthropic", "openai"]),
// Residency is a hard constraint: an out-of-region family can't be reached.
permittedRegions: new Set([req.region]),
tenantId: req.tenantId,
});
}The lock is structural, not advisory. An out-of-list family can't be reached under any cascade condition. The permitted set is recorded in the session row — an auditor reading the contract clause and the session row sees the same family list.
See Family lock for the cascade rules and Call classes for what each class covers.
Parity validation across the failover list
A failover claim is unverified until the substitute behaves the
same as the primary on a held-out fixture set. @pleach/eval
records a fixture run against the primary, then replays it
against each family in the permitted list.
import { createReplayRuntime } from "@pleach/replay";
for (const family of ["anthropic", "openai"]) {
const challenger = buildPinnedRuntime({
...req,
overrideCallClassFamilies: { synthesize: family },
});
const replayRuntime = createReplayRuntime({
sessionRuntime: challenger,
tenantId: req.tenantId,
});
const replay = await replayRuntime.replayTurn({
chatId: sessionId,
tenantId: req.tenantId,
messageId: goldenMessageId,
});
// `replay.state` is the `HydratedHarnessState` projection the turn
// closed on; `replay.sequenceNumberRange` bounds the event window
// walked. There is no built-in `.diff` field — compare the tool-call
// set / refusal pattern / citation count across families from the
// returned state yourself.
console.log(family, replay.state, replay.sequenceNumberRange);
}The replayed state is what procurement reviews. A failover that changes
the refusal pattern or the tool-call set isn't safe to take silently.
(For tamper-evidence rather than parity, @pleach/replay also ships a
hash-chain verifyIntegrity verdict — { valid, brokenAt? } — that
proves an event log wasn't altered between record and replay.)
What today ships
Today, @pleach/core ships the family-strict cascade,
permittedFamilies, deterministic replay, and the audit row
that records which family served each call. @pleach/eval
ships the recording + replay engine that drives the parity
suite.
Roadmap
Roadmap pieces, in expected order:
- Per-call-class family pinning. Today
permittedFamilieslocks the reachable family set; the underlying matrix already keys on(family, callClass), but a per-session surface that pins a specific family to each call class is still being widened. - Cascade-time region enforcement.
permittedRegionsis a real session field today, enforced at the lock-time guard (isRegionPermitted). Cascade-time enforcement — failing closed on an out-of-region resolution mid-cascade — lands when the matrix grows a region-keyed dimension. Until then region is a lock-time constraint, not an in-cascade one. - Article 12 attestation pack. A signed manifest of which family + model + region served each turn, in a shape an EU AI Act reviewer can verify offline. The audit row carries the underlying data today; the signed-attestation surface ships later.
- Parity-suite scaffold. The replay engine handles the
per-turn diff today; a multi-fixture parity suite that
aggregates pass/fail across a corpus and reports per-family
divergence is a planned
@pleach/evaladdition.
No dates. Track the upstream package READMEs and CHANGELOG for landing notices.
What the audit row carries
Every row in harness_auditable_calls carries the fields a
procurement reviewer reads first:
| Column | Carries | Reviewer question it answers |
|---|---|---|
record_id | ULID, monotonic | "is the chain intact?" |
tenant_id | runtime context | "which business unit?" |
turn_id | one per user message | "what was the unit of work?" |
call_class | utility / reasoning / etc. | "which class served this?" |
family | resolved family | "did routing stay in the contract list?" |
model_id | resolved at call time | "which model produced this?" |
region | runtime context | "did the call run in the cleared region?" |
created_at | server clock | "when, to the millisecond?" |
See Auditable call row for the full column list.
Where to go next
Family lock
The permittedFamilies constraint and the cascade rules it constrains.
Call classes
utility, reasoning, converse, synthesize — the four classes a per-class pin keys on.
Model resolution matrix
The (family, callClass) lookup the runtime uses to resolve a model at call time.
Eval and replay
Recording, replay, and the diff engine the parity suite runs on top of.
Cloud-routed agent
The sibling shape for buyers reaching the same models through Bedrock, Azure OpenAI, or Vertex.
Regulated-domain agent
The HIPAA / FedRAMP / 21 CFR Part 11 shape, when the regulator drives the constraint instead of procurement.
Cloud-routed agent
An agent reaching Anthropic, OpenAI, or Google models through AWS Bedrock, Azure OpenAI Service, or Vertex AI — IAM-federated, VPC-bound, region-enforced.
Air-gapped deployment
What v1 ships that makes a contained, perimeter-bound deployment reachable, and what lands in v2+ to close the remaining gaps.