ai@7.0.94 is a patch release that reshapes the experimental batch API. Seven names leave the package and nine arrive in their place: a batch is no longer text-specific, and the model it runs against is now named per request rather than once for the whole batch. The package’s changelog files the work under “feat: support per-request models in batch.” Only code that imports one of the seven removed names from ai is affected.
What changed
experimental_startTextBatchis nowexperimental_startBatch, and it takes a provider rather than a model.Experimental_StartTextBatchOptionsandExperimental_StartTextBatchResultgo with it, replaced byExperimental_StartBatchOptionsandExperimental_StartBatchResult. The new options carry an optionalprovider, which defaults to the global provider or to the Vercel AI Gateway, in place of the requiredmodel.- The batch-level
model,tools,toolChoice,toolOrderandtoolsContextmove onto each request. A request is now discriminated by modality:Experimental_TextBatchRequestkeeps its name but requirestype: 'text'and its ownmodel, andExperimental_BatchRequestis the union over modalities. Experimental_TextBatchandExperimental_TextBatchReferenceare gone.Experimental_BatchandExperimental_BatchReferencereplace them. The reference is a new shape as well as a new name:versionis2, and thetypeandmodelIdfields are no longer part of it, since a batch can hold requests against more than one model.Experimental_BatchOperationOptionssplits in two.experimental_getBatchStatusandexperimental_getBatchResultskeep their names, but now takeExperimental_GetBatchStatusOptionsandExperimental_GetBatchResultsOptions, each naming aproviderinstead of amodel.Experimental_BatchLanguageModelis gone. Nothing replaces the type directly. A model is a plain model id string on a request, and the provider is typed byExperimental_BatchProvider.
Before and after
The import Emendant’s matchers look for, one per removed name:
import { experimental_startTextBatch } from 'ai';
export { experimental_startTextBatch };No transform can write any of the seven, so there is no rewritten file to show. An assisted patch is offered for each, and what it has to work out follows from the two option types. In ai@7.0.93, the model and the tools belonged to the batch:
type StartTextBatchOptions<TOOLS extends ToolSet = ToolSet> = { model: BatchLanguageModel; requests: ReadonlyArray<TextBatchRequest>; tools?: TOOLS; toolChoice?: ToolChoice<NoInfer<TOOLS>>; providerOptions?: ProviderOptions; webhookUrl?: string;} & BatchRequestOptions;In ai@7.0.94, the batch names a provider and each request names its own model:
type StartBatchOptions<TOOLS extends ToolSet = ToolSet, PROVIDER extends BatchProvider = BatchProvider> = { provider?: PROVIDER; requests: ReadonlyArray<BatchRequest<InferBatchModelIds<PROVIDER>, TOOLS>>; providerOptions?: ProviderOptions; webhookUrl?: string;} & BatchCallOptions;Migration guidance and its limits
The seven removed names carry an assisted fix. Name a model provider on the command line or in emendant.json and emendant fix tries each one; without one they are reported with their guidance and nothing is sent anywhere. Expect declines among them: the guidance names the construct that went and tells the model to set fixed to false rather than invent a replacement, and several of these have no replacement that is a rename. Experimental_BatchLanguageModel has no direct successor at all, and experimental_startTextBatch becomes a differently shaped call rather than a differently spelled one. A patch that is written is proved in a copy of your repository moved to 7.0.94 and put through whichever of your own typecheck and tests it finds there, and withheld if it fails.
The two findings on experimental_getBatchStatus and experimental_getBatchResults are report only. Both fire at the options literal rather than at an import, because the model key those calls took is the thing that went, and what belongs there instead is a provider on a differently named type rather than a key to rename.
Rename the call and the two option types, then move what the batch used to hold down onto the requests. Each entry in requests takes type: 'text' and a model, plus the tools, toolChoice, toolOrder and toolsContext that used to sit beside requests. Drop Experimental_BatchLanguageModel from your own signatures and use the model id string the request expects.
Persisted references do not survive the upgrade. A batch reference stored by ai@7.0.93 is version 1 and carries type and modelId; the code reading it in 7.0.94 expects version 2 and neither field. A batch started before the upgrade has to be drained before it, or its reference migrated by hand.
The matchers fire on the import statement alone. Two things a scan therefore stays quiet about: Experimental_BatchReference and Experimental_TextBatchRequest kept their names while changing shape, so importing either is not a finding even though the code around it may no longer compile. A clean scan says a file does not import these seven names from ai, and nothing more about the release.
What Emendant detects, fixes and verifies
9 changes in ai 7.0.94. 0 patched by a transform, 7 patched only with a model provider you name, 2 report only. Every patch is proved in a copy of your repository before it is offered, and its header names the checks that passed. This table is generated from the feed entry, so it cannot claim more than the entry does.
| Change | Severity | Detects | Fix | Verified by |
|---|---|---|---|---|
Removed Experimental_BatchLanguageModelai-npm-7.0.94-experimental-batch-language-model-removed | Breaking |
| Patch, only when you name a model provider | Your typecheck and tests |
Removed Experimental_BatchOperationOptionsai-npm-7.0.94-experimental-batch-operation-options-removed | Breaking |
| Patch, only when you name a model provider | Your typecheck and tests |
Removed Experimental_StartTextBatchOptionsai-npm-7.0.94-experimental-start-text-batch-options-removed | Breaking |
| Patch, only when you name a model provider | Your typecheck and tests |
Removed Experimental_StartTextBatchResultai-npm-7.0.94-experimental-start-text-batch-result-removed | Breaking |
| Patch, only when you name a model provider | Your typecheck and tests |
Removed Experimental_TextBatchai-npm-7.0.94-experimental-text-batch-removed | Breaking |
| Patch, only when you name a model provider | Your typecheck and tests |
Removed Experimental_TextBatchReferenceai-npm-7.0.94-experimental-text-batch-reference-removed | Breaking |
| Patch, only when you name a model provider | Your typecheck and tests |
Removed experimental_startTextBatchai-npm-7.0.94-experimental-start-text-batch-removed | Breaking |
| Patch, only when you name a model provider | Your typecheck and tests |
Removed model from the first argument of experimental_getBatchResults()ai-npm-7.0.94-experimental-get-batch-results-argument-1-model-removed | Breaking |
| Report only | Not applicable |
Removed model from the first argument of experimental_getBatchStatus()ai-npm-7.0.94-experimental-get-batch-status-argument-1-model-removed | Breaking |
| Report only | Not applicable |
emendant explain <change-id> prints any row's entry, guidance and sources at the terminal.
Coverage
- Snapshot
2026-09-20.1, sequence 27, signed 20 September 2026- Minimum CLI
emendant@0.1.4- Feed entry
feed/npm/ai/7.0.94.json
emendant feed status shows the snapshot your machine holds, and emendant feed update fetches the latest.
Primary sources
Every claim above was checked against these, each pinned to the release rather than to a default branch.
Scan your repository
Runs locally, reads your lockfile and source, sends nothing anywhere.
npx emendant scanThen npx emendant fix writes the patches the table says exist. The getting started guide covers the flags and the patch grades.