Field note
Reconcile AI batch results before importing them
Treat the input manifest as the list of work owed, and prove what happened to every item.
An overnight classification job can finish successfully while leaving individual records unusable. The import process needs to establish which request each answer belongs to, whether the answer passed validation, and which input records still need attention.
Start with a durable request ledger. A downloaded results file should update that ledger; its line order should never determine which customer, invoice or document receives an answer.
Give every attempt a stable identity
OpenAI's Batch guide explicitly says output order can differ from input order and directs developers to match records using custom_id. Anthropic also returns Message Batch results against a custom_id. Gemini's file-based Batch API uses a caller-supplied key that is echoed in the result. The field names differ, so keep that translation in the provider adapter.
For each submitted record, store a business item identifier, input revision or digest, task version, attempt identifier and provider batch identifier. Keep the prompt and output schema versions as well. These fields let you distinguish a second attempt at the same task from a new task on a changed document.
Avoid putting names, email addresses or invoice descriptions in identifiers. A random or internal surrogate identifier is sufficient for reconciliation. The business system can resolve it where access is authorised.
Reject duplicate attempt identifiers before submission. Also retain the exact submitted manifest rather than reconstructing it later from a database that may have changed overnight.
Separate delivery, interpretation and acceptance
Use separate statuses for the provider result and the business outcome. A provider success means a response was generated. It does not establish that the response met your import rules.
An illustrative ledger might distinguish:
| State | What still needs to happen |
|---|---|
| Submitted, no terminal result | Establish whether the request is still running or unresolved |
| Provider error | Classify the error and decide whether another attempt is appropriate |
| Response received | Parse and validate the returned content |
| Validation rejected | Correct the input or route the item for review |
| Accepted | Make the result available to the authorised import step |
| Imported | Record the destination revision and import receipt |
Keep a refusal, empty response, truncated answer and schema failure distinguishable. Collapsing them into a blank cell makes a later reviewer guess what happened. This is particularly important when the destination treats an empty value as an instruction to erase existing data.
Reconcile the complete sets
After collecting the provider's success and error outputs, compare their identifiers with the submitted manifest. Investigate unknown identifiers, repeated identifiers and manifest entries with no corresponding terminal outcome. Count the sets as well as the raw lines: two results for one item must not disguise another item's absence.
Check that the result refers to the expected input revision. Suppose a product description changed after submission. The classification may be perfectly reasonable for yesterday's text and still be unsuitable for today's catalogue. Mark it stale rather than silently applying it to the current record.
Run the content validation separately. A category must belong to the permitted set. Extracted dates should use the agreed format. A summary must satisfy the constraints of the destination field. These checks are application decisions; the provider's batch status cannot supply them.
Only produce the import file once every submitted item has an explained outcome. An explained outcome can be a recorded exception awaiting review. It does not require every item to have an accepted answer.
Retry a defined subset
Provider documentation distinguishes errors within batches. Anthropic's examples, for instance, handle invalid requests separately from server errors. OpenAI documents expired requests in the batch error output. Use those distinctions when building the next attempt.
A malformed request needs correction. An outdated input needs a new revision. A transient service error may justify a bounded retry. A business validation failure may need a different instruction or a person, rather than repeated identical requests.
Create a new attempt identifier and retain its link to the original business task. Do not resubmit already accepted items simply because rebuilding the whole input file is easier. Protect the import operation against duplicate delivery independently of the model request.
Test the importer with an awkward file
Before enabling automatic imports, use a small synthetic batch. Shuffle its results, duplicate one identifier, remove another, add an unknown identifier and include a successful response with an invalid category. The importer should explain each discrepancy and produce no unintended destination changes.
Start production with results held for review, then enable a narrow import scope. Keep the previous destination values or a reversible change record appropriate to that system. The finance output review guide covers the separate judgement required when an accepted technical response feeds financial work.
References
- OpenAI, Batch API guide. Accessed 17 October 2026.
- Anthropic, Batch processing. Accessed 17 October 2026.
- Google, Batch API. Accessed 17 October 2026.