You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Consolidates and supersedes #362. Bundled into one issue (bug + UX findings + a proposed fix) for easier triage — happy to split or send a PR if you prefer.
Summary
Tested the tether skill hands-on end-to-end (Windows/Git Bash, hosted api.e2a.dev, plugin e2a@e2a 0.4.5), from a true zero state through a live tethered session. One hard blocker on Windows, one hosted deploy-lag, and several onboarding-UX rough edges. I prototyped a fix + a one-command tether.sh setup; details and a reference implementation below.
1. Blocker — hardcoded python3 breaks tether on Windows
Every script hardcodes python3. On a default Windows install that's the Microsoft Store App Installer redirector shim: it's on PATH (so command -v python3 succeeds) but exits non-zero without running; the real interpreter is python.
$ python3 -c 'print(1)'# exit 49, no output (the shim)
$ python -c 'print(1)'# 1 (Python 3.13.5)
Because the scripts use set -uo pipefailwithout -e, each failed python3 call returns empty and execution limps forward. Result: a configured start fails silently with a misleading message:
None of creds/URL/protection is the cause — t_duration_to_expiry, t_state_set (no state file written), and the send payload builder all no-op'd first. Even with a valid key, start can't work: the state file update/poll/listen rely on is never created.
_selftest gives a false green — it prints # syntax OK on this broken machine because it only runs the unconfigured status path (no python3) + bash -n; it never does a real interpreter round-trip.
Suggested fix (resolve once, verify it actually executes):
t_resolve_python() {
local c
forcin"${E2A_PYTHON:-}" python3 python;do
[ -n"$c" ] ||continueifcommand -v "$c">/dev/null 2>&1 \
&&"$c" -c 'import sys; sys.exit(0 if sys.version_info[0]==3 else 1)'>/dev/null 2>&1;thencommand -v "$c";return 0
fidone;return 1
}
PY="$(t_resolve_python)"||echo"tether: no working Python 3 (set E2A_PYTHON)">&2# route the ~20 python3 call sites through "$PY"
Plus: make _selftest do a real interpreter round-trip so it can go red; distinguish "local tooling failed" from "server rejected" in the start error; document the Python-3 prereq in SKILL.md.
2. Onboarding friction (a "just tether" user)
Tether is a bash/curl sidecar, but a new user is routed through two credential worlds and three surfaces:
Before (works, but ~8 manual steps / 3 surfaces):
e2a login → install plugin + mcp add/OAuth → create agent →
dashboard: mint an agent-scoped key by hand → turn HITL off →
hand-edit env (full agent address; local-part alone 404s) → /tether
Pain points: the plugin quickstart is "no key to paste," but tether needs a hand-minted key; mcp add writes nothing tether reads and there's no key-minting MCP tool; the env template's E2A_AGENT_EMAIL needs the full address; status reports config: OK even on a placeholder key (non-empty ≠ valid); chmod 600 in the setup steps is a no-op on NTFS.
Correction to a common assumption: minting an agent-scoped key is not dashboard-only — POST /v1/account/api-keys with scope=agent works with an account key (verified live). So the flow can be automated.
3. Proposed: tether.sh setup (one command)
After:
e2a login → /tether → setup → give email + duration → start + listen → steer from inbox
setup resolves an account credential (~/.e2a/config.json from e2a login, or an e2a_acct_ key), then:
ensures an agent inbox (reuse, else POST /v1/agents a tether-<rand>@<shared_domain>),
forces HITL off (GET+merge+PUT /protection),
mints a least-privilege e2a_agt_ key bound to that inbox (POST /v1/account/api-keys) and stores that (not the account key) in ~/.e2a-tether.env.
Verified from a true zero state (0 agents, 0 keys) on Windows against hosted: setup created the inbox, minted a scoped key (whoami → scope=agent), wrote the env, and start delivered to a real Gmail. I have this working on a branch and am happy to open a PR — or you may prefer to fold it into the "smoother CLI path" the skill already mentions.
4. Live-use findings (from an actual tethered session)
Consecutive updates fail (High).update = "reply to the last message"; after one update the last message is the agent's own outbound, so a second update back-to-back → 404 not_found. This is the reply-to-own-outbound behavior; feat: reply to and forward the agent's own outbound messages #360 fixes it but isn't deployed to api.e2a.dev yet (hosted still 404s POST …/messages/{id}/reply on an outbound target even though GET returns it). Net effect until deploy: a tethered agent can post at most one update per user reply — the normal "give a couple status updates while working" pattern is broken.
Window expiry cuts off an active conversation (Medium).--for hit TETHER_EXPIRED and auto-stopped mid-decision, with no auto-extend and no warning. Suggest extend-on-activity + an "expiring soon" email.
Stopped/expired tether silently drops inbound (Medium). Once unarmed, nothing polls and the user's emails get no reaction/bounce. Correct by design, but surprising — worth a clearer "no longer listening" signal.
What works well: the background listen → wake-the-agent loop reacted to each email within ~20s with zero polling tokens, and the safe-vs-destructive judgment (executed a "make a folder" request immediately; refused a vague "delete temp files" and investigated read-only instead) is exactly right for an AFK channel.
Summary
Tested the tether skill hands-on end-to-end (Windows/Git Bash, hosted
api.e2a.dev, plugine2a@e2a0.4.5), from a true zero state through a live tethered session. One hard blocker on Windows, one hosted deploy-lag, and several onboarding-UX rough edges. I prototyped a fix + a one-commandtether.sh setup; details and a reference implementation below.Environment: Windows 11, Git Bash (GNU bash 5.2.37, MSYS),
python3.13.5, curl 8.11.0.1. Blocker — hardcoded
python3breaks tether on WindowsEvery script hardcodes
python3. On a default Windows install that's the Microsoft Store App Installer redirector shim: it's onPATH(socommand -v python3succeeds) but exits non-zero without running; the real interpreter ispython.Because the scripts use
set -uo pipefailwithout-e, each failedpython3call returns empty and execution limps forward. Result: a configuredstartfails silently with a misleading message:None of creds/URL/protection is the cause —
t_duration_to_expiry,t_state_set(no state file written), and the send payload builder all no-op'd first. Even with a valid key,startcan't work: the state fileupdate/poll/listenrely on is never created._selftestgives a false green — it prints# syntax OKon this broken machine because it only runs the unconfiguredstatuspath (nopython3) +bash -n; it never does a real interpreter round-trip.Suggested fix (resolve once, verify it actually executes):
Plus: make
_selftestdo a real interpreter round-trip so it can go red; distinguish "local tooling failed" from "server rejected" in thestarterror; document the Python-3 prereq in SKILL.md.2. Onboarding friction (a "just tether" user)
Tether is a bash/curl sidecar, but a new user is routed through two credential worlds and three surfaces:
Before (works, but ~8 manual steps / 3 surfaces):
Pain points: the plugin quickstart is "no key to paste," but tether needs a hand-minted key;
mcp addwrites nothing tether reads and there's no key-minting MCP tool; the env template'sE2A_AGENT_EMAILneeds the full address;statusreportsconfig: OKeven on a placeholder key (non-empty ≠ valid);chmod 600in the setup steps is a no-op on NTFS.3. Proposed:
tether.sh setup(one command)After:
setupresolves an account credential (~/.e2a/config.jsonfrome2a login, or ane2a_acct_key), then:POST /v1/agentsatether-<rand>@<shared_domain>),GET+merge+PUT /protection),e2a_agt_key bound to that inbox (POST /v1/account/api-keys) and stores that (not the account key) in~/.e2a-tether.env.Verified from a true zero state (0 agents, 0 keys) on Windows against hosted: setup created the inbox, minted a scoped key (
whoami→scope=agent), wrote the env, andstartdelivered to a real Gmail. I have this working on a branch and am happy to open a PR — or you may prefer to fold it into the "smoother CLI path" the skill already mentions.4. Live-use findings (from an actual tethered session)
update= "reply to the last message"; after one update the last message is the agent's own outbound, so a secondupdateback-to-back →404 not_found. This is the reply-to-own-outbound behavior; feat: reply to and forward the agent's own outbound messages #360 fixes it but isn't deployed toapi.e2a.devyet (hosted still 404sPOST …/messages/{id}/replyon an outbound target even thoughGETreturns it). Net effect until deploy: a tethered agent can post at most one update per user reply — the normal "give a couple status updates while working" pattern is broken.--forhitTETHER_EXPIREDand auto-stopped mid-decision, with no auto-extend and no warning. Suggest extend-on-activity + an "expiring soon" email.What works well: the background
listen→ wake-the-agent loop reacted to each email within ~20s with zero polling tokens, and the safe-vs-destructive judgment (executed a "make a folder" request immediately; refused a vague "delete temp files" and investigated read-only instead) is exactly right for an AFK channel.Asks / follow-ups
updateworks (and/or haveupdatefall back to a fresh send in the sameconversation_idwhen the last message is outbound).tether.sh setup(or your own CLI path) to collapse onboarding to one command.