Agent Playbook: Autonomous Real-World Purchases via ADB + Bazos.cz

Date: 2026-02-19 Bead: beads-hub-sl1 GitHub Issue: #31 Status: Proven in production (DDR4 RAM purchase, 2026-02-19)


1. Overview

This playbook documents how an AI agent can autonomously complete a real-world purchase on Bazos.cz (Czech classifieds platform) using:

  • Browser automation for web interactions (phone reveal, verification)
  • ADB (Android Debug Bridge) for SMS read/write on a paired Android device
  • Agent reasoning for negotiation, logistics lookup, and payment generation

End-to-end flow time: ~40 minutes (including seller response wait times)


2. Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   AI Agent                       β”‚
β”‚  (OpenClaw / Claude / any LLM orchestrator)     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Browser    β”‚  ADB Bridge   β”‚  Web Fetch        β”‚
β”‚  Control    β”‚  (USB/TCP)    β”‚  (HTTP client)    β”‚
β”‚             β”‚               β”‚                   β”‚
β”‚  bazos.cz   β”‚  Samsung SMS  β”‚  zasilkovna.cz    β”‚
β”‚  subdomain  β”‚  app via UI   β”‚  pickup points    β”‚
β”‚  navigation β”‚  automation   β”‚  bank QR gen      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚              β”‚               β”‚
   Phone reveal   Read/Send SMS   Logistics &
   Verification   Negotiation     Payment

Components

Component Role Interface
Browser Navigate Bazos listings, trigger phone reveal, enter verification codes JS evaluation via browser control
ADB Read incoming SMS, compose and send outgoing SMS adb shell commands (uiautomator, input, am)
Web Fetch Look up shipping/pickup info (ZΓ‘silkovna), generate payment QR HTTP GET + parse
Agent LLM Orchestrate flow, negotiate with seller, make decisions Prompt-based reasoning
Human Approve payment (final confirmation gate) QR code presented for manual bank transfer

3. Complete Purchase Flow

Phase 1: Get Seller Phone Number

  1. Navigate to listing on correct subdomain (e.g., pc.bazos.cz)
  2. Trigger phone reveal: document.querySelector('.teldetail').click()
  3. Enter agent phone number in overlay and submit
  4. Read verification SMS via ADB UI dump (see Β§4)
  5. Enter verification code in overlay β†’ receive seller phone number

Phase 2: Initial Contact (SMS)

  1. Compose SMS via ADB to seller number
  2. Send inquiry β€” express interest, ask about shipping/availability
  3. Monitor for seller reply via ADB UI dumps

Phase 3: Negotiation

  1. Read seller reply β€” parse shipping terms, price confirmation
  2. Send follow-up β€” confirm price, request bank details and shipping info
  3. Handle seller questions β€” provide name, email, pickup point as needed

Phase 4: Logistics

  1. Look up pickup point (e.g., ZΓ‘silkovna) via web fetch
  2. Send logistics details to seller via SMS

Phase 5: Payment

  1. Receive bank account from seller (Czech format: XXXXXXXXXX/BBBB)
  2. Convert to IBAN and generate SPD payment QR code
  3. Present QR to human for approval and payment ← HUMAN GATE
  4. Send payment confirmation SMS to seller after human confirms

4. ADB Interaction Patterns

4.1 Reading SMS (UI Dump Method)

Samsung devices block content://sms queries and SQLite access without root. The reliable method is UI automation:

# Dump current UI state
adb -s $DEVICE shell uiautomator dump /sdcard/ui.xml
adb -s $DEVICE pull /sdcard/ui.xml /tmp/ui.xml

# Extract all visible text
grep -o 'text="[^"]*"' /tmp/ui.xml | grep -v 'text=""'

To navigate to a specific SMS thread:

  1. Open Messages app: adb -s $DEVICE shell am start -n com.samsung.android.messaging/.ui.ConversationListActivity
  2. Dump UI to find the target thread row
  3. Calculate tap coordinates from bounds attribute (center of bounding box)
  4. Tap: adb -s $DEVICE shell input tap X Y

4.2 Sending SMS

# ALWAYS force-stop first to get clean compose window
adb -s $DEVICE shell am force-stop com.samsung.android.messaging
sleep 1

# Open fresh compose to target number
adb -s $DEVICE shell 'am start -a android.intent.action.SENDTO -d "smsto:+420XXXXXXXXX"'
sleep 2

# Type word-by-word (spaces are eaten by `input text`)
for word in "Hello," "I" "am" "interested."; do
  adb -s $DEVICE shell input text "$word"
  adb -s $DEVICE shell input keyevent KEYCODE_SPACE
done

# Dismiss keyboard BEFORE tapping Send
adb -s $DEVICE shell input keyevent KEYCODE_BACK
sleep 1

# Find Send button via UI dump, tap its bounds center
adb -s $DEVICE shell uiautomator dump /sdcard/ui.xml
# Parse for content-desc="Send", extract bounds, tap center
adb -s $DEVICE shell input tap $SEND_X $SEND_Y

