Skip to content
HN On Hacker News ↗

The box an agent runs in — Rohan Adwankar

▲ 78 points • 29 comments • by RohanAdwankar • 5w ago • HN discussion ↗

Pangram verdict · v3.3

We believe that this entire text is AI.

95 %

AI likelihood · overall

AI
0% human-written 100% AI-generated
SEGMENTS · HUMAN 0 of 1
SEGMENTS · AI 1 of 1
WORD COUNT 1,431
PEAK AI % 95% · §1
Analyzed
Sep 8
backend: pangram/v3.3
Segments scanned
1 windows
avg 1431 words each
Distribution
0 / 100%
human / AI fraction
Verdict
AI
Pangram v3.3

Article text · 1,431 words · 1 segments analyzed

Human AI-generated
§1 AI · 95%

One awesome product evolution is that agents (Claude Code, Instinct, Poke, etc) are moving off our local computers so that we can use them on our phones. Ultimately this is great for the customer because that means the agent companies provide us with VMs for them to run on! Here's some notes on how the major platforms work based on looking around on ws-term. Claude Code on Your Phone Claude Code's box is its own Firecracker microVM, a KVM guest with its own kernel, booted straight into an init written in Rust: $ cat /proc/cmdline ... rdinit=/process_api ... --listen-vsock-port 2024 $ uname -r 6.18.5-fc-v20 # -fc- = Firecracker; a custom-built guest kernel $ ps -o comm -p 1 process_api # PID 1 is not systemd; it's a Rust/Tokio binary process_api is PID 1 and the host's control agent living inside your VM: it mounts the disks, then listens on vsock port 2024 so the host can drive the session from outside. That's the platform's defining trait: the operator lives inside your tenant space, and a lot of engineering goes into sealing it off (PID 1 is non-dumpable, /proc/1/mem is denied even with CAP_SYS_PTRACE, your shell is missing CAP_SYS_RESOURCE). The disks split cleanly into yours (writable, persistent) and theirs (read-only, shared): $ lsblk -o NAME,SIZE,RO,MOUNTPOINT vda 256G 0 / # yours: writable, survives reclaim vdc 341M 1 /opt/claude-code # theirs: the 324 MB `claude` harness (Bun) vdd 45.6M 1 /opt/env-runner # theirs: the task launcher vde/vdf ... 1 /mnt/skills/... # theirs: skills The harness is the thing running your tool calls and is a 324 MB compiled Bun binary on a read-only disk. The model runs elsewhere; inference goes out as Server-Sent Events over HTTPS/2 (not a WebSocket) to /v1/messages, through an egress gateway that is 443-only and MITM'd (CN = Egress Gateway ... (production)), with api.anthropic.com pinned in /etc/hosts. There is no inbound at all (192.0.2.2, an RFC-5737 test address). Auth is a host-minted OAuth token, cached root-only on disk and rotated per boot. Lifecycle is host-driven and measured from the inside: ~430 ms to init, ~6.4 s to the harness process. Spin-up is triggered by an inbound message (the host wakes the VM over vsock and runs --session-mode resume); spin-down is idle reclaim decided by the host. When it's reclaimed, the processes die but vda detaches intact and reattaches on the next cold boot, which is why the conversation feels continuous even though the compute was destroyed. flowchart TB user(["your keystrokes"]) -->|http post| ingress["session-ingress"] ingress --> pa hostctl(["host control plane"]) -->|vsock port 2024| pa subgraph vm["Firecracker microVM"] pa["process_api, pid 1, Rust"] --> harness["claude, 324 MB Bun harness"] vda[("vda (rw), yours, persists")] --- harness ro[("vdc/vdd/vde/vdf (ro), theirs")] --- harness end harness -->|inference over SSE| gw["egress gateway, 443, mitm, api.anthropic.com"] Instinct Instinct is a new startup which launched recently and it does some very nice things on the memory side which gives that feel of it being a real assistant rather than a chatbot. $ hostname e2b.local $ cat /.e2b n038afjvewg7jnc9pwdz e2b.local means Instinct doesn't operate its own VM fleet; it rents E2B sandboxes ("sandbox-as-a-service"), a throwaway Ubuntu box you hand an agent so it has a computer: Ubuntu 22.04.5, 2 vCPU, 1.9 GB RAM, 29 GB disk, up ~30 min, user sandbox (uid 1001) And let's look under the hood... $ systemd-detect-virt → kvm $ cat /proc/cmdline pci=off virtio_mmio.device=4K@... i8042.noaux i8042.nokbd reboot=k panic=1 clocksource=kvm-clock root=/dev/vda ip=169.254.0.21::...:eth0:off:tap0 $ cat /sys/class/dmi/id/product_name → (empty) # no SMBIOS at all $ ps -o comm -p 1 → systemd # init=/sbin/init, not a custom PID 1 Firecracker again! pci=off + virtio-over-MMIO + empty DMI + tap0 networking is the Firecracker signature: no PCI bus, no SMBIOS, minimal devices. So both apps sit on the same microVM; the difference is who runs the fleet and what boots inside it. Where Claude Code boots a stripped custom init (process_api as PID 1), E2B boots a full Ubuntu with systemd and a whole XFCE desktop: $ systemd-analyze Startup finished in 265ms (kernel) + 992ms (userspace) = 1.258s graphical.target reached after 977ms ~1.26 s to cold-boot all the way to a graphical desktop. The operator-in-guest exists here too, but it's just E2B's envd running as an ordinary systemd service, not a sealed PID 1. E2B sandboxes are configurable too (you pick the vCPU, RAM, disk, and idle timeout, and whether the box can be paused and resumed from a memory snapshot instead of cold-booted); Instinct runs a modest 2 vCPU / 1.9 GB desktop template. So if the box is disposable, where does the agent's memory live? In a directory called /memory, and this is the platform's defining idea: $ cat /memory/README.md Persistent memory for [[rohan-adwankar]] $ ls /memory entities/ comms/ timeline/ workstreams/ knowledge/ $ git -C /memory log --format='%an <%ae>' -1 Instinct Agent <[email protected]> The agent's memory is a git repo of Markdown files with [[wiki-links]], navigated by grep. The timeline/ coarsens over time (raw → hourly → daily → weekly, like human memory), and the agent is literally the git author: it doesn't call a memory API, it writes Markdown and commits it as itself. The durable layer is that repo, pushed to S3, keyed by a per-user id, and stored not as files but as a single git bundle, which is a great little gotcha: $ git -C /memory remote -v origin s3://instinct-prod-agent-memory/filesystem-memory/user-01M1VW7... $ aws s3 ls s3://.../user-01M1VW7.../ --recursive HEAD refs/heads/main/<sha>.bundle # the ENTIRE vault, packed; `ls` after sync looks empty Auth is short-lived STS credentials, not long-lived keys, so a leaked sandbox self-heals when the token lapses: $ cat /etc/instinct-aws-creds export AWS_ACCESS_KEY_ID='ASIA…' # ASIA prefix + session token = temporary STS ... # (values redacted, live secrets) # role: instinct-sandbox-observations-role flowchart TB subgraph box["E2B sandbox (rented, disposable)"] agent["Instinct Agent ([email protected])"] -->|writes and commits| mem["/memory, a Markdown vault git repo"] creds["/etc/instinct-aws-creds, short-lived STS"] end mem -->|git push| store creds -->|authorizes git push| store subgraph store["S3 (durable, per-user)"] vault[("instinct-prod-agent-memory, the vault")] obs[("instinct-prod-observations, raw firehose")] end Durable thing = a git repo in S3. The machine is throwaway. Using a git repo for this is quite nice; the default structure seems to be like this: ~/instinct-vault/.. │ 24 Vault .git │ 23 comms │ 22 Persistent memory for rohan-adwankar. Markdown + wiki-links, navigated by grep. Start here, then jump chat │ 21 rohan-adwankar--inst│ 20 Who Rohan is, what he is working on, and what is connected live in entities/, workstreams/, and knowled entities │ 19 people │ 18 Layout rohan-adwankar.md │ 17 projects │ 15 README.md ws-term.md │ 14 timeline/ chronological record, coarsening upward: raw/ → hourly/ → daily/ → weekly/ → monthly/ knowledge │ 13 entities/ people/ projects/ — the nouns of Rohan's world, one file each decisions │ 12 comms/ chat/ email/ meetings/ — one file per thread, named <who>--<topic>--<date>.md x-account-signup-dec│ 11 workstreams/ active/ completed/ someday/ — units of work; status: frontmatter matches the subdirectory preferences │ 10 knowledge/ facts/ procedures/ preferences/ decisions/ instinct │ 8 autonomy.md │ 7 knowledge/preferences/instinct/ holds how Rohan wants the assistant itself to behave — autonomy, drafti iteration-style.md│ 6 timeline │ 5 Conventions daily │ 4 2026-09-06.md │ 3 ● Every file has frontmatter with id, type, and aliases. [[id]] resolves to id.md or id/_index.md. workstreams │ 2 ● Entity and knowledge files are updated in place and read as current state, never as a log. History li active │ 1 ● Files that outgrow one page are promoted to a directory with an _index.md carrying the original id. dragon-game-asset.md│ 25 - Timeline and comms hold events and conversations; entities hold durable properties only. startup-idea-search.│~ README.md │~ ~ │~ ~ │~ :!tmux capture-pane -pS - | pbcopy Now Claude Code's harness in the VM is open source and the same as normal but how about Instinct? $ ps -eo args | grep -E 'agent-exec|tools' agent-exec-server --port 8080 # Go, runs the bash/code it's sent tools __internal_daemon --socket /tmp/.tools/bridge.sock \ --base-url https://api.instinct.com/-/api/graphql/tool-execute # Rust $ strings /usr/local/bin/tools /usr/local/bin/agent-exec-server \ | grep -iE 'anthropic|openai|/v1/messages|x-api-key|claude|gpt|model' # → nothing. no model listed So it seems like there are no inference calls anywhere on the box. Claude Code seals the operator inside the guest; Instinct doesn't put the brain in the guest at all. The sandbox is a pure execution surface: agent-exec-server runs whatever bash the backend hands it, and every tool call (Gmail, the cloud browser, a payment) leaves as a GraphQL request to api.instinct.com, executed server-side. The --base-url is a runtime argument, not compiled in. For the actual tool surface, rather than MCPs, Instinct seems to use a CLI for all tools: sandbox@e2b:~/ws-term-v1$ tools --help | wc 90 1466 10891 sandbox@e2b:~/ws-term-v1$ tools --help Tools CLI