# How to Pause and Resume GUIAgent Execution in UI-TARS Desktop

> Effortlessly pause and resume GUIAgent execution in UI-TARS Desktop using simple guiAgent.pause() and guiAgent.resume() commands. Control your test flow with ease.

- Repository: [Bytedance Inc./UI-TARS-desktop](https://github.com/bytedance/UI-TARS-desktop)
- Tags: how-to-guide
- Published: 2026-05-10

---

**You can pause and resume GUIAgent execution in UI-TARS Desktop by invoking `guiAgent.pause()` and `guiAgent.resume()`, which manipulate an internal `isPaused` flag and a `resumePromise` that blocks the main run loop until explicitly resolved.**

UI-TARS Desktop provides a robust **GUIAgent** that automates GUI interactions by capturing screenshots, invoking LLMs, and executing actions. When you need to temporarily halt automation without terminating the session entirely, the SDK offers built-in pause and resume functionality through the `GUIAgent` class in the `@ui-tars/sdk` package.

## How Pause and Resume Works in GUIAgent

The `GUIAgent` class extends `BaseGUIAgent` and implements a cooperative pausing mechanism within its main execution loop. According to the source code in [`packages/ui-tars/sdk/src/GUIAgent.ts`](https://github.com/bytedance/UI-TARS-desktop/blob/main/packages/ui-tars/sdk/src/GUIAgent.ts), the agent checks the `isPaused` flag on every iteration of the `run()` loop.

When `isPaused` is `true`, the agent emits a `StatusEnum.PAUSE` event and awaits a promise stored in `resumePromise`. This blocks further execution while maintaining the session state. Once `resume()` resolves this promise, the loop continues from where it left off.

## Implementation Details

### The Pause State Flag

The `isPaused` boolean property indicates whether the agent should halt its loop. In [`packages/ui-tars/sdk/src/GUIAgent.ts`](https://github.com/bytedance/UI-TARS-desktop/blob/main/packages/ui-tars/sdk/src/GUIAgent.ts) (lines 95-101), the `pause()` method sets this flag to `true` and initializes a new `Promise` assigned to `resumePromise`:

```typescript
pause() {
  this.isPaused = true;
  this.resumePromise = new Promise<void>((resolve) => {
    this.resolveResume = resolve;
  });
}

```

### The Resume Promise Mechanism

The `resume()` method resolves the pending promise and clears the pause state:

```typescript
resume() {
  this.resolveResume?.();
  this.isPaused = false;
}

```

When the main loop encounters the paused state, it awaits this promise indefinitely:

```typescript
if (this.isPaused && this.resumePromise) {
  data.status = StatusEnum.PAUSE;
  await onData?.({ data });
  await this.resumePromise;           // Blocks until resume() is called
  data.status = StatusEnum.RUNNING;
  await onData?.({ data });
}

```

### Distinguishing Pause from Stop

UI-TARS Desktop distinguishes between temporary pauses and hard stops. The `isStopped` flag, set by `GUIAgent.stop()` (lines 111-113 in [`GUIAgent.ts`](https://github.com/bytedance/UI-TARS-desktop/blob/main/GUIAgent.ts)), terminates the loop entirely rather than suspending it. Unlike `pause()`, `stop()` cannot be reversed without restarting the agent.

## IPC Routes for UI Integration

The desktop application exposes pause and resume functionality through Electron IPC routes defined in [`apps/ui-tars/src/main/ipcRoutes/agent.ts`](https://github.com/bytedance/UI-TARS-desktop/blob/main/apps/ui-tars/src/main/ipcRoutes/agent.ts). These routes allow the renderer process (UI) to control the main process agent instance via `GUIAgentManager`.

**Pause execution:**

```typescript
pauseRun: t.procedure.input<void>().handle(async () => {
  const guiAgent = GUIAgentManager.getInstance().getAgent();
  if (guiAgent instanceof GUIAgent) {
    guiAgent.pause();                     // Triggers internal pause
    store.setState({ thinking: false });
  }
}),

```

**Resume execution:**

```typescript
resumeRun: t.procedure.input<void>().handle(async () => {
  const guiAgent = GUIAgentManager.getInstance().getAgent();
  if (guiAgent instanceof GUIAgent) {
    guiAgent.resume();                    // Unblocks the loop
    store.setState({ thinking: false });
  }
}),

```

## Code Examples

### Programmatic Control

To pause and resume the agent from a custom extension or script:

```typescript
import { GUIAgentManager, GUIAgent } from '@ui-tars/sdk';
import { Operator } from '@ui-tars/sdk/core';

// Assuming agent was previously created and registered
const agent = new GUIAgent<Operator>(config);
GUIAgentManager.getInstance().setAgent(agent);

// Temporarily halt execution
agent.pause();

// ... perform intermediate tasks ...

// Continue automation
agent.resume();

```

### React Component Integration

Bind IPC calls to UI buttons in your React components:

```tsx
import { useIpc } from '@ui-tars/electron-ipc/react';

const Toolbar = () => {
  const ipc = useIpc();

  return (
    <div>
      <button onClick={() => ipc.invoke('pauseRun')}>Pause</button>
      <button onClick={() => ipc.invoke('resumeRun')}>Resume</button>
    </div>
  );
};

```

### Monitoring Agent Status

Check the current execution state using the shared status enum:

```tsx
import { useSelector } from 'react-redux';
import { StatusEnum } from '@ui-tars/shared/types';

const StatusBanner = () => {
  const status = useSelector(state => state.status);
  return <div>{status === StatusEnum.PAUSE ? 'Paused' : 'Running'}</div>;
};

```

## Summary

- The **GUIAgent** class in `@ui-tars/sdk` provides native **pause and resume** capabilities through the `pause()` and `resume()` methods.
- The implementation relies on an **`isPaused` flag** and a **`resumePromise`** that blocks the main `run()` loop until resolved.
- **IPC routes** in [`apps/ui-tars/src/main/ipcRoutes/agent.ts`](https://github.com/bytedance/UI-TARS-desktop/blob/main/apps/ui-tars/src/main/ipcRoutes/agent.ts) expose these controls to the Electron frontend via `pauseRun` and `resumeRun` commands.
- **StatusEnum.PAUSE** allows UI components to reflect the current execution state.
- Unlike **`stop()`**, pausing preserves the session state and allows continuation without restarting the agent.

## Frequently Asked Questions

### What happens to the LLM call when I pause GUIAgent?

The pause mechanism operates at the loop level in [`packages/ui-tars/sdk/src/GUIAgent.ts`](https://github.com/bytedance/UI-TARS-desktop/blob/main/packages/ui-tars/sdk/src/GUIAgent.ts). If an LLM request is already in flight when `pause()` is called, that request completes, but the agent pauses before processing the next screenshot and action cycle. The `resumePromise` blocks at the start of the next iteration.

### How do I check if the agent is currently paused?

Monitor the `StatusEnum` value emitted through the `onData` callback or the global store. When paused, the agent sets `data.status = StatusEnum.PAUSE` (defined in [`packages/ui-tars/shared/src/types/agent.ts`](https://github.com/bytedance/UI-TARS-desktop/blob/main/packages/ui-tars/shared/src/types/agent.ts)). You can also check `agent.isPaused` directly on the GUIAgent instance if you have reference to it.

### Can I pause the agent from a custom extension without using the UI?

Yes. Obtain the active agent instance via `GUIAgentManager.getInstance().getAgent()`, verify it is an instance of `GUIAgent`, and call `agent.pause()`. This works from any Node.js context in the main process where the SDK is available.

### What is the difference between pause() and stop()?

`pause()` temporarily suspends the execution loop using a promise-based waiter, allowing you to resume later with `resume()`. `stop()` sets the `isStopped` flag (lines 111-113 in [`GUIAgent.ts`](https://github.com/bytedance/UI-TARS-desktop/blob/main/GUIAgent.ts)) and breaks the loop entirely, requiring you to instantiate and start a new GUIAgent to resume automation.