{"slug": "a-remote-coding-agent-can-deadlock-on-a-local-permission-dialog", "title": "A Remote Coding Agent Can Deadlock on a Local Permission Dialog", "summary": "A developer building BitFun, an open-source remote coding agent, identified a critical failure mode where permission prompts in a desktop UI can deadlock remote jobs. The fix involves modeling permission requests as durable state owned by the job, with a persisted mailbox, stable request IDs, and replay-safe answers. The developer emphasizes that approval is not UI state and that the protocol must be bounded, auditable, and fail-closed.", "body_md": "The nastiest failure mode in a remote coding agent is not a bad patch.\n\nIt is a permission prompt that nobody can see.\n\nYou start a long-running job on a workstation, leave the desk, and check it from a phone later. The agent reaches a command that needs approval. If that request only exists as a modal in the desktop UI, the job has not technically failed. It has just stopped forever.\n\nThat is worse. A failed job is observable. A hidden wait looks healthy until someone notices no work has moved.\n\nThe fix starts with a small change in how you model approval.\n\nA permission request is not UI state. It is durable state owned by the job that is doing the work.\n\nThe lifecycle should look more like this:\n\n**asked → persisted → surfaced → answered → applied → resolved**\n\nThe desktop dialog, phone screen, CLI, or web controller is only one view over that state. Closing a window must not erase it. Reconnecting must not create a second request. Two controllers must not be able to resolve different requests because a stale button happened to be on screen.\n\nThis also changes what a remote-control protocol needs. A controller should be able to fetch job status with pending approvals, submit an answer for one request ID, and observe the resulting event. It should not become a filesystem or runtime proxy just to click “allow.”\n\nAt minimum, the pending request needs a stable request ID, its owning job/session, the requested action and resources, and enough ordering information to render concurrent requests deterministically.\n\nThe answer also needs an identity.\n\nIf request `abc`\n\nis pending, an answer for `xyz`\n\nmust fail. Replaying the same answer for `abc`\n\nshould be harmless. Replaying a different answer under the same ID should not quietly overwrite the first decision.\n\nThat sounds fussy until a phone reconnects on a flaky network and retries the last command. Then it is the difference between idempotence and “the agent ran it twice.”\n\nThe mailbox also needs limits. A broken or hostile tool should not be able to fill an unattended host with an unbounded number of serialized approval requests.\n\nPersisting an “approved” flag is not enough.\n\nThe running worker has to consume the answer, apply it to the exact pending request, record where the reply came from, and only then remove the request from the mailbox. If the worker crashes between those steps, recovery should be able to tell whether the answer is queued, applied, or fully resolved.\n\nReply source matters too. A user approval, an automatic policy, and a system rejection are not the same audit event, even if they all unblock the same future.\n\nWhen the permission event stream disappears, the safe behavior is not to assume approval. Pending work should fail closed or be cancelled with an explicit reason. Otherwise a transport failure silently turns into broader authority.\n\nOnce the protocol exists, the phone UI really can be two buttons: approve and reject.\n\nBut those buttons are the last five percent. The hard part is making the request durable, routed to the correct session, replay-safe, auditable, bounded, and fail-closed.\n\nThere is also a boundary worth keeping explicit: an application-level tool approval is not an operating-system security grant. A remote controller can approve an agent action that the app is already capable of performing. It cannot legitimately manufacture Accessibility, Screen Recording, or similar host privileges that the operating system has not granted.\n\nI am building BitFun, and this is how we ended up treating detached-job approvals: the target owns a persisted permission mailbox; the controller answers by request ID; the worker applies the reply with its source and marks it resolved. The same permission events can then reach desktop and remote-control surfaces without making the controller the runtime.\n\nThe implementation is open source here: [https://github.com/GCWing/BitFun](https://github.com/GCWing/BitFun)", "url": "https://wpnews.pro/news/a-remote-coding-agent-can-deadlock-on-a-local-permission-dialog", "canonical_source": "https://dev.to/bobleer/a-remote-coding-agent-can-deadlock-on-a-local-permission-dialog-o44", "published_at": "2026-08-13 00:07:48+00:00", "updated_at": "2026-08-13 00:46:09.379780+00:00", "lang": "en", "topics": ["developer-tools", "ai-agents"], "entities": ["BitFun", "GCWing"], "alternates": {"html": "https://wpnews.pro/news/a-remote-coding-agent-can-deadlock-on-a-local-permission-dialog", "markdown": "https://wpnews.pro/news/a-remote-coding-agent-can-deadlock-on-a-local-permission-dialog.md", "text": "https://wpnews.pro/news/a-remote-coding-agent-can-deadlock-on-a-local-permission-dialog.txt", "jsonld": "https://wpnews.pro/news/a-remote-coding-agent-can-deadlock-on-a-local-permission-dialog.jsonld"}}