UI-TARS SDK Retry Mechanism: How to Configure Retries for Screenshots, Models, and Actions
The UI-TARS SDK implements a configurable retry mechanism using the async-retry library (v1.3.3) for screenshot capture, model inference, and action execution, defaulting to zero retries but allowing granular per-operation configuration via the RetryConfig interface.
The retry system in the bytedance/UI-TARS-desktop repository provides resilience for the three critical operations within the GUIAgent class. By default, the SDK performs no retries, but you can enable automatic re-attempts with custom callbacks and timeouts for specific failure scenarios.
How the UI-TARS SDK Retry Mechanism Works
The retry logic is centralized in the GUIAgent.run method within packages/ui-tars/sdk/src/GUIAgent.ts. The SDK wraps three distinct operations with the async-retry utility to handle transient failures in GUI automation workflows.
Retry Operations and Default Behavior
The SDK applies retry logic to three specific phases of the agent execution cycle:
| Operation | Location in SDK | Default Max Retries | Min Timeout |
|---|---|---|---|
| Screenshot | GUIAgent.run lines 85-89 |
0 | 5000ms |
| Model invocation | GUIAgent.run lines 96-100 |
0 | 30000ms |
| Action execution | GUIAgent.run lines 122-126 |
0 | 5000ms |
Each operation defaults to maxRetries: 0, meaning the SDK attempts each operation exactly once unless explicitly configured otherwise.
Underlying Implementation with async-retry
The mechanism relies on the async-retry npm package declared in packages/ui-tars/sdk/package.json. Inside GUIAgent.run, each operation calls asyncRetry with operation-specific parameters:
// Screenshot retry logic (GUIAgent.ts lines 85-89)
await asyncRetry(() => operator.screenshot(), {
retries: retry?.screenshot?.maxRetries ?? 0,
minTimeout: 5000,
onRetry: retry?.screenshot?.onRetry,
});
// Model invocation retry logic (GUIAgent.ts lines 96-100)
await asyncRetry(async (bail) => { /* model call */ }, {
retries: retry?.model?.maxRetries ?? 0,
minTimeout: 30_000,
onRetry: retry?.model?.onRetry,
});
// Action execution retry logic (GUIAgent.ts lines 122-126)
await asyncRetry(() => operator.execute({ /* action */ }), {
retries: retry?.execute?.maxRetries ?? 0,
minTimeout: 5000,
onRetry: retry?.execute?.onRetry,
});
The bail function available in the model invocation wrapper allows immediate termination of retries for non-recoverable errors.
Configuration Architecture
The retry system uses a strongly-typed configuration structure defined in packages/ui-tars/sdk/src/types.ts.
RetryConfig Interface
The SDK exposes a RetryConfig interface at lines 81-84:
interface RetryConfig {
maxRetries?: number;
onRetry?: (error: Error, attempt: number) => void | Promise<void>;
}
maxRetries: Specifies the number of additional attempts beyond the initial call (e.g.,maxRetries: 2allows 3 total attempts).onRetry: Optional callback invoked after each failed attempt, receiving the error and attempt number (1-indexed).
GUIAgentConfig Integration
The top-level configuration accepts an optional retry field containing separate configs for each operation (lines 96-103):
interface GUIAgentConfig {
// ... other config options
retry?: {
model?: RetryConfig;
screenshot?: RetryConfig;
execute?: RetryConfig;
};
}
This structure allows independent retry strategies for each phase of the automation loop.
Configuring Retries in Practice
When instantiating GUIAgent, pass the retry configuration object to enable resilience for specific operations.
Basic Configuration: Screenshot Retries
Enable retries only for screenshot operations when dealing with unstable screen capture:
import { GUIAgent } from '@ui-tars/sdk';
const agent = new GUIAgent({
operator: new MyOperator(),
model: new MyModel(),
retry: {
screenshot: {
maxRetries: 2,
onRetry: (err, attempt) => {
console.warn(`Screenshot failed, retry #${attempt}: ${err.message}`);
},
},
// model and execute remain at default (no retries)
},
});
await agent.run('Open the settings page');
This configuration attempts screenshots up to 3 times total (initial + 2 retries) with a 5000ms minimum timeout between attempts.
Comprehensive Configuration: All Operations
Configure different retry limits for each phase of the agent loop:
const agent = new GUIAgent({
operator: new MyOperator(),
model: new MyModel(),
retry: {
screenshot: {
maxRetries: 1 // 2 attempts total
},
model: {
maxRetries: 3, // 4 attempts total for LLM calls
onRetry: (e, i) => console.info(`Model retry ${i}`, e),
},
execute: {
maxRetries: 2, // 3 attempts total for action execution
onRetry: (err) => console.error('Action failed:', err)
},
},
});
The model invocation uses a 30-second timeout suitable for API latency, while screenshot and execution use 5-second timeouts.
Advanced: Custom onRetry Hooks with Exponential Backoff
Implement custom backoff strategies by returning a Promise from onRetry:
function exponentialBackoff(error: Error, attempt: number) {
const delay = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s...
console.warn(`Waiting ${delay}ms before retry #${attempt}: ${error.message}`);
return new Promise((resolve) => setTimeout(resolve, delay));
}
const agent = new GUIAgent({
operator: new MyOperator(),
model: new MyModel(),
retry: {
model: {
maxRetries: 3,
onRetry: exponentialBackoff,
},
},
});
Because async-retry respects the resolution timing of the onRetry callback, this custom delay logic properly throttles retry attempts.
Error Handling and Timeouts
When the retry limit exhausts, async-retry throws the final error, which the SDK catches and converts to a GUIAgentError via the guiAgentErrorParser utility. The error propagates through the agent's onError callback if configured.
Key timeout characteristics:
- Screenshot retries: 5000ms minimum between attempts
- Model retries: 30000ms minimum between attempts (accommodating LLM API latency)
- Action retries: 5000ms minimum between attempts
If omitted from the configuration, any operation defaults to immediate failure propagation without retry attempts.
Summary
- The UI-TARS SDK retry mechanism uses
async-retryto handle transient failures in screenshot, model, and execution operations. - Default behavior is zero retries (
maxRetries: 0), requiring explicit opt-in for resilience. - Configure retries via the
RetryConfiginterface inGUIAgentConfig, supporting distinct strategies per operation type. - Implement custom logic using the
onRetrycallback, which receives the error and attempt count and supports asynchronous delays. - Source implementation resides in
packages/ui-tars/sdk/src/GUIAgent.tswith type definitions inpackages/ui-tars/sdk/src/types.ts.
Frequently Asked Questions
What is the default retry behavior in the UI-TARS SDK?
By default, the SDK performs no retries. The maxRetries parameter defaults to 0 for screenshot, model invocation, and action execution operations, meaning each operation executes exactly once and fails immediately on error. This conservative default prevents unnecessary latency in production environments.
How do I configure different retry limits for screenshots versus model calls?
Pass separate RetryConfig objects within the retry field of GUIAgentConfig. The configuration supports distinct maxRetries values for screenshot, model, and execute properties. For example, set retry.screenshot.maxRetries: 2 for image capture resilience while keeping retry.model.maxRetries: 0 for strict single-shot LLM inference.
Can I implement exponential backoff with the UI-TARS SDK retry mechanism?
Yes. The onRetry callback in RetryConfig supports async functions. Return a Promise that resolves after your desired delay to implement exponential backoff, jitter, or other custom timing strategies. The underlying async-retry library waits for the onRetry Promise to resolve before attempting the next retry.
What happens when all retry attempts are exhausted?
When retry limits exhaust, the SDK throws the final error through the guiAgentErrorParser and propagates it via the onError callback of the GUIAgent. If unhandled, this terminates the current agent.run() execution. The error object contains the original failure details from the last attempt, allowing diagnostic logging or fallback logic in your application code.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →