An AI agent submits a purchase requisition to an ERP system. The ERP creates the record, but the response never reaches the agent. A timeout appears. The agent tries again, and purchasing now has two requests for the same materials.
The model may have understood the task perfectly. The failure happened at the boundary between a conversational system and an application that changes business records. Before giving an agent write access, engineers need a clear answer to a mundane question: what happens when the same action arrives twice?
Consider an illustrative workflow in which an employee asks an assistant to prepare a requisition for replacement equipment. The assistant gathers the product identifiers, quantity, cost center and delivery location. A manager approves the request. An integration service then submits it to the ERP.
If the connection breaks after submission, the integration service cannot infer whether the requisition exists. Treating that uncertainty as a definite failure creates the duplicate risk. Microsoft's Retry pattern guidance explicitly describes this lost-response scenario and the unintended effects of repeating a non-idempotent operation.
Build an explicit unknown state into the workflow. The user-facing response can say that submission is being checked. It should not announce failure and invite a fresh request while the original operation may still be completing.
For this requisition workflow, create an operation identifier when the approved business action is recorded. Keep it outside the model's conversational memory. The integration layer should reuse that identifier when retrying the same action, even if the agent session restarts or a queue delivers the work again.
Store the intended action alongside it: the requesting organization, requisition fields, approval reference and a fingerprint of the normalized payload. If a caller reuses the identifier with different quantities or a different destination, reject the mismatch instead of silently treating it as the original request. AWS discusses caller-supplied identifiers and mismatched parameters in Making retries safe with idempotent APIs.
A practical record might move through prepared, approved, submitting, confirmed and needs-review states. Those names are design choices, not a platform standard. The useful property is that an operator can tell what was authorized, what was attempted and what remains unresolved without reconstructing a chat transcript.
The identifier must represent one business intention. A deliberately approved second requisition needs a new identifier even if its fields match the first. Conversely, asking the model to generate a fresh identifier on every attempt defeats duplicate protection.
A local action log is helpful, but it cannot make a remote ERP call atomic. There is still a gap between the ERP accepting the requisition and the integration service recording success. A crash in that gap leaves an uncertain result.
Prefer a destination API that accepts an idempotency key and documents its behavior. Where that is unavailable, investigate whether the business system can enforce a unique external reference and return the existing record for that reference. A search followed by an ordinary create is insufficient: two workers can both search before either creates anything.
For a consumer updating its own database, the processed-message record and business update can share a transaction. That protection does not automatically extend to a separate application. Microsoft's Idempotent Consumer pattern explains this distinction and the need for additional handling when external effects cannot join the transaction.
When the destination offers neither reliable duplicate protection nor a trustworthy status lookup, automatic retry of an uncertain write may be the wrong policy. Route it to reconciliation. An employee can check for the requisition and resolve the operation before another submission is allowed. This costs time, but makes the uncertainty visible instead of multiplying business records.
The assistant can explain a failure, but retry timing and eligibility belong in deterministic application logic. Retry temporary transport or service faults within a bounded budget. A missing permission, invalid product identifier or rejected approval needs correction rather than another identical call. Use delays and backoff appropriate to the destination, and avoid stacking independent retry loops in the agent, connector and worker.
Separate read and write tools. A tool that checks submission status should have a clearly different contract from one that creates a requisition. Return a structured result containing the operation identifier, status, destination record identifier when known, and whether reconciliation is required. The assistant then has specific evidence for its response.
Approval also needs a defined scope. In this example, bind it to the exact requisition payload and apply an expiry rule appropriate to the process. A changed quantity or expired approval should return to review. Recovery should not become a way to submit a different transaction under an old approval.
These controls complement the identity and permission boundaries covered in our article on connecting AI agents safely to ERP and CRM systems. Permission determines whether an action is allowed; recovery design determines what happens when its execution becomes uncertain.
Before enabling the workflow, test a lost response after a successful write, a worker restart during submission, two concurrent deliveries, and a retry carrying altered fields. Also test an expired duplicate-protection window. A key that the destination has forgotten may no longer prevent a second write.
For each case, inspect the actual business records and the operation log. A friendly assistant response is not evidence that recovery worked. The acceptance criteria should include no unintended duplicate requisition, an accurate status, and enough evidence for an operator to resolve uncertainty.
Track unresolved submissions and reconciliation time alongside ordinary error rates. A low error count can conceal a backlog of actions whose outcomes nobody has confirmed. Give that backlog an owner and a recovery procedure before increasing the agent's workload.
Business Dynamics helps teams turn these integration details into workable enterprise applications. If an agent is moving from answering questions to changing records, our enterprise AI integration work can help define the action contract, recovery path and tests before rollout.