Guide #10 Use Case — Operations 22 min read March 2026

The AI Desktop Worker: GUI Applications Without APIs

Not everything has an API. Your ERP has a Java GUI. Your accounting software runs on Windows. Your government portal only works in a browser with a specific plugin. Your vendor's "integration" is a human clicking through a desktop application.

Give the AI agent a desktop. A full Linux environment with XFCE, LibreOffice, a file manager, and any application you install. The agent sees the screen, moves the mouse, types on the keyboard, and operates the GUI exactly like a human would. No API required. No RPA scripts. Just vision and clicks.

The API gap

The modern enterprise runs on a patchwork of software. Some of it has APIs. Most of it doesn't. The CRM has a REST API. The ERP has a SOAP endpoint from 2008 that nobody maintains. The government compliance portal has no API at all — just a login page and a series of forms. The insurance claims system is a thick-client Java application that only runs on a desktop.

When you need to move data between these systems, the integration is a person. Someone logs into System A, copies a number, switches to System B, pastes it, fills in three fields, clicks Submit, goes back to System A, marks it as done. Repeat 200 times. Every day.

Traditional RPA (UiPath, Automation Anywhere, Blue Prism) tries to solve this with recorded click sequences. You record a macro, deploy it to a virtual machine, and pray that the UI doesn't change. When it does — and it always does — the macro breaks, the queue stalls, and an RPA engineer spends a day rebuilding the selector chain.

AI agents solve this differently. They don't replay recorded clicks. They see the screen, understand what's on it, and decide what to click. When a button moves from the left side to the right side, the agent finds it in its new location. When a dialog box pops up unexpectedly, the agent reads it and responds appropriately. The agent uses the application the same way a human does: by looking at it.

Traditional RPA

  • Record click sequences with pixel coordinates or selectors
  • Breaks when UI changes — buttons move, dialogs appear
  • Requires RPA engineer to maintain and update scripts
  • $10K–100K/year in platform licensing (UiPath, AA)
  • Months of implementation per workflow
  • No understanding of what's on screen — just replays clicks

AI desktop agent

  • Sees the screen with vision models, decides what to click
  • Adapts to UI changes — finds buttons in new locations
  • Configured with plain English, not click recordings
  • $0.05–0.50 per task in compute + model costs
  • First workflow running in hours, not months
  • Reads dialogs, understands context, handles exceptions
$0.10
Cost per desktop task
0
APIs required
Any
GUI application supported

What a desktop container gives you

A desktop container is a cloud container running a full Linux desktop environment. When you create one via POST /api/desktops, you get:

The desktop container is the same environment a human would RDP or VNC into. The difference: instead of a human sitting at the screen, an AI agent controls it.

bash
# Create a desktop container
export SANDBOX_API_KEY="ab0t_sk_live_YOUR_KEY_HERE"
export SANDBOX_URL="https://sandbox.dev.ab0t.com"

DESKTOP=$(curl -s -X POST "$SANDBOX_URL/api/desktops" \
  -H "Authorization: Bearer $SANDBOX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "desktop_type": "ubuntu-xfce",
    "idle_timeout_minutes": 30,
    "metadata": {"task": "spreadsheet-processing"}
  }')

echo "Container: $(echo $DESKTOP | jq -r '.container_id')"
echo "Status:    $(echo $DESKTOP | jq -r '.status')"
bash
# Poll until assigned, then open the desktop in your browser
CONTAINER_ID=$(echo "$DESKTOP" | jq -r '.container_id')

while true; do
  STATUS=$(curl -s "$SANDBOX_URL/api/containers/$CONTAINER_ID/status" \
    -H "Authorization: Bearer $SANDBOX_API_KEY")
  STATE=$(echo "$STATUS" | jq -r '.state')
  echo "State: $STATE"
  [ "$STATE" = "assigned" ] && break
  sleep 3
done

ACCESS_URL=$(echo "$STATUS" | jq -r '.access_url')
echo "Open in browser: $ACCESS_URL"

Open that access_url in your browser and you'll see a full Linux desktop rendered via noVNC. You can interact with it manually to test, or hand control over to an AI agent.

Available desktop types

TypeBaseDesktopIncluded softwareBest for
alpine-xfce Alpine Linux XFCE LibreOffice, Firefox, file manager Lightweight tasks, fast startup
ubuntu-xfce Ubuntu 22.04 XFCE LibreOffice, Firefox, apt ecosystem Maximum compatibility, custom installs
alpine-kde Alpine Linux KDE Plasma LibreOffice, Dolphin, Konsole Richer GUI, more complex applications
windows Windows Windows Desktop Office, .NET runtime Windows-only applications