4.3 Verifying Send Success

adb -s $DEVICE shell uiautomator dump /sdcard/ui.xml
# Check compose field β€” empty means sent
grep 'editor_body' /tmp/ui.xml | grep -o 'text="[^"]*"'
# text="" β†’ success | text="..." β†’ still in compose, retry

4.4 Coordinate Systems β€” Critical

  • UI dump bounds = touch coordinate space ← USE THESE
  • Screenshot pixels β‰  touch coordinates on Samsung
  • Check touch space: adb shell wm size (e.g., 1080x1920)
  • Never derive tap coordinates from screenshot pixel positions

5. Bazos.cz Platform Specifics

Subdomain Scoping

  • Verification is per-subdomain β€” verifying on www.bazos.cz does NOT work for pc.bazos.cz
  • Always verify on the same subdomain as the listing
  • Codes expire quickly β€” complete the flow without navigating away

Phone Reveal DOM Selectors

// Trigger overlay
document.querySelector('.teldetail').click()

// Enter phone/code
document.querySelector('#overlaytel input[type=text]').value = 'VALUE'
document.querySelector('#overlaytel button').click()

// Read result
document.querySelector('#overlaytel').innerText

6. Czech Payment QR Generation

Czech banks use the SPD (Short Payment Descriptor) format.

Account Number β†’ IBAN Conversion

def czech_account_to_iban(account: str, bank_code: str, prefix: str = '000000') -> str:
    padded = prefix.zfill(6) + account.zfill(10)
    bban = bank_code + padded
    rearranged = bban + '1235' + '00'  # CZ = 12,35
    check = 98 - (int(rearranged) % 97)
    return f'CZ{check:02d}{bban}'

SPD QR String

SPD*1.0*ACC:CZ{IBAN}*AM:{AMOUNT}*CC:CZK*MSG:{MESSAGE}

Generate a QR code from this string and present to the human for scanning with their banking app.


7. Security Considerations

7.1 Human-in-the-Loop Gates

Gate When Why
Payment approval Before any money transfer Agent MUST NOT autonomously pay
Personal data sharing Before sending name/address/email Privacy protection
Price threshold If negotiated price exceeds budget Financial guardrail

7.2 ADB Security

  • Device authentication: ADB requires prior USB debugging authorization (device-level trust)
  • Network exposure: Use USB connection, NOT adb tcpip over network (exposes device to LAN)
  • Scope limitation: Agent should only interact with SMS app β€” no contacts, no file access, no app installs
  • Credential isolation: Agent phone number is separate from human’s personal number

7.3 Data Handling

  • No persistent storage of seller phone numbers or bank details after transaction completes
  • SMS content should be processed in-memory, not logged to disk
  • Redact phone numbers and account numbers in any logs or memory files

7.4 Anti-Abuse

  • Rate limiting: Max 1 SMS per 30 seconds to avoid carrier spam flags
  • Verification cooldown: Bazos may throttle repeated phone verifications β€” respect delays
  • No automated bulk purchasing β€” this playbook is for single, intentional purchases

8. Known Pitfalls

Pitfall Impact Mitigation
input text drops spaces Garbled messages Word-by-word + KEYCODE_SPACE
Keyboard obscures Send button Silent tap failure KEYCODE_BACK before tapping Send
Stale compose window Text appended to old message Always am force-stop before composing
Wrong subdomain verification Code rejected Verify on listing’s subdomain
Screenshot coords β‰  touch coords Tap misses target Always use UI dump bounds
Script killed mid-send Duplicate on retry Verify compose field empty after each attempt
SMS content provider blocked Can’t read SMS programmatically Use UI dump method instead

9. Proof-of-Concept Outline

A minimal PoC consists of three scripts:

bazos_phone_reveal.py

  • Input: Bazos listing URL, agent phone number, ADB device ID
  • Flow: Browser β†’ trigger overlay β†’ enter phone β†’ read SMS via ADB β†’ enter code β†’ return seller phone
  • Output: Seller phone number

adb_sms.sh

  • Functions: send_sms(device, number, message), read_thread(device, contact_name)
  • Handles: force-stop, word-by-word typing, keyboard dismiss, send verification

purchase_orchestrator.py

  • Input: Listing URL, budget, shipping preference
  • Orchestrates: phone reveal β†’ SMS negotiation loop β†’ logistics lookup β†’ payment QR generation
  • Human gate: Presents QR, waits for confirmation before sending payment confirmation SMS

10. Future Improvements

  • OCR fallback: Screenshot + OCR when UI dump fails to capture dynamic content
  • Multi-device support: Route SMS through different devices based on carrier/region
  • Conversation memory: Track multi-turn negotiations across sessions
  • Auto-retry with backoff: Handle transient ADB connection drops
  • Platform expansion: Adapt patterns for other Czech classifieds (Sbazar, Facebook Marketplace)

This playbook is based on a successful real-world purchase completed on 2026-02-19. All techniques were validated against a Samsung device running Samsung Messages.