Skip to lesson

AWSAWS Certified Generative AI Developer - Professional2026-102.1 Implement agentic AI solutions and tool integrations

Preserve action identity across tool retries

Completed by the knowledge check

Learning objective

Make side-effecting tool calls retry-safe using idempotency keys, bounded retries, and compensating actions.

Core idea

A tool timeout does not tell you whether the business action happened. A refund can reach the payment service even when its response never reaches the agent. Retrying with a fresh action identifier can issue another refund. Refusing every retry can leave a completed refund unrecorded.

Separate the logical action from its delivery attempts. Give the action a stable idempotency key, persist its outcome, and preserve that key through retries and recovery. Then limit how much recovery you attempt and define what happens when a multi-step operation cannot finish. Idempotency prevents duplicate effects within its contract; compensation handles effects you intentionally need to reverse.

AWS recommends idempotent Lambda code because duplicate processing can occur. The enforceable boundary belongs in the tool implementation and the business service, rather than in an instruction asking the model to avoid repetition. For typed tool validation, see 2.1.10; this lesson addresses what happens after a valid action starts.

How it works

Bind the key to approved intent

Assign an application-controlled action ID after you validate and authorize the request. Combine it with the trusted tenant identity and operation name to define the deduplication scope. Store a digest of the consequential parameters alongside the key: target account, amount, currency, and approved revision, for example. These are application design choices, not DynamoDB field requirements.

Reuse the same key only for the same intent. If the parameters change, reject the conflicting reuse rather than silently treating a different action as a duplicate. Do not derive the key solely from identical arguments: two separately authorized refunds of the same amount can be legitimate. Conversely, a model tool-call ID or Lambda invocation ID identifies an attempt and should not automatically become the business action identity.

Choose a retention period that covers the application’s permitted replay and recovery window. Reject or reconcile late replays after that window; do not assume an expired record still protects the action. Human approval must bind to the same immutable action parameters, as described in 2.1.9.

Record ownership and the outcome

AWS names the Powertools for AWS Lambda idempotency utility as a packaged option for making handlers idempotent. This protects handler execution; it does not make a downstream payment call atomic.

One implementation uses a DynamoDB action ledger. Use PutItem with ConditionExpression: attribute_not_exists(action_key), where action_key is the table’s partition key, to claim an action without replacing an existing record. A ConditionalCheckFailedException means the claim condition failed; inspect the existing action rather than treating it as permission to execute again.

Define application statuses such as IN_PROGRESS, COMPLETED, and UNKNOWN. A completed duplicate returns the recorded business result. An action still owned by another attempt waits within a deadline or returns a pending result. An unknown outcome enters reconciliation. Preserve the original request digest, downstream transaction identifier, and result so recovery can distinguish these cases.

A claim record alone cannot make an external effect atomic. The process can fail after issuing the refund but before recording completion. Pass the stable key to the downstream service if it supports an idempotency contract. If it does not, reconcile by a stable business reference before authorizing another attempt. An expired lease proves that a worker lost ownership; it does not prove that a payment failed.

When the effect and ledger updates are all DynamoDB writes within the same supported transaction scope, TransactWriteItems can commit them atomically. Its ClientRequestToken makes identical transaction requests idempotent for 10 minutes after the first request completes. Reusing the token with changed parameters inside that window is rejected with IdempotentParameterMismatchException. This token does not deduplicate an external payment call or provide an indefinite business replay window.

Bound retries and compensate deliberately

Configure Step Functions Retry through ErrorEquals, IntervalSeconds, MaxAttempts, BackoffRate, MaxDelaySeconds, and JitterStrategy: FULL; see 2.1.5 for their definitions. For example, choosing MaxAttempts: 2 permits two retries in addition to the initial attempt. These are policy choices, not a universal safe configuration.

Retry transient failures only when repeating the action is safe. Route invalid parameters, authorization denials, and conflicting key reuse to explicit failures. A timeout after dispatch requires the downstream idempotency contract or reconciliation. Coordinate retries across the SDK, tool adapter, and workflow so one logical action has a shared attempt budget. Step Functions resets configured retry counts when eligible states rerun on redrive, so the workflow’s local counter is not a lifetime action budget.

After retries are exhausted, use Catch to route to reconciliation or compensating tasks. A saga records the successful steps and invokes business-defined compensations if a later step fails. AWS Prescriptive Guidance shows Step Functions coordinating order, inventory, and payment operations with compensating Lambda functions. Compensation participants must also tolerate repeated execution. Give each compensation a stable identity tied to the original action and record its outcome.

Key distinctions and trade-offs

The recovery decision depends on the effect’s known state:

SituationRecovery decision
The original action completedReturn its stored result without repeating the effect
Another attempt owns the actionReturn pending or wait within the shared deadline
The remote effect has an uncertain outcomeQuery or reconcile by business identity before replay
A later saga step failedCompensate confirmed prior effects according to business policy

Idempotency does not mean every response byte is identical. DynamoDB documents that repeated TransactWriteItems requests can report different consumed capacity while producing the same effect. The business result is the contract that matters.

Compensation is a separate business action, not a database rollback across services. Releasing inventory can restore availability; sending an email cannot unsend it. AWS documents that sagas lack transaction isolation. Concurrent changes can therefore require semantic locks or business checks before compensation. A failed compensation remains unfinished work that needs recovery, not a successful cancellation.

Architecture / decision scenario

An agent handles an approved replacement order. A Step Functions workflow reserves stock, refunds the damaged item, and creates the replacement shipment. Each side-effecting tool receives a distinct action key under the same trusted tenant and case identity. The tool adapter stores each request digest in DynamoDB before dispatch.

The refund service accepts the key, completes the refund, and loses its response. The workflow performs two bounded retries with the same key and capped jittered delays. It retrieves the original refund result instead of generating another refund. If the refund service cannot establish the outcome, Catch sends the case to reconciliation rather than instructing the agent to try a different key.

Shipment creation then fails permanently. The workflow records that the refund succeeded, releases the confirmed reservation with its own idempotent compensation, and escalates the remaining business decision. It does not automatically charge the customer again: that requires a separately authorized policy decision. A retry of the release returns its recorded result. The case reaches a terminal outcome only after required compensation or reconciliation is complete.

Common exam traps

  • Generating a fresh idempotency key for each delivery attempt.
  • Treating a timeout or expired ownership lease as proof that no effect occurred.
  • Assuming a DynamoDB claim makes a remote service call atomic.
  • Extending ClientRequestToken protection beyond its 10-minute window.
  • Treating Step Functions redrive as preserving the original retry count.
  • Retrying compensations without their own duplicate-effect protection.

What to remember

  • Bind a stable key to one authorized intent and reject parameter conflicts.
  • Persist ownership, downstream identity, and outcomes outside agent reasoning.
  • Reconcile uncertain effects before replaying them.
  • Bound recovery across layers and across redrives.
  • Compensate confirmed effects through explicit, retry-safe business actions.

Knowledge check

References