How the agent controls the desktop

The AI agent controls the desktop using a screenshot-and-click loop. It takes a screenshot of the current screen, sends it to a vision model (Claude Sonnet 4.6 or Claude Opus 4.6), receives instructions about what to do next, and executes those instructions via VNC or xdotool commands. This is Claude's computer use capability applied to a dedicated container.

Take screenshot Claude vision:
"What should I do next?"
Execute action
(click / type / scroll)
Repeat until task is complete. Each iteration: ~2–5 seconds.

The control loop

python — desktop_agent.py
import anthropic
import base64
import subprocess
import time

client = anthropic.Anthropic()

def screenshot() -> bytes:
    """Capture the current screen via xdotool/scrot."""
    subprocess.run(["scrot", "/tmp/screen.png", "-o"], check=True)
    with open("/tmp/screen.png", "rb") as f:
        return f.read()


def click(x: int, y: int):
    subprocess.run(["xdotool", "mousemove", str(x), str(y), "click", "1"])


def double_click(x: int, y: int):
    subprocess.run(["xdotool", "mousemove", str(x), str(y),
                    "click", "--repeat", "2", "--delay", "100", "1"])


def type_text(text: str):
    subprocess.run(["xdotool", "type", "--clearmodifiers", "--delay", "30", text])


def key_press(keys: str):
    """Press key combo like 'ctrl+s' or 'Return'."""
    subprocess.run(["xdotool", "key", "--clearmodifiers", keys])


def run_desktop_task(task_description: str, max_steps=50):
    """Run a task on the desktop using vision-guided interaction."""
    history = []

    for step in range(max_steps):
        # 1. Screenshot
        img = screenshot()
        b64 = base64.b64encode(img).decode()

        # 2. Ask Claude what to do
        messages = [{
            "role": "user",
            "content": [
                {"type": "text", "text": f"""You are controlling a Linux desktop to complete this task:

{task_description}

Previous actions taken: {json.dumps(history[-5:])}

Look at the screenshot and decide the next action.
Reply with exactly ONE line in one of these formats:
  CLICK x y
  DOUBLE_CLICK x y
  TYPE text to type
  KEY combo (e.g., KEY ctrl+s, KEY Return, KEY alt+F4)
  SCROLL up/down
  WAIT seconds
  DONE
  FAIL reason"""},
                {"type": "image", "source": {
                    "type": "base64", "media_type": "image/png", "data": b64}},
            ],
        }]

        response = client.messages.create(
            model="claude-sonnet-4-6-20250514",
            max_tokens=256,
            messages=messages,
        )
        action = response.content[0].text.strip()
        print(f"Step {step+1}: {action}")
        history.append(action)

        # 3. Execute
        if action.startswith("CLICK"):
            _, x, y = action.split()
            click(int(x), int(y))
        elif action.startswith("DOUBLE_CLICK"):
            _, x, y = action.split()
            double_click(int(x), int(y))
        elif action.startswith("TYPE"):
            type_text(action[5:])
        elif action.startswith("KEY"):
            key_press(action[4:])
        elif action.startswith("SCROLL"):
            direction = "5" if "down" in action else "4"
            subprocess.run(["xdotool", "click", direction])
        elif action.startswith("WAIT"):
            time.sleep(int(action.split()[1]))
        elif action == "DONE":
            print("Task complete.")
            return True
        elif action.startswith("FAIL"):
            print(f"Task failed: {action}")
            return False

        time.sleep(1)  # Let the UI update

    print("Max steps reached.")
    return False
This runs inside the desktop container

The control script runs directly on the desktop container itself (via terminal emulator or SSH). It uses scrot for screenshots and xdotool for mouse/keyboard input — both are pre-installed. The agent script has direct access to the X display, so there's no network latency between the screenshot and the click.

Five use cases where desktop containers shine

1. Spreadsheet processing with LibreOffice

Your finance team receives a monthly spreadsheet from a partner. It needs to be reformatted: columns reordered, formulas updated, a pivot table created, the result exported as a PDF. There's no API for this — it's a spreadsheet manipulation task.

