Inside the Devin Harness: Two Loops and a Handoff
Devin now reaches you through four surfaces: a cloud agent you start from Slack or a ticket, a terminal CLI, a desktop editor that used to be Windsurf, and an API that runs fleets. Underneath there are only two harnesses. One loop runs on your machine and is shared by the CLI and the desktop app. The other runs in a virtual machine that boots every session from a frozen image. The interesting engineering sits in the second loop, and in the command that moves work between them.
A note on method, because this part of the series is different. Pi, Codex and Kimi CLI are open source, so the earlier essays read their code. Devin is closed. Everything here comes from Cognition's documentation, CLI reference and changelogs as published on September 24, 2026, plus the few independent tests that exist. Where the docs describe behavior, I describe it; where they are silent, I say so.
Four surfaces, two loops
The product map changed a lot this year. Windsurf became Devin Desktop on June 2, 2026. On September 8, release 3.9.19 removed Windsurf's old agent, Cascade: "Devin Local is now the only agent available in Devin Desktop." Two days later, 3.10.23 removed the remaining Cascade entry points and made the Agent Client Protocol always on, so the editor is now a host for agents rather than one agent with an editor around it. And the Devin Local page states the relationship plainly: Devin Local "is our next-generation agent harness shared with Devin CLI" (docs).
| Surface | Which loop | Where it runs | How you start it |
|---|---|---|---|
| Devin CLI | Local | Your terminal, your files | devin in a repo |
| Devin Desktop | Local (Devin Local) | Your machine, inside the editor | A new agent tab |
| Cloud session | Cloud | A VM booted from your snapshot | Web, Slack, Linear, Jira, GitHub, API |
| Fleet | Cloud, many at once | One VM per child session | A coordinating session, Automations, the API |
The local loop looks like the other harnesses in this series: files on disk, a permission system, subagents, a model picker. The cloud loop does not, and the reason is where it keeps state.
The snapshot is the unit of state
Every harness in this series treats the transcript as the thing to protect. Pi keeps its prefix stable for the cache. Codex compacts it with a trained summarizer. Kimi preserves thinking inside it. Devin's cloud loop protects something else: the machine.
Before any session exists, Devin builds a snapshot, which the environment docs call "a frozen, bootable image that every session starts from": your cloned repositories, runtimes and dependencies. Each session boots a fresh copy. Nothing a session does writes back. If Tuesday's session installs a missing package by hand, Wednesday's session does not have it. The transcript still matters within one session, but across sessions the durable state is the image, and the recipe for the image is a file you can review.
That file is the blueprint, a YAML recipe you can commit as .devin/blueprint.yaml (a git-backed blueprint). Its three core sections differ by when they run, per the blueprint reference: initialize for runtimes and system packages, run on full builds and fresh workspaces; maintenance for dependency installs, run on every build; and knowledge, which never runs at all.
.devin/blueprint.yaml · repository level
initialize:
- name: "Install Node.js 20"
uses: github.com/actions/setup-node@v4
with:
node-version: "20"
- name: "Install pnpm and system packages"
run: |
npm install -g pnpm
apt-get update && apt-get install -y jq
maintenance:
- name: "Private registry"
run: cp "$FILE_NPMRC" ~/.npmrc
- name: "Build-wide variables"
run: |
echo "NODE_OPTIONS=--max-old-space-size=4096" >> $ENVRC
- name: "Install dependencies"
run: pnpm install --frozen-lockfile
knowledge:
- name: lint
contents: |
pnpm lint
- name: test
contents: |
All tests: pnpm test
One file: pnpm test -- path/to/file.test.ts
- name: build
contents: |
pnpm build (output in dist/)
Three mechanics in that file follow from the image model. A plain export dies with its step's shell, so variables that later steps and the session need are appended to $ENVRC. Files attached to the blueprint arrive as $FILE_<NAME> (upload npmrc, read $FILE_NPMRC). Secrets set in the blueprint editor are injected before every step and "scrubbed from the snapshot image itself", so the image never holds a credential.
Builds are also differential. Snapshots rebuild when a blueprint changes and on a schedule, and the differential builds rules decide which workspace rebuilds and which inherits its parent image. That has a sharp edge: a workspace that inherits skips initialize, and $ENVRC is reset every build, so a variable written from initialize silently vanishes on the next ordinary code push. The figure plays those rules out.
One org blueprint and two repositories. Pick what just changed and see which blueprint sections each workspace runs on the next build, and what the session after it boots with. Rules are from the differential builds page.
What changed
Next session boots with
A workspace rebuilds when the digest of its blueprint, attached files, or secrets changes. The 7-day full-build refresh is the default and is configurable in the environment settings.
The knowledge section is a verification contract
The knowledge section is the most interesting line in the schema, because it is executable configuration that is never executed. It is reference text Devin reads when it checks its own work: which command lints, which one tests a single file, where the build output goes. A cloud session has no human at the keyboard to say "run the tests with pnpm test -- file, not npm test." The blueprint says it once, for every session.
The same idea extends to procedure. Knowledge, the older mechanism for standing instructions, is marked deprecated in the docs and is being migrated to Skills: SKILL.md files that follow the open Agent Skills specification, found in several directories including .agents/skills/, .claude/skills/ and .github/skills/ (Skills docs). At session start Devin sees only each skill's name and description, and loads the body when it invokes the skill. So the description has to say when to use it:
.agents/skills/verify-before-pr/SKILL.md
---
name: verify-before-pr
description: Run before opening any pull request that touches packages/web. Lints, tests the changed files, builds, and checks the pages in a browser.
---
## Verify
1. Run `pnpm lint` and fix every error you introduced. Do not disable rules.
2. Run `pnpm test -- <each changed test file>`, then the full `pnpm test`.
3. Run `pnpm build`. A build warning you introduced counts as a failure.
4. Start `pnpm dev`, open every page whose files changed, and screenshot it at 1280px and 375px.
## Open the PR
1. Include the screenshots and the exact test commands you ran.
2. List any file you changed outside the task's scope, and why.
Playbooks sit one level down: a reusable prompt for one task type, called by a macro such as !rtl-migrate from Slack, a Linear label, or the API (Playbooks docs). The docs suggest sections for Procedure, Specifications, Advice, Forbidden Actions and Required from User. Forbidden Actions is the one that earns its place, because it answers the complaint reviewers raise most about autonomous agents, edits beyond the task:
Forbidden Actions
- Do not delete, skip or weaken a test to make it pass.
- Do not touch jest.config.ts or shared test utilities.
- Do not modify any file outside the test file you were given.
Read together, blueprint, skill and playbook are a harness design choice. The local harnesses in this series keep their standing instructions in AGENTS.md or CLAUDE.md, loaded into every prompt. Devin splits them by lifetime: the environment in the image, the procedure in a lazily loaded skill, the task shape in a playbook.
Routing lives inside the harness
The second design choice is that model selection is a harness feature, not a user decision per request. The local loop offers two routers.
Fusion pairs two models in one session. Per the Fusion docs, the lead is "a frontier model that drives planning, design decisions, investigations, and correctness-critical work", and the sidekick is "a smaller, more efficient model that executes the lead's plan". You talk to one agent; the split happens behind it. Each model bills at its own rate, the recommended pairing is Fable 5.1 as lead with Cognition's SWE-2 as sidekick, and /session-stats shows cost by model. It needs a paid plan and CLI 3000.10.20 or Desktop 3.10.0.
Adaptive routes each prompt: "Simple tasks get routed to fast, efficient models. Complex tasks get routed to more capable ones" (Adaptive docs). On self-serve plans it bills a flat rate whatever it picks: $0.50 per million input tokens, $2.00 per million output, $0.10 per million cache reads. The docs add that it considers caching when routing, since staying on one model across turns keeps the cached prefix alive. You can make it the default in the CLI config:
~/.config/devin/config.json
{
"agent": {
"model": "adaptive"
}
}
# or per session
devin --model adaptive
/model adaptive # switch inside a session
/fusion # pick lead, effort and sidekick
/session-stats # tokens and cost by model
The cloud loop exposes the same choice as a session mode. The create-session schema accepts normal, fast, lite, ultra and fusion. Cognition announced SWE-2 on September 10 and put it into Devin as a research preview on September 21.
Compare that with Pi, the first essay in this series, whose central idea is showing you the cache meter so you can manage it. Adaptive takes the opposite position: a flat price, with the router responsible for keeping the cache warm. Whether that is a better deal depends on your mix, and the flat rate is at least a number you can plan against.
The handoff is the seam
Two loops need a bridge, and Devin's is one command. From a CLI session, /handoff creates a cloud session that continues the work (handoff docs):
curl -fsSL https://cli.devin.ai/install.sh | bash
# inside a CLI session, when the job needs a VM, a browser, or hours:
/handoff fix the flaky integration tests in CI
# with no description, the cloud session continues where you stopped
/handoff
The docs list exactly what carries over: the repo and branch, the conversation context, and your uncommitted changes ("Commit or stash anything you don't want sent"). The cloud session starts in a fresh VM, so everything else comes from the other loop's state: tools and dependencies from the snapshot, credentials from Devin's secret store. Your terminal's exported variables and your local node_modules are not on the list. The command also runs backward: in a cloud session started with devin --cloud, /handoff fetches the session's pull request branch, switches your checkout to it, and starts a local session on that code. Cognition also publishes a handoff plugin so Claude Code, Codex or Cursor sessions can hand work to a cloud Devin the same way.
A CLI session on feat/billing-dates hands a task to the cloud, then pulls the pull request back. Rows are the named pieces of state; columns are the three stops. Flip the two settings to see what the cloud session has when it boots.
Carried items are the three the handoff docs list. Everything else in the cloud column follows from the VM booting from the snapshot and secrets being injected. The return leg per the docs: fetch the PR branch, switch the checkout, start a local session on that code.
The practical rule falls out of the figure: anything the cloud session needs every time belongs in the blueprint or the secret store, never in your shell. A handoff from a laptop where everything works can land in a VM where nothing installs, and the cause is state that lived on the laptop.
Isolation, two ways
The cloud loop isolates by construction: one VM per session, booted fresh, secrets injected and absent from the image. The local loop has to isolate on your machine, and the CLI's --sandbox flag does it at the OS level (sandbox docs). Writable paths are the workspace plus granted Write(...) scopes; paths under a Read(...) deny rule are hidden from sandboxed commands for the whole session. It fails closed: "If sandbox resolution fails ... the CLI will refuse to start rather than running unsandboxed." Linux needs bubblewrap and socat; Windows is not supported yet, and sessions there hard-fail when the sandbox is required. Network filtering by domain exists but carries a warning in the docs that it is "currently unstable".
Some commands legitimately need to leave the sandbox, usually git reaching credentials or hooks. The config expresses that with the same rule syntax as permissions, and the most restrictive verdict wins when user and team settings disagree:
~/.config/devin/config.json · sandbox
{
"sandbox": {
"excluded": {
"allow": ["Exec(git status *)"],
"ask": ["Exec(git push *)"],
"deny": ["Exec(git tag *)"]
}
}
}
Enterprise admins can set sandbox enforcement to Required for everyone. Codex, the third essay in this series, made the same bet on refusing to run unsandboxed. Devin Local inherits the sandbox because it is the same harness as the CLI.
Review is another agent, and so is the fleet
In the cloud loop, the reviewer is not the author. Devin Review reads a pull request grouped by logic rather than by file, flags moved and copied code, labels findings by confidence, runs a security scan, and can run on every PR event, on open, or when someone comments /devin review. It reads REVIEW.md, AGENTS.md, CLAUDE.md and CONTRIBUTING.md at any directory level, so review rules can be scoped per folder:
REVIEW.md · repository root
# Review guidelines
## Block the merge for
- Any change under src/payments/ or src/auth/ without a test that exercises it.
- A test that was deleted, skipped, or had its assertion loosened.
- Edits outside the directories the PR title names.
## Ignore
- src/generated/ and lockfiles, unless package.json changed.
The local loop has its own version: Devin Local ships a Quick Review subagent, and both local surfaces can spawn subagents defined as markdown files under agents/, which share tools and codebase context with the parent but keep their own conversation chain. In the cloud, the equivalent is a fleet. A coordinating session starts managed Devins, each a child session in its own VM, with its own prompt, playbook, tags and compute limit. The same limit is available when you start sessions from code, and it is the field that keeps a stuck session from grinding:
curl -X POST "https://api.devin.ai/v3/organizations/$DEVIN_ORG_ID/sessions" \
-H "Authorization: Bearer $DEVIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Migrate packages/web/src/cart/__tests__/CartRow.test.tsx to RTL.",
"playbook_id": "'"$RTL_PLAYBOOK_ID"'",
"devin_mode": "normal",
"max_acu_limit": 10,
"tags": ["rtl-migration", "batch-3"]
}'
The response carries a session id, a URL, a status, and acus_consumed, so a script can poll and total spend by tag.
The meter
Self-serve billing changed on April 14, 2026: Free, Pro at $20 a month, Max at $200, and Teams at an $80 monthly minimum with $40 full seats. Enterprise is still billed in ACUs at a contracted rate. The usage docs say what accrues: the number and complexity of Devin's actions, plus a small share of VM time. Waiting on your reply or on a test run costs almost nothing, and idle sessions sleep after 30 minutes by default. Cognition does not publish the Pro or Max quotas as numbers, so the only hard ceilings you control are max_acu_limit in the cloud and the model choice locally.
What independent tests say
Three data points are worth holding next to Cognition's own claims. Answer.AI gave Devin a month of real work and reported in January 2025: "Out of 20 tasks we attempted, we saw 14 failures, 3 inconclusive results, and just 3 successes", adding that Devin "would spend days pursuing impossible solutions rather than recognizing fundamental blockers". That predates Devin 2.0 and every harness change above. On Artificial Analysis's Coding Agent Index, as mirrored by BenchLM, Devin's Fusion CLI configuration scores 61.7%, against 62.2% for Claude Code and 61.6% for Codex (their numbers, each agent's best configuration). And Scott Logic's seven-day rebuild of a spreadsheet as a web app used "around ≈155 ACUs and cost ≈$350" on the old pay-as-you-go plan, with the engineer noting "it was easy to start tasks without a clear sense of cost".
Read together: on bounded, checkable tasks the harness performs level with the best local ones, and on open-ended work it can burn time and money without noticing it is stuck. Cognition's own guidance draws the same line: "if a task would take you three hours or less, Devin can most likely do it."
What it teaches
Each harness in this series made one bet the others did not. Pi bet on showing the meter. Claude Code bet on ordering the prompt by volatility. Codex bet on compaction as a trained primitive. Kimi bet on preserving thinking. Devin's bet is that the durable state of an autonomous agent is its environment, not its transcript, and that the environment should be a reviewed file. Once the image is reproducible, the rest follows: sessions can be thrown away, fleets are cheap to start, a second agent can review the first, and a local loop can hand off to a cloud loop without shipping your laptop along.
The cost of that bet is that the transcript-centric tools of the other harnesses, the cache meter and the careful compaction, matter less here, and the failure mode moves to setup: a missing tool in the image looks like a bad model. If you adopt it, the order that follows from the mechanism is:
- Commit
.devin/blueprint.yamlwithinitialize,maintenanceandknowledgeentries for lint, test and build, and run one session to confirm it finds the commands without asking. - Move anything your shell provides into the blueprint or the secret store before you rely on
/handoff. - Add a verification skill and a
REVIEW.md, and turn on Devin Review before you scale past one session. - Work locally with Adaptive or Fusion, and hand off only when the task needs a VM, a browser, or hours.
- Start every cloud session from code or a coordinator with
max_acu_limitand tags, and pilot one session before a fleet. - On the CLI, run with
--sandbox, and have an admin set enforcement to Required once every machine can run it.
Sources: docs.devin.ai (environment, blueprint reference, differential builds, Skills, Playbooks, CLI Fusion, Adaptive, handoff, sandbox, Devin Local, Devin Review, API v3, usage), the Devin Desktop changelog, Cognition's pricing post, and the independent reports linked above, all read on September 24, 2026.
Keep reading