{"slug": "3-traps-i-fell-into-while-letting-a-phone-control-a-desktop-agent", "title": "3 traps I fell into while letting a phone control a desktop agent", "summary": "A developer building DeepSeek Phone Harness, a mobile remote control for a desktop agent, encountered three major pitfalls during development. The relay initially missed question frames from the agent's `ask_user_question` tool, causing tasks to hang indefinitely. Additionally, the tool result payload had a nested structure that was not parsed correctly, and caching issues prevented UI updates from appearing on the phone. The developer fixed these issues and open-sourced the project under the MIT license.", "body_md": "On the surface it's an HTTP layer and a web page. Underneath, every step fights your assumptions. Real pitfalls, so you can avoid them.\n\nBefore building DeepSeek Phone Harness, I assumed \"mobile remote control for a desktop agent\" was just moving a web page to a phone. After finishing it, I admit: **the idea took 10 minutes; the bug-fixing took a week.**\n\nHere are 3 real traps — each one made tasks \"gracefully deadlock\" in production.\n\nThis is the nastiest one.\n\nOur relay listened to DSH's approval channel (`approval/requested`\n\n) — all good. Until one day a test task **never finished**. Not an error — just hung, `pending`\n\nclimbing.\n\nTwo days of digging later: DSH agents can call the `ask_user_question`\n\ntool to **ask the user something** — and that goes through a *different* channel (`question/requested`\n\n), **not** the approval channel. My relay only listened for approvals, so question frames were silently dropped.\n\nResult: the agent waits on the computer for a human answer, the phone has no idea, the task hangs forever. **It only continues once the user answers.**\n\nFix: ingest question frames separately, forward them as \"your answer needed\" cards, and use the exact same answer protocol as the official Web GUI.\n\n**Lesson: in an agent's realtime event stream, every frame type exists for a reason. Miss one, and tasks die in ways you'd never guess.**\n\nThe phone shows \"tool cards\": tool name + file path + result. Name is easy, path is easy (extract from arguments). Result?\n\nI assumed `tool/result`\n\ncontent was `[{type:'text', text:'...'}]`\n\n. Naive. The real shape:\n\n```\ncontent: [{\n  \"type\": \"tool-result\",\n  \"content\": [{ \"type\": \"text\", \"text\": \"<path>...<content>...\" }]\n}]\n```\n\n**Two levels of nesting**, with `toolCallId`\n\non the inner block. My first version only read one level: cards had names and paths, but results were always empty.\n\nFix: recursive text collection + pairing calls to results via `source.callId`\n\n.\n\n**Lesson: no protocol doc beats capturing one real payload.**\n\nChanged the UI, opened the phone — **still the old one.** Refresh, restart browser, switch browser — same.\n\nNot a network issue. It's **caching**: the old page was cached, and `Cache-Control`\n\nwasn't set.\n\nFix: serve HTML with `no-store, no-cache, must-revalidate`\n\n. Every open is now the latest.\n\n**Lesson: for mobile web apps, cache strategy matters as much as feature code.**\n\nEach one reveals the real complexity of \"remote-controlling an agent from a phone\":\n\nAfter fixing all of it, tool cards look like this on the phone:\n\n```\n[📄 read]                          ● done\nC:/Users/Joey/Documents/.../config.json\n▾ tap to expand: full arguments + full result\n```\n\nEvery step the agent takes — which file, what command, the outcome — is visible. Permission requests and questions become cards. **Tasks never hang because \"nobody answered.\"**\n\nOpen source (MIT). Stars / PRs / issues welcome:\n\n**What's the weirdest bug you've hit while working with agents?** Share it below — I bet it beats mine.", "url": "https://wpnews.pro/news/3-traps-i-fell-into-while-letting-a-phone-control-a-desktop-agent", "canonical_source": "https://dev.to/joey020907/3-traps-i-fell-into-while-letting-a-phone-control-a-desktop-agent-4gc6", "published_at": "2026-08-16 06:49:42+00:00", "updated_at": "2026-08-16 07:11:37.566401+00:00", "lang": "en", "topics": ["ai-agents", "developer-tools", "ai-infrastructure"], "entities": ["DeepSeek Phone Harness", "DSH"], "alternates": {"html": "https://wpnews.pro/news/3-traps-i-fell-into-while-letting-a-phone-control-a-desktop-agent", "markdown": "https://wpnews.pro/news/3-traps-i-fell-into-while-letting-a-phone-control-a-desktop-agent.md", "text": "https://wpnews.pro/news/3-traps-i-fell-into-while-letting-a-phone-control-a-desktop-agent.txt", "jsonld": "https://wpnews.pro/news/3-traps-i-fell-into-while-letting-a-phone-control-a-desktop-agent.jsonld"}}