An AI application can appear to handle one user request while sending several requests to its model provider.

A double click, a timeout handler, or a reconnect routine can trigger another generation before the first request has finished. The interface may display only the final answer, leaving the duplicate work visible mainly in backend logs and API usage.

This tutorial explains how to ask TRAE to implement a request lifecycle that prevents common duplicate submissions.

The example concerns an application you build with TRAE and connect to DeepSeek through an API gateway. It does not describe how to change TRAE's own internal model connection.

If you need the initial application structure, begin with the TRAE API gateway application tutorial.

1. Define a user operation separately from a network attempt

A user operation is an intentional action, such as “summarize this note.”

A network attempt is one effort to deliver or process that operation.

The same operation can produce multiple attempts because a browser connection fails or a user presses a button again. Those attempts should not automatically create new model generations.

Give the operation a stable identifier. Generate a new identifier when the user intentionally starts a new task, not whenever a transport retry occurs.

Keep the identifier associated with the authenticated user and the submitted payload. Reusing an identifier with different input should produce a conflict rather than silently returning an unrelated answer.

This is an application design. It is not a claim that your model provider supports an idempotency header.

2. Give TRAE a precise implementation request

Use a prompt that describes observable behavior:

Update the existing AI summary application.

Requirements:
- Keep the model API key on the backend.
- Assign one operation ID to each intentional submission.
- Prevent simultaneous submissions from the current page.
- Store operation state on the server.
- Repeated requests for the same user and operation ID
  must reuse the existing operation.
- Reject the same operation ID with a different payload.
- A browser timeout must not automatically create
  another upstream model request.
- Provide a status lookup for an existing operation.
- Test double clicks, reconnects, and unknown outcomes.

Do not change the application's selected model.
Explain any storage or deployment assumptions.

Review the generated implementation. A disabled button alone does not satisfy these requirements.

The task is independent of product naming. TRAE's current product page describes its work and coding environment; use the coding workflow available in your installed version.

3. Add a frontend submission guard

A simple guard prevents repeated clicks while the current page is waiting.

let submitting = false;
let pendingOperationId = null;

async function submitSummary(text) {
  if (submitting) return;

  if (pendingOperationId) {
    throw new Error(
      "Check the existing operation before starting another."
    );
  }

  pendingOperationId = crypto.randomUUID();
  submitting = true;

  try {
    const response = await fetch("/api/summaries", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        operation_id: pendingOperationId,
        text
      })
    });

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}`);
    }

    return await response.json();
  } finally {
    submitting = false;
  }
}

function markOperationSettled() {
  pendingOperationId = null;
}

These application endpoints and functions are proposed interfaces, not TRAE or gateway APIs.

Call markOperationSettled() only after the application confirms a terminal outcome. Do not call it automatically when a network error occurs.

The example keeps state in memory. A production interface needs an appropriate recovery mechanism for reloads and additional tabs.

MDN's Fetch guide explains why applications must check HTTP status explicitly.

4. Make the backend the source of truth

Frontend protection improves usability, but the backend must prevent duplicate execution.

Store an operation record containing:

Authenticated user ID
Operation ID
Payload hash
State
Requested model
Creation and update times
Upstream request identifier, when available
Result or sanitized error

Enforce uniqueness on the combination of user ID and operation ID.

The initial claim must be atomic. Two concurrent requests that both check “no record exists” before inserting can otherwise both call the model.

A database uniqueness constraint or an equivalent atomic mechanism can resolve that race. A process-local dictionary cannot coordinate several workers or survive a restart.

The backend should derive user identity from authentication. Do not trust a user ID supplied in the browser payload.

5. Define replay behavior

When the same operation arrives again, inspect its stored state.

Stored stateResponse to a repeated request
Accepted or runningReturn the existing operation and status
SucceededReturn or reference the stored result
Failed before model dispatchAllow a controlled retry under your policy
Upstream outcome unknownReconcile before another generation
CancelledFollow the documented cancellation outcome

A retry policy needs to distinguish “the model was never called” from “the response was lost after dispatch.”

That distinction becomes especially important after a backend restart. An operation left in running might have completed upstream. Automatically starting it again can create duplicate work.

Use available provider request records or task identifiers for reconciliation. When the upstream service provides no reliable lookup, preserve the uncertainty and make another generation an explicit decision.

Application deduplication reduces duplicates at your boundary. It cannot manufacture exactly-once behavior across an undocumented upstream API.

6. Treat cancellation as a separate operation

A Stop button should communicate what actually stopped.

The browser's AbortController can stop a fetch request or response consumption. That does not, by itself, establish that a remote model stopped computing or that billing was cancelled.

Define whether your backend attempts upstream cancellation, stops forwarding output, or merely records that the user no longer wants the result.

Keep the operation record until its outcome is understood.

Do not immediately erase the operation ID when the user closes a stream. The interface may need that ID to retrieve a result, display an unresolved state, or explain what happened.

7. Keep model access on the server

The application backend should select the permitted DeepSeek route and attach the gateway credential.

The browser should not choose arbitrary upstream URLs or receive the API key.

When using TreeRouter, confirm the exact model identifier and request protocol in the integration documentation. Keep these settings separate from the application operation ID.

An internal operation_id does not automatically become a provider-recognized deduplication key. Only rely on upstream idempotency when the selected endpoint explicitly documents and supports it.

Also inspect SDK retry defaults. A backend that sends one SDK call may still generate multiple network attempts. Retry ownership should be clear across the browser, backend, SDK, and gateway.

8. Test failures before testing volume

Use a mock upstream service first. Count how many times the model-dispatch function is entered.

TestExpected application behavior
Double clickOne operation and one dispatch
Same ID submitted concurrentlyExisting operation reused
Same ID, different textConflict returned
Browser loses connectionExisting operation remains discoverable
Backend restarts after dispatchOutcome reconciled or marked uncertain
User requests a new summaryNew operation ID permitted

These are acceptance criteria, not claimed benchmark results.

After the local tests pass, run one small live request. Compare application records with the available gateway usage record.

Do not begin by sending a large batch. A small duplicate-request bug becomes harder to diagnose when hundreds of operations are mixed together.

Frequently asked questions

Is disabling the submit button enough?

No. It does not protect against multiple tabs, repeated HTTP requests, or several backend workers.

Can I add an Idempotency-Key header to any model API?

You can send a header, but it has no deduplication effect unless the endpoint documents and honors it.

Does a browser timeout mean the model request failed?

No. The client may have lost the response while processing continued elsewhere.

Should every failed request retry automatically?

No. Authentication, invalid payloads, and unknown upstream outcomes need different handling from a confirmed temporary failure.

Verify the runtime connection

Register with TreeRouter, choose a supported DeepSeek route, and create a development key for the application's backend.

Verify one intentional operation, one known dispatch path, and one understandable usage record before expanding traffic.