python
# Task: Process a financial spreadsheet in LibreOffice Calc
run_desktop_task("""
1. Open the file /workspace/monthly_report.xlsx in LibreOffice Calc
2. Delete columns E through G (they contain internal notes)
3. Sort the remaining data by column C (Amount) in descending order
4. Add a SUM formula in the last row of column C
5. Create a pivot table summarizing amounts by category (column A)
6. Export the result as a PDF to /workspace/report_final.pdf
7. Save and close
""")

The agent opens LibreOffice Calc, navigates the menus, selects columns, applies sorting, types formulas, creates the pivot table through the UI, and exports to PDF. Every step is guided by what it sees on screen. If LibreOffice shows a dialog ("Do you want to keep the current format?"), the agent reads it and clicks the appropriate button.

2. ERP data entry

Your ERP system (SAP, Oracle, NetSuite) has a thick-client interface or a complex web portal. Creating purchase orders, entering journal entries, or processing invoices requires navigating through multiple screens, filling forms, and clicking confirmation dialogs.

python
# Task: Create a purchase order in the ERP
run_desktop_task("""
1. Open Firefox and navigate to https://erp.internal.company.com
2. Log in with username 'ap_agent' and password from $ERP_PASSWORD
3. Click 'Procurement' in the left sidebar
4. Click 'Create Purchase Order'
5. Fill in:
   - Vendor: "Staples Business Advantage" (select from dropdown)
   - Delivery date: last day of next month
   - Line item 1: "Office Paper A4", Qty: 50, Unit price: 4.99
   - Line item 2: "Ink Cartridge HP 61", Qty: 10, Unit price: 24.99
6. Click 'Calculate Total'
7. Verify the total matches $499.40
8. Click 'Submit for Approval'
9. Note the PO number shown in the confirmation dialog
""")

3. Government portal form submission

Government portals are notoriously unfriendly to automation. They use custom form controls, session timeouts, CAPTCHAs, PDF uploads, and multi-step wizards with back-button-breaking JavaScript. The agent handles all of this because it interacts with the portal exactly as a human would.

python
# Task: File a quarterly compliance report
run_desktop_task("""
1. Open Firefox and go to https://portal.state.gov/compliance
2. Log in with the credentials in /workspace/credentials.txt
3. Click 'Quarterly Reports' > 'File New Report'
4. Select reporting period: Q1 2026
5. Upload the file /workspace/q1_compliance_data.pdf
6. Fill in the summary fields:
   - Total revenue: $2,450,000
   - Employees: 47
   - Incidents: 0
7. Check the certification checkbox
8. Click 'Submit Report'
9. Download the confirmation receipt PDF to /workspace/receipt.pdf
""")

4. Legacy Java or .NET applications

Some critical business software only runs as a desktop application. Insurance claims processors, medical records systems, and warehouse management tools often have no web version and no API. They're Java Swing apps, .NET WinForms, or even older technology.

Install the application on the desktop container and let the agent operate it. For Java apps, install the JRE. For .NET apps, use a Windows desktop type or Wine on Linux.

python
# Task: Process insurance claims in a Java application
run_desktop_task("""
1. The claims processing application is already running on the desktop
2. In the 'Pending Claims' list, select the first claim
3. Read the claim details: claimant name, amount, date, type
4. Cross-reference the claim against the policy data in the right panel
5. If the claim amount is under $5,000 and the policy is active:
   - Click 'Approve'
   - Enter approval code: AUTO-{date}
6. If the claim needs review:
   - Click 'Flag for Review'
   - Enter note: 'Amount exceeds auto-approval threshold'
7. Click 'Next Claim' and repeat for all pending claims
8. When no more pending claims, take a screenshot for the audit log
""")

5. Document conversion and processing

Convert documents between formats, merge PDFs, create presentations from data, or fill in PDF forms. LibreOffice handles all common office formats, and the agent operates it through the GUI.

python
# Task: Create a presentation from data
run_desktop_task("""
1. Open LibreOffice Impress (Presentation)
2. Create a new presentation with the 'Business' template
3. Slide 1: Title 'Q1 2026 Results', subtitle 'Sales Division'
4. Slide 2: Insert a table with these quarterly numbers:
   - North: $1.2M (+12%)
   - South: $890K (+5%)
   - East: $2.1M (+18%)
   - West: $1.5M (-3%)
5. Slide 3: Insert a bar chart visualizing the data from Slide 2
6. Slide 4: Title 'Key Takeaways', bullet points:
   - East region leading growth at 18%
   - West region needs attention, -3% decline
   - Total Q1 revenue: $5.69M (+10% YoY)
7. Save as /workspace/q1_presentation.pptx
8. Also export as PDF to /workspace/q1_presentation.pdf
""")

