{"slug": "2000-agents-ported-prime-agent-to-rust-a-terminal-frame-diff-was-the-judge", "title": "2,000 Agents Ported Prime Agent to Rust. A Terminal-Frame Diff Was the Judge", "summary": "Prime Intellect ported its Prime Agent coding agent from TypeScript to Rust using a swarm of more than 2,000 agents across 10,000+ Prime Sandboxes, consuming over 200 billion tokens from its GLM-5.3 endpoint over two weeks. Each task passed through plan, implement, review and verify stages, with failed reviews or verifications returning work to the implementer, and merges gated on parity checks including a terminal-frame diff that ran both binaries against the same scripted model. A follow-up hillclimb by 228 agents merged over 69 changes, cutting cold start from 736.1 ms to 51.9 ms and memory use from 1,130 MB to 237 MB.", "body_md": "On October 9, [Prime Intellect](https://www.primeintellect.ai/blog/prime-agent-rust) published how its coding agent, [Prime Agent](https://github.com/PrimeIntellect-ai/prime-agent), rewrote itself from TypeScript to Rust. Over two weeks, a swarm of more than 2,000 agents ran across 10,000+ Prime Sandboxes and spent over 200 billion tokens from the company's GLM-5.3 endpoint. The agent being rewritten had been downloaded more than 300,000 times since its August launch, according to the same post.\n\nThe token count is the headline. The part worth copying is smaller: how anyone could tell the Rust binary behaved like the TypeScript one. The answer was a test that runs both programs against the same scripted model and diffs the terminal frames they draw. Every merge had to pass its task's parity check, and for the TUI that check was this frame diff.\n\nA root orchestrator split the port into tasks in dependency order. Per the post, \"the root agent wrote no product code.\" It watched tasks, merged finished work, kept the overview and settled priorities with the humans.\n\nEach task then went through four agents:\n\nA failed review or a failed verification sends the task back to the implementer with the findings. The pull request merges only when both pass. The post gives the reason in one line: \"an agent that writes code is biased when evaluating it.\"\n\nThat loop is small enough to write down. Here it is as a TypeScript transition function. The stage names are mine, the rules are the post's:\n\n```\ntype Stage =\n  | \"plan\" | \"implement\" | \"review\" | \"verify\" | \"merged\";\n\ninterface Result {\n  pass: boolean;\n  findings: string[];\n}\n\nfunction next(stage: Stage, r: Result): Stage {\n  switch (stage) {\n    case \"plan\":\n      return \"implement\";\n    case \"implement\":\n      return \"review\";\n    case \"review\":\n      return r.pass ? \"verify\" : \"implement\";\n    case \"verify\":\n      return r.pass ? \"merged\" : \"implement\";\n    case \"merged\":\n      return \"merged\";\n  }\n}\n```\n\nLook at the two failure edges. They both go back to the implementer, never forward. No agent can vote its own work through, because the review stage never sees the implementer's context and the verify stage doesn't take an opinion at all.\n\n\"Behaves the same\" is vague until you name what gets compared. Prime Intellect compared four things:\n\nThe scripted model is the trick that makes this work. A real model answers differently every run, so two binaries talking to it would never draw the same screen twice. Replace it with a script that returns the same tokens in the same order, and any difference between the two screens comes from the client. That is a test an agent can't argue with.\n\nThe core of a frame diff is boring on purpose. Render each binary in a terminal emulator, capture the screen after each step as text, and find the first step where they disagree:\n\n```\n// frames[i] = the full screen text after step i\nfunction firstDiff(ts: string[], rs: string[]): number {\n  const n = Math.max(ts.length, rs.length);\n  for (let i = 0; i < n; i++) {\n    if (ts[i] !== rs[i]) return i;\n  }\n  return -1; // identical\n}\n```\n\nYou can get a crude version of the capture step with [tmux](https://man.openbsd.org/tmux.1): run each program in its own pane and dump the screen text with `capture-pane -p` after every scripted input. Prime Intellect's post says it drives a real terminal through a screen emulator; it doesn't name the tool. What matters is the shape: same inputs, same fake model, two programs, one equality check.\n\nAfter the port, 228 agents spent three more days on a performance \"hillclimb\" and merged over 69 changes. [The post's table](https://www.primeintellect.ai/blog/prime-agent-rust), from a fresh 4-core, 8 GB sandbox per benchmark:\n\n| Metric | TypeScript | Rust, first port | Rust, after hillclimb | \n|---|---|---|---|\n| Cold start, input-ready | 736.1 ms | 293.3 ms | 51.9 ms | \n| Warm start, input-ready | 552.3 ms | 276.7 ms | 41.4 ms | \n| RSS, 10 MiB session | 1,130.0 MB | 554.9 MB | 237.3 MB | \n| Installed size | 172.1 MB | 206.7 MB | 59.6 MB | \n| Agents view switch | 78.0 ms | 118.8 ms | 12.8 ms | \n\nThe first Rust port started about 2.5x faster than TypeScript (293.3 ms vs 736.1 ms). The hillclimb then cut that another 5.6x, to 51.9 ms. The post's headline 14.18x cold-start figure is the port and three days of tuning together, and the tuning is the larger multiplier. And the first port was worse than TypeScript on two rows: a larger install and a slower agents view switch. The rewrite by itself did not win every row.\n\nThe benchmark drives the binary \"against a scripted model, so timings reflect what a user sees and exclude inference.\" That 51.9 ms is the time until you can type into a client whose model answers instantly. It says nothing about how long a real turn takes, because every real turn also waits on the model, and nothing about the quality of the agent's work.\n\nThe post also compares against other harnesses. Time to type, cold: 55.8 ms for Rust Prime Agent, 348.4 ms for Claude Code v2.1.289, 324.6 ms for Codex CLI v0.160.0 and 2,094.5 ms for Hermes Agent v0.21.5. The authors add the caveat themselves: \"Without a common benchmark standard, comparisons should be interpreted with caution.\" [AlphaSignal](https://alphasignal.ai/news/prime-intellect-sent-2-000-agents-to-rewrite-prime-agent-13x-faster-in-rust) notes the numbers \"have not been independently replicated.\" That Hermes Agent is not the Hermes IDE I build; Nous Research publishes an agent under that name.\n\nPrime Intellect is direct about the gap: \"the parity checks only verified the behavior they exercised.\" Remaining bugs and behavior differences \"were largely found through internal use\" and through agents reading beta users' logs and traces. Per the post, humans set up the verification, made the priority calls with the root agent and reviewed all results.\n\nUsers noticed too. A [GitHub issue](https://github.com/PrimeIntellect-ai/prime-agent/issues/3324) opened on October 2 calls the Rust TUI \"nothing but a huge degradation of usability and functionality and consistency,\" and its author says they keep a fork that fixes several bugs. A bot closed it the same day under the repo's rule that issue reporters must be vouched for, without a technical reply. It is one report. It still shows the boundary: a frame diff proves the scripted flows match. It cannot prove that flows nobody scripted feel right.\n\nKeep the diff, and keep a list of what it covers. Each scripted flow is a promise you can check on every merge; anything outside the scripts is back to humans reading the screen.\n\nYou don't need 10,000 sandboxes to borrow the pattern. You need three things: the implementer works in isolation, the reviewer is a different agent that never saw the implementer's reasoning, and the verifier is a command that passes or fails.\n\nI build [Hermes IDE](https://hermes-ide.com), so weigh this section with that in mind. Hermes runs each agent in a real terminal, with its own interface. ⌘N (Ctrl+Shift+N on Windows and Linux) starts a task on its own `hermes/<name>` branch in its own git worktree, with the task as the agent's first prompt. That is the implementer's isolated worktree, on your machine.\n\n*Codex on orders-types and Claude Code on orders-api, each in its own `hermes/` worktree, with status, context use, cost and branch in the sidebar.*\n\nFor the reviewer, use a different agent from the implementer. If Claude Code wrote `hermes/port-config`, start a second task in Codex and ask it to review `git diff main...hermes/port-config`. Worktrees share one git history, so the branch is visible from every worktree. That is the closest local version of \"a different model in a separate context.\" Hermes also lets you run the same task in two agents side by side, each in its own worktree, so you get two implementers and can compare the branches yourself.\n\nFor the verifier, write it down. A repo's `.hermes/worktree.toml` can name the commands that decide when a task is done, as in the [worktree recipe docs](https://github.com/hermes-hq/hermes-ide/blob/main/docs/worktree-recipes.md):\n\n```\n# .hermes/worktree.toml\nsetup = [\"npm ci\"]\ndone_when = [\"npm test\"]\n```\n\nPut your parity check there. If you are porting a CLI, that can be a script that replays recorded inputs through the old and new binaries and fails on the first differing frame, like `firstDiff` above. Then read the work by turn in the Review Desk (⌘G, or Ctrl+Shift+G), where a line comment goes back to the agent that wrote that line.\n\n*The Review Desk by turn: two Claude Code turns, turn 1's diff of src/db.ts, and a commit message drafted from the turns.*\n\nHermes runs agents on your machine in worktrees. It does not give you fresh cloud sandboxes like Prime's verifier had, so your check runs in the task's worktree. Hermes is source-available under BSL 1.1 and runs on macOS, Windows and Linux. It is not affiliated with Prime Intellect, Nous Research, Anthropic, OpenAI or any agent vendor. [Download it](https://hermes-ide.com/download), and if the pattern helps, [star it on GitHub](https://github.com/hermes-hq/hermes-ide).\n\nTo start small, pick one flow your agents touch this week, script it, and put the check in `done_when` before the next task starts.\n\nA planner, an implementer, a reviewer and a verifier passing state between them is a multi-agent graph with explicit transitions, and that is what my book *AI That Plans* is about. It builds that kind of system in TypeScript with LangGraph.js: state, memory, multi-step plans and several agents that hand work to each other without losing the thread.\n\nIt is book 4 of *AI in TypeScript*, a five-book series that runs from your first LLM call through to agents in production.", "url": "https://wpnews.pro/news/2000-agents-ported-prime-agent-to-rust-a-terminal-frame-diff-was-the-judge", "canonical_source": "https://dev.to/gabrielanhaia/2000-agents-ported-prime-agent-to-rust-a-terminal-frame-diff-was-the-judge-1o70", "published_at": "2026-10-19 22:01:24+00:00", "updated_at": "2026-10-19 22:15:21.521543+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools", "ai-infrastructure"], "entities": ["Prime Intellect", "Prime Agent", "Prime Sandboxes", "GLM-5.3", "Rust", "TypeScript", "tmux"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/2000-agents-ported-prime-agent-to-rust-a-terminal-frame-diff-was-the-judge", "markdown": "https://wpnews.pro/news/2000-agents-ported-prime-agent-to-rust-a-terminal-frame-diff-was-the-judge.md", "text": "https://wpnews.pro/news/2000-agents-ported-prime-agent-to-rust-a-terminal-frame-diff-was-the-judge.txt", "jsonld": "https://wpnews.pro/news/2000-agents-ported-prime-agent-to-rust-a-terminal-frame-diff-was-the-judge.jsonld"}}