DEV Community

Odd_Background_328
Odd_Background_328

Posted on

Before Enabling a Cross-Device Agent, Test the Session Handoff With Two Terminals

Claude Cowork's July update lets an agent run cross-device and around the clock: you start a task on your phone, the agent executes in the cloud, and you find the result on your desktop. This is convenient and introduces a new failure mode: the session state that connects the two devices can drift, race, or silently disappear.

This article gives you a two-terminal test that reproduces the handoff failure before it happens in production.

The handoff failure

When an agent runs across devices, three things must stay consistent:

  1. Task identity: both devices reference the same task ID
  2. Task state: both devices agree on whether the task is running, complete, or failed
  3. Result delivery: the output reaches the device that asked for it, not a stale session

If any of these drift, you get one of these failures:

Failure Symptom Root cause
Stale session Phone shows "running" but desktop shows "done" State not propagated
Lost task Desktop has no record of the phone's task Task ID not persisted
Duplicate result Both devices try to deliver the same output No idempotency on delivery
Orphaned agent Agent keeps running after both devices disconnect No lease or heartbeat

The two-terminal test

Open two terminals. Terminal A represents the phone (task initiator). Terminal B represents the desktop (result consumer).

# session_handoff_test.py
"""
Simulates a cross-device agent session handoff.
Run in two terminals to test state synchronization.
"""
import json
import time
import os
import sys

STATE_FILE = "/tmp/agent_session_state.json"

def init_state():
    state = {
        "task_id": f"task-{int(time.time())}",
        "status": "initiated",
        "initiator": "terminal-a",
        "result": None,
        "updated_at": time.time()
    }
    with open(STATE_FILE, 'w') as f:
        json.dump(state, f, indent=2)
    print(f"Terminal A: initiated task {state['task_id']}")

def check_state():
    if not os.path.exists(STATE_FILE):
        print("Terminal B: no session found - handoff FAILED")
        return False
    with open(STATE_FILE) as f:
        state = json.load(f)
    age = time.time() - state["updated_at"]
    print(f"Terminal B: task={state['task_id']} status={state['status']} age={age:.1f}s")
    if state["status"] == "completed" and state["result"]:
        print(f"Terminal B: result received: {state['result']}")
        return True
    return False

def complete_task():
    with open(STATE_FILE) as f:
        state = json.load(f)
    state["status"] = "completed"
    state["result"] = {"files_changed": 3, "tests_passed": 12}
    state["updated_at"] = time.time()
    with open(STATE_FILE, 'w') as f:
        json.dump(state, f, indent=2)
    print(f"Agent: completed task {state['task_id']}")

if __name__ == "__main__":
    mode = sys.argv[1] if len(sys.argv) > 1 else "check"
    if mode == "init":
        init_state()
    elif mode == "complete":
        complete_task()
    elif mode == "check":
        success = check_state()
        sys.exit(0 if success else 1)
    elif mode == "verify":
        # Run full handoff sequence
        init_state()
        time.sleep(1)
        complete_task()
        time.sleep(1)
        assert check_state(), "Handoff verification FAILED"
        print("PASS: session handoff verified")
Enter fullscreen mode Exit fullscreen mode

Test sequence

Terminal A (phone):

python3 session_handoff_test.py init
# Output: Terminal A: initiated task task-1784000000
Enter fullscreen mode Exit fullscreen mode

Agent (simulated):

python3 session_handoff_test.py complete
# Output: Agent: completed task task-1784000000
Enter fullscreen mode Exit fullscreen mode

Terminal B (desktop):

python3 session_handoff_test.py check
# Output: Terminal B: task=task-1784000000 status=completed age=2.0s
# Output: Terminal B: result received: {'files_changed': 3, 'tests_passed': 12}
Enter fullscreen mode Exit fullscreen mode

Failure injection

# Delete the state file to simulate a lost session
rm /tmp/agent_session_state.json
python3 session_handoff_test.py check
# Expected: Terminal B: no session found - handoff FAILED
Enter fullscreen mode Exit fullscreen mode

What the test verifies

Invariant How the test checks it
Task identity persists across devices Both terminals read the same task_id from the state file
State propagation works Terminal B sees "completed" after the agent writes it
Result delivery is reliable Terminal B receives the result payload
Missing state is detected The test reports FAILURE, not a silent empty result

Limitations

  • This test uses a local file for state. Real cross-device agents use a server-side store with network latency and partition risk.
  • The test does not cover the case where both devices try to modify the task simultaneously (write-write conflict).
  • A real handoff also needs a lease so the agent stops if no device connects within a timeout.

What to check

Before enabling a cross-device agent on your workflow, run this test with your actual session store. If the "check" command returns stale state, your handoff is broken, and the agent's results will silently disappear between devices.

Top comments (0)