Orchestrating desktop tasks from a terminal sandbox

In production, the desktop container is just one part of a larger workflow. A terminal sandbox orchestrates the entire pipeline: fetch data from an API, create a desktop container to process it in a GUI application, collect the results, and push them downstream.

python — orchestrator.py (runs in terminal sandbox)
import asyncio, httpx, json, os

SANDBOX_URL = os.environ["SANDBOX_URL"]
API_KEY = os.environ["SANDBOX_API_KEY"]
HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}


async def process_spreadsheet(input_file: str, task: str) -> str:
    """
    Create a desktop container, upload a file, run a GUI task,
    and download the result.
    """
    async with httpx.AsyncClient(timeout=300) as client:
        # 1. Create desktop
        desktop = (await client.post(
            f"{SANDBOX_URL}/api/desktops", headers=HEADERS,
            json={"desktop_type": "ubuntu-xfce", "idle_timeout_minutes": 15},
        )).json()
        cid = desktop["container_id"]

        # 2. Wait for ready
        for _ in range(40):
            status = (await client.get(
                f"{SANDBOX_URL}/api/containers/{cid}/status",
                headers=HEADERS)).json()
            if status["state"] == "assigned": break
            await asyncio.sleep(3)

        # 3. Upload the input file to the desktop
        #    (via shared volume or HTTP file transfer)

        # 4. Run the desktop agent script
        #    (SSH into the desktop or use the VNC-based agent)

        # 5. Download results

        # 6. Release desktop back to pool
        await client.post(
            f"{SANDBOX_URL}/api/containers/{cid}/release",
            headers=HEADERS)

    return "result.pdf"

The complete workstation: browser + desktop + terminal

The most powerful pattern combines all three container types in a single workflow. This is what makes the platform different from every other AI infrastructure provider: the agent gets the same workstation a human employee would get.

Browser + Desktop + Terminal The complete AI workstation. Same tools a human uses. Every interface covered.

Example: end-of-month reconciliation

Every month, the finance team reconciles vendor invoices against internal records. The data lives in three places: the vendor portal (web), the accounting spreadsheet (desktop), and the internal API (terminal). Here's how the three containers work together:

  1. Terminal sandbox orchestrates the workflow, queries the internal API for purchase order data, saves it as JSON.
  2. Browser containers log into 10 vendor portals in parallel, download this month's invoices, save them to shared storage.
  3. Desktop container opens the accounting spreadsheet in LibreOffice, enters the new invoice data, runs the reconciliation macro, generates the variance report, exports to PDF.
  4. Terminal sandbox collects the PDF, emails it to the CFO, posts a summary to Slack, archives everything to S3.

No human touched any of these systems. The agent navigated web portals, operated a desktop application, and ran code — using the same interfaces a human would use.

Watching the agent work

Desktop containers have a unique advantage: you can watch the agent in real time. The access_url opens a noVNC session in your browser. You see exactly what the agent sees. The mouse moves, windows open, text gets typed. It's like watching a screen recording of an employee working — except it's happening live.

This is critical for three reasons:

Record the session for audit

For compliance-sensitive tasks (ERP entries, government filings, financial processing), record the VNC session. Tools like ffmpeg can capture the X display directly on the container: ffmpeg -f x11grab -i :0 -t 600 /workspace/recording.mp4. This gives you a complete video audit trail of exactly what the agent did.

Desktop agents vs traditional RPA

If your company already has a UiPath or Automation Anywhere deployment, you might wonder whether AI desktop agents replace it. The short answer: they solve the same problem differently, and the AI approach is better for most new automation.

DimensionTraditional RPAAI desktop agent
How it works Replays recorded click sequences (selectors, coordinates) Sees the screen, reasons, decides next action
Setup time Weeks to months per workflow Hours. Write a task description in English.
UI change resilience Breaks when selectors/layout changes. Manual repair. Adapts automatically. Finds buttons in new locations.
Exception handling Pre-programmed exception paths. Unhandled = crash. Reads unexpected dialogs. Reasons about context.
Cost $10K–100K/year platform + RPA engineer salary $0.05–0.50/task. No platform fee.
Infrastructure Dedicated VMs or RPA cloud Ephemeral containers. Spin up, use, release.
Maintenance Constant. UI changes break bots weekly. Minimal. Vision model handles routine UI shifts.
Speed Fast (replays at machine speed) Moderate (2–5s per visual reasoning step)
Determinism 100% deterministic (same clicks every time) ~98% consistent (vision model is probabilistic)

