- Duale AI
- Documentation
- Security
- Secure Integration
Secure Integration: Delivery, Approval, and Validation
Describes how to control duplicate attempts, keep human approval outside the Tool Call, and validate results before business actions in SDK Tool integrations.
This page covers owning controls, duplicate attempt handling, human approval patterns, and result validation for secure SDK Tool integration.
- Owning controls for credentials, identity, and domain validation.
- Duplicate attempt and uncertain outcome handling for SDK Tool delivery.
- Two-step human approval pattern kept outside the Tool Call.
- Result validation and content mark verification before business actions.
Summaries were generated by AI.
Apply the controls that match what your integration can reach. Every integration protects credentials and validates results. When a Tool can change business or external state, control duplicate attempts and uncertain outcomes, and authorize each protected operation. Add human approval only when an applicable law, policy, or impact rule requires it.
The implementation steps on this page apply directly to SDK Tools whose code you control. An MCP Connection cannot add validation or an approval wait to a remote Tool. Put the same control in the remote system, or expose the protected operation through an SDK Tool or separate authorized process. Operate Tools explains remote Tool outcomes, and Tool Call outcomes defines each outcome. Tools reference defines MCP call behavior and limits.
Start from the owning controls
Before a production review:
- Load and rotate the Agent Identity token through your secret manager. Credentials and lifecycle owns the sequence and propagation limits.
- Treat SDK Tool results and errors as content that reaches the model provider. Authoring SDK
Tools owns return-value, exception, logging, and
error_transform=behavior. - Match Agent Identities, Library Grants, and Tenant roles to the intended access boundary. Identity owns the principal model and links to the controls.
- Define domain validation and the outcome when no acceptable result arrives. SDK errors and content marking own their exact contracts.
For a material Effect that can repeat or remain uncertain, also provide an owning transaction, business record, destination idempotency facility, or durable claim store outside the Task history.
Control duplicate attempts and uncertain outcomes
SDK Tool delivery is not exactly once. The same (task_id, tool_call_id) can reach more than one Tool Host process,
and a timeout does not prove whether an Effect occurred. Authoring SDK Tools defines the
complete delivery and retry contract.
Choose the lightest mechanism that handles redelivery:
- A read-only or intrinsically repeat-safe Tool needs no durable state solely for redelivery.
- When the owning system already accepts a business-operation identifier or destination idempotency key, validate and reuse it. If an external result can remain uncertain, also use the final path below.
- When a material Effect and its owning record share one store, write both in one transaction. No intermediate state remains from which a crash can replay the Effect. Prefer this path when the work can use it without a costly redesign.
- When a material Effect leaves that store or can have an uncertain outcome, use a durable claim, a result record, and
reconciliation keyed on
(task_id, tool_call_id).
For a durable delivery or claim record, key on the pair and store the Tool name and a canonical input digest. Different data under the same pair is an identity conflict: do not act. The SDK also uses the pair to suppress duplicates within one process; that does not cover a second process. A provider can reuse a Tool Call ID across model turns in one Task; use separate Tasks when distinct calls must not share the key.
When one Tool can request distinct business Effects, include a validated business-operation identifier in the Tool input or move the Effect into a separate acting process. The identifier distinguishes business Effects; it does not replace the Tool delivery key.
For an external or uncertain Effect, a local transaction cannot make the Effect atomic. Use this sequence:
- Atomically claim a record keyed by
(task_id, tool_call_id), and store the Tool name and canonical input digest in the same transaction. - If an existing record carries different data, stop without acting and investigate the identity conflict.
- Return a completed record’s stored result. If another worker holds an in-progress claim, wait for the final record or return a retryable state without acting.
- Pass the validated business-operation identifier when the destination accepts an idempotency key.
- Store the result as complete before you release the claim.
If the external result is uncertain, mark the record as uncertain and reconcile it. Do not run the action again without checking the external system.
Verify. For a material external Effect, call the claim path twice at once with one (task_id, tool_call_id) pair,
then again from a second process that shares the durable store. Assert that the external operation is attempted once and
every completed call returns the stored result. Repeat with different input under the same pair and assert that no
operation runs.
Recover. When a timeout leaves it uncertain whether an Effect occurred, read the external system before you retry. Record the result under the same identifier or run the compensating action; do not guess that the first attempt failed.
If a person must approve, keep the wait outside the Tool Call
When a person must decide, an SDK Tool that blocks while they decide can time out, and the Tool request can be delivered again while they are still deciding. Split that decision into two steps:
- The Tool proposes
It writes a proposal keyed by
(task_id, tool_call_id)and returns. Recording the proposal is an Action and can create an External Effect, but it does not attempt the proposed business operation. A redelivery writes the same proposal instead of applying that operation twice. - A separate process acts
It shows the proposal to a person and records the decision. If the person approves it, the process claims that decision in your state machine before it executes the business operation once.
An MCP Connection has no Ask policy, approval queue, or wait list. Use the two-step pattern through code that you own instead of allowing the remote operation to run before approval.
Commit the approval or claim transition before attempting the approved operation. This prevents a retry, restart, or second worker from holding a concurrent claim; it does not make an external operation exactly once. Use destination idempotency where available. After an uncertain outcome, let no worker act again until reconciliation establishes the external state. Threat model names the three properties that make this gate necessary.
Verify. Deliver the same proposal twice and accept it twice. Assert that one proposal exists, one state transition succeeds, and the approved business operation is attempted once.
Recover. If the process stops after the state transition, mark the proposal as uncertain. Reconcile the external system before another worker acts on it.
Validate the result before you act on it
A schema-valid result is well-formed, not necessarily correct. Apply domain rules before a result reaches a business action, and treat model-reported confidence as prose rather than approval. Define what happens when no acceptable result arrives before the deadline. Keep the correlation identifiers from a failure with the business record.
If the workflow relies on a content mark, verify it at the receiving edge before text changes and define how the
application handles unmarked. SDK errors defines the typed Task outcomes and retry
boundary. Content marking defines the four verdicts and their limits.
Verify. Block a schema-valid result that violates a domain rule, a Task that crosses its deadline, and a
non-retryable filtered Task before any business action. If you rely on a content mark, change one character and confirm
that the verdict stops being valid.
Recover. Keep the business record pending or rejected. Retry only when the typed failure permits it. Otherwise, change the request or send the case to a person with the correlation identifiers.
Return to Security to place these controls in the lifecycle of one Task.