Compatibility: Pactmark 0.1.x. @pactmark/ai-sdk demonstrates Vercel AI SDK integration as an optional peer dependency; its types never enter core APIs.

What an adapter is responsible for

A model adapter normalizes five things and nothing else:

Streamed content

Provider chunks become a bounded, countable stream the runtime can enforce limits against.

Tool requests

Provider tool-call shapes become a tool_call referencing a registration digest.

Finish reasons

Normalized so the runtime can distinguish “done” from “ran out of tokens”.

Usage accounting

Input and output usage, with an explicit failure when it cannot be accounted for.

Retry classification

timed_out, retryable or uncertain — the third one is not a synonym for the second.

Nothing else

An adapter does not decide policy, resolve credentials for other calls, or write events.

The two profiles you must declare

Every one of these fields is a claim you are making about your provider contract. They become part of modelSecurityProfileDigest, which travels with the accepted work order — so a change of region, retention or training posture is a visible identity change rather than a quiet one.
providerOutputCap: "enforced" asserts that the provider itself will cap output. If your provider cannot, say so — an unsupported output cap or unusable usage accounting fails before export rather than being discovered when the bill arrives.

Credentials

Figure 1. The runtime takes a pessimistic model-call reservation first, then issues a short-lived ModelCredentialRef bound to that specific call. The adapter resolves it and nothing else.
Raw prompts, completions and hidden reasoning stay out of ordinary telemetry and evidence. If your adapter wraps a client that logs requests by default, turn that off — the redaction canaries will catch it in CI, but you should not need them to.

Retry classification is a safety decision

Getting this wrong is expensive in both directions. Classifying an uncertain outcome as retryable duplicates work; classifying a retryable one as uncertain parks runs that could have proceeded.
A model call that ends uncertain retains its maximum charge in the reservation. That is deliberate: the alternative is a crash-loop that leaks budget.

Deterministic models for tests

You do not need a provider key to test agent behaviour, and you should not want one in CI:
The deterministic driver covers required behaviour — ordering, limits, tool binding, finish reasons — without a live provider. Every example in the repository runs this way.

Registration and drift

A model adapter registration binds provider, model factory, security and resource profiles, endpoint, implementation version and source digest. Changing any of them changes the digest, and a run accepted against the old one will not silently continue against the new one — KAF_MODEL_ADAPTER_MISMATCH.

Observability and privacy

What may be recorded about a model call, and what may not.

Testing agents

Building deterministic scenarios around a fake driver.