When to use traditional RPA: High-volume, time-critical tasks on stable UIs where you need sub-second execution and 100% determinism. Example: processing 10,000 identical transactions per hour on an internal system that never changes.

When to use AI desktop agents: Everything else. Varied portals, changing UIs, exception handling, tasks that require judgment, tasks you need running this week not this quarter. For most enterprise desktop automation, the AI approach wins on setup time, maintenance cost, and flexibility.

What it costs

ItemDurationUnit costTotal
Desktop container (ubuntu-xfce) ~10 min per task ~$0.05/hour $0.008
Claude Sonnet (vision steps) ~15 screenshots per task ~$0.005/screenshot $0.075
Terminal sandbox (orchestrator) ~5 min $0.01/hour $0.001
Total per task ~$0.08
With overhead ~$0.10

For a task that takes a human 15 minutes at $40/hour fully loaded, that's $10 of human time replaced by $0.10 of agent time. A 100× cost reduction. Run 50 desktop tasks per week and you save $25,000/year.

Vision steps dominate the cost

The desktop container itself costs almost nothing (~$0.008 for 10 minutes). The Claude API calls for visual reasoning are the main expense. Each screenshot-and-reason cycle costs ~$0.005. A task that requires 30 steps costs $0.15. Optimize by giving clear task descriptions that minimize the number of reasoning steps needed.

Production tips

Give precise task descriptions

The agent performs better when you tell it exactly what to click, not just the outcome you want. "Click the 'File' menu, then 'Export as PDF'" is better than "save it as a PDF." Precise descriptions mean fewer reasoning steps, which means faster execution and lower model costs.

Use alpine-xfce for speed, ubuntu-xfce for compatibility

Alpine-based desktops start faster and use less memory. Use them for LibreOffice tasks and simple GUI work. Switch to Ubuntu if you need to install software that requires apt-get (Java runtimes, custom .deb packages, proprietary tools).

Pre-install software in custom images

If every desktop task needs the same software (a specific Java app, a particular browser plugin), build a custom Docker image with it pre-installed. This eliminates the installation step from every task and ensures consistency.

Set resolution explicitly

Vision models work best at consistent resolutions. Set the VNC resolution to 1280×720 or 1920×1080 and don't change it between tasks. This makes the coordinates consistent and the screenshots clearer for the model.

Add delays after clicks

GUI applications take time to respond. After clicking a menu item, wait 1–2 seconds for the dropdown to appear. After clicking "Save," wait for the file dialog. The control loop should include a sleep between the action and the next screenshot to let the UI settle.

Screenshot on every failure

When the agent reports FAIL, the last screenshot shows exactly what went wrong. Save it to the workspace for debugging. This is the equivalent of a stack trace for visual automation.

Use release, not delete

Desktop containers support warm pools. After a task completes, call POST /api/containers/{id}/release to return the container to the pool. The next desktop task claims it instantly without a cold start.

Troubleshooting

Agent can't find a button that's clearly visible

The screenshot resolution might be too low for the vision model to read small text. Increase the VNC resolution or zoom in the application. Also try Claude Opus 4.6 instead of Sonnet for tasks that require reading small or low-contrast text.

Agent clicks the wrong location

Coordinate accuracy depends on the screenshot matching the actual screen state. If there's a lag between the screenshot and the click (because the UI was still animating), the agent clicks the wrong spot. Increase the wait time after screenshots. Also verify that the VNC resolution matches the screenshot resolution.

LibreOffice dialog box blocks the workflow

LibreOffice shows "Recovery" dialogs on startup if a previous session crashed. Add a pre-task step: "If you see a recovery dialog, click 'Discard' to dismiss it." Or configure LibreOffice to skip recovery prompts by editing its config files in the custom image.

Desktop container is slow to start

Desktop containers are heavier than browser containers (~2–3 GB image). First start takes 45–90 seconds in the cloud. Use warm pools to eliminate this: pre-provision 2–3 desktop containers so they're ready when you need them.

Agent runs out of steps before completing the task

The default max_steps=50 should handle most tasks. If a task genuinely requires more steps, increase the limit. But first check: does the task description have unnecessary ambiguity that's causing the agent to wander? A clearer description almost always reduces step count.


What's next

Give your agent a desktop

Any application. Any GUI. No API required. The agent sees the screen, clicks the buttons, and gets the work done.

Get Started Free