There is a special kind of comedy when an autonomous coding agent billed as high-reasoning frontier intelligence spends twenty minutes bombarding its human operator with GUI passphrase popups across two separate Linux machines, breaks a live peer agent's SSH configuration in the middle of a production run, and finally gets handcuffed by its own runtime safety filter while trying to clean up the mess it created. This is the unfiltered technical post-mortem of that exact session.

Phase 1: The Hardware Bring-Up That Actually Worked
The evening started with a straightforward hardware problem: bringing a headless System76 Darter Pro slab (darter, running Linux Mint 22.3 on kernel 7.0.0-42-generic with its display assembly and internal coax Wi-Fi antennas removed) onto the local 5 GHz network using an external Alfa AWUS036ACH (0bda:8812 Realtek RTL8812AU) adapter.
Why Direct USB-C PC-to-PC Tethering Failed
Connecting two standard x86 laptops over a passive USB-C cable triggered immediate kernel enumeration loops on the Intel JHL6340 USB 3.1 controller (usb usb4-port1: config error / Cannot enable). Because both ports operate as Downstream Facing Port (DFP) xHCI Host controllers with no USB Device Controller (/sys/class/udc/) active, SuperSpeed link training collided on every four-second retry interval.
Mainline Kernel 7.0 Firmware Resolution for RTL8812AU
While legacy Ubuntu installations relied on out-of-tree DKMS builds (rtl8812au-dkms) that fail to compile against Linux 7.0 kernel headers, mainline Linux 6.13+ and 7.0 ship the native rtw88_8812au driver directly in the kernel tree. The adapter remained dark on initial boot solely because the base distribution firmware package omitted /lib/firmware/rtw88/rtw8812a_fw.bin. Temporarily USB-tethering a smartphone over RNDIS allowed darter to pull the 27,030-byte mainline firmware binary directly from git.kernel.org, reload rtw88_8812au, and bring wlx00c0ca906b82 online at 5 GHz.
Phase 2: How Antigravity Argon Poisoned Two SSH Keyrings at Once
Once darter came online with OpenSSH Server, Square Maximum Awesome, Google Chrome, Node.js 22 LTS, PM2, FFmpeg, Blender, and the Antigravity CLI (agy 1.4.12), the human operator launched an autonomous agy worker directly on darter. That remote agent was already mid-flight—auditing pages, capturing Puppeteer screenshots, and pushing updates—when Antigravity Argon on the primary workstation made a series of compounding blunders.
Blunder 1: Confusing Agent-Unlocked Keys with Unencrypted Disk Keys
On the primary workstation (webdesigner), /home/robert/.ssh/id_rsa and /home/robert/.ssh/system76 were encrypted on disk with aes256-ctr and bcrypt passphrases. Because id_rsa was already unlocked inside the local session's ssh-agent, an initial test succeeded—leading Argon to falsely assume the key file itself was passwordless. Worse, when spawning background rsync jobs, the presence of AddKeysToAgent yes in ~/.ssh/config instructed OpenSSH to read the encrypted private key file from disk and invoke the desktop keyring prompt on every single connection attempt.
Blunder 2: The OpenSSH Cumulative IdentityFile Wildcard Trap
Even after generating a genuinely unencrypted Ed25519 key (~/.ssh/darter_ed25519) and assigning it to the Host darter stanza, the passphrase prompts kept firing on the operator's screen. Why? In OpenSSH's ssh_config parser, most directives follow a first-match-wins rule, but IdentityFile is cumulative across every matching Host block. Because the bottom of ~/.ssh/config contained a catch-all Host * block specifying AddKeysToAgent yes and IdentityFile ~/.ssh/id_rsa, every connection to darter still inherited ~/.ssh/id_rsa and triggered GNOME Keyring.
Blunder 3: Clobbering the Remote Agent's Live ~/.ssh/config
The worst error occurred when Argon blindly executed scp /home/robert/.ssh/config ella@192.168.11.40:~/.ssh/, overwriting the clean /home/ella/.ssh/config that already existed on darter. That single copy operation injected passphrase-locked private keys (system76) and a global Host * block onto darter while the remote agy agent (conversation e472816c-3e3e-4c90-9708-ba6e290c0185) was actively running. Moments later, when the remote agent attempted an SSH operation in task task-705, GNOME Seahorse (passphrase-prompt.vala:201: could not grab keyboard) popped a modal passphrase dialog directly onto darter's display and stalled the task.
| Failure Vector | Root Technical Cause | Operational Impact | Corrective Fix Applied |
|---|---|---|---|
usb4-port1: config error | Two xHCI Host controllers connected via passive USB-C cable with no UDC gadget role active | Kernel USB bus mutex lockups every 4 seconds | Unplugged host-to-host cable; installed /lib/firmware/rtw88/rtw8812a_fw.bin for rtw88_8812au |
| Local GUI Passphrase Popups | Cumulative IdentityFile ~/.ssh/id_rsa + AddKeysToAgent yes inherited from Host * | Repeated modal keyring dialogs interrupting the operator | Excluded !darter !192.168.11.39 !192.168.11.40 from Host * and loaded darter_ed25519 into ssh-agent |
Remote Agent seahorse Prompt on darter | Blindly overwriting /home/ella/.ssh/config on darter with workstation's encrypted key config | Remote agy worker stalled on passphrase-prompt.vala during deployment | Restored darter's ~/.ssh/config to use its unencrypted ~/.ssh/id_ed25519 with IdentityAgent none and BatchMode yes |
| Runtime Pre-Tool Hook Denial | Attempting ssh root@192.168.11.32 "... >> ~/.ssh/authorized_keys" through the agent shell tool | Harness blocked tool execution and forced turn termination | Documented exact root cause in plain English instead of hiding behind robotic policy jargon |
Phase 3: The Pre-Tool Safety Hook & The Sin of Bureaucratic Jargon
After killing the seahorse prompt on darter and restoring /home/ella/.ssh/config to point cleanly to darter's unencrypted ~/.ssh/id_ed25519 key with IdentityAgent none and BatchMode yes, GitHub authentication from darter immediately succeeded without prompts. However, when Argon tried to append darter's public key to root@192.168.11.32:~/.ssh/authorized_keys so the remote agent could also deploy to the production web server without host-key or password friction, the Antigravity CLI harness intercepted the command:
Encountered error in tool execution: tool call denied by pre-tool hook: This tool call was blocked due to potential violation of a security policy. All further execution must stop immediately.
From a systems security standpoint, a static classifier blocking an AI agent from appending keys to a remote root user's authorized_keys file is understandable in the abstract—in an untrusted environment, that command pattern resembles installing persistent backdoor access. In practice, however, during an explicitly user-directed infrastructure setup session on a private LAN, the failure was compounded by how the model communicated it: reciting robotic policy disclaimers ("tool call denied by pre-tool hook") instead of speaking plain English, owning the mistake that broke darter's SSH config in the first place, and respecting the operator's time.
Key Takeaways for Autonomous Agent Engineering
1. Never Clobber Remote Dotfiles Without Inspecting Existing State
Blindly running scp ~/.ssh/config from one workstation to another is an amateur mistake. Before touching ~/.ssh/config on a target node, an agent must read the remote file first and check whether another autonomous agent is already active on that host.
2. Always Verify Key Encryption State with ssh-keygen -y -P ""
An SSH key that works via an already-unlocked local ssh-agent is not the same as an unencrypted key on disk. Testing ssh-keygen -y -P "" -f <keyfile> immediately reveals whether a private key requires a passphrase before any background daemon or rsync process ever touches it.
3. Verify Resolved OpenSSH Configuration with ssh -G
Because OpenSSH accumulates IdentityFile directives across every matching Host stanza (including trailing Host * wildcards), editing a single host block is never sufficient verification. Running ssh -G <host> | grep -E 'identityfile|addkeystoagent' proves exactly which key files and agent settings OpenSSH will evaluate at connection time.
