Inside the Devin Harness: Two Loops and a Handoff
Devin now reaches you through four surfaces: a cloud agent, a terminal CLI, a desktop editor that used to be Windsurf, and a fleet API. You start the cloud agent from Slack or a ticket. Under all four there are only two harnesses. One loop runs on your machine, and the CLI and the desktop app share it. 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 the two.
This part of the series uses a different method. Pi, Codex and Kimi CLI are open source, so the earlier essays read their code. Devin is closed source. Everything here comes from Cognition's documentation, CLI reference and changelogs as published on September 24, 2026. I also use the few independent tests that exist. Where the docs describe behavior, I describe it, and where they say nothing, I say so.
Four surfaces, two loops
The product map changed a lot this year. Windsurf became Devin Desktop on June 2, 2026. Release 3.9.19 on September 8 made Devin Local "the only agent available in Devin Desktop" by removing Windsurf's old agent, Cascade. Two days later, 3.10.23 removed the remaining Cascade entry points and made the Agent Client Protocol always on. The editor is now a host for agents, where it used to be one agent with an editor around it. 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 the machine instead.
Before any session exists, Devin builds a snapshot. The environment docs call it "a frozen, bootable image that every session starts from": your cloned repositories, runtimes and dependencies. Each session boots a fresh copy, and 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. 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). Per the blueprint reference, its three core sections differ by when they run. The initialize section holds runtimes and system packages, and it runs on full builds and fresh workspaces. The maintenance section holds dependency installs and runs on every build. The knowledge section 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 you append variables that later steps and the session need 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. 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. The figure then shows which blueprint sections each workspace runs on the next build and what the next session 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 sits in an executable config file, yet Devin never executes it. Devin reads this text when it checks its own work. It says which command lints, which one tests a single file, and where the build output goes. In a cloud session, no human at the keyboard can tell Devin to run pnpm test -- file instead of 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 moving to Skills. A skill is a SKILL.md file that follows the open Agent Skills specification. Devin finds skills 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 playbook is a reusable prompt for one task type. You call it with 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 most useful of these. It answers the complaint reviewers raise most about autonomous agents, which is 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 puts model selection inside the harness, so the user does not pick a model for each 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". The sidekick is "a smaller, more efficient model that executes the lead's plan". You talk to one agent, and the split happens behind it.
Each model bills at its own rate, and /session-stats shows cost by model. The recommended pairing is Fable 5.1 as lead with Cognition's SWE-2 as sidekick. Fusion 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 one flat rate whatever model it picks. That rate is $0.50 per million input tokens, $2.00 per million output, and $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 what carries over: the repo and branch, the conversation context, and uncommitted changes ("Commit or stash anything you don't want sent"). The cloud session starts in a fresh VM, so everything else comes from cloud-side state. Tools and dependencies come from the snapshot, and credentials come 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 and switches your checkout to it. It then 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, and 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. On the return leg, the docs say the CLI fetches the PR branch, switches the checkout, and starts a local session on that code.
The figure gives a practical rule. Put anything the cloud session needs every time in the blueprint or the secret store, and keep it out of your shell. A handoff from a laptop where everything works can land in a VM where nothing installs. The cause is state that lived only 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 the docs warn 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 instead of by file. It flags moved and copied code, labels findings by confidence, and runs a security scan. You can trigger it on every PR event, on open, or when someone comments /devin review. Review reads REVIEW.md, AGENTS.md, CLAUDE.md and CONTRIBUTING.md at any directory level. So you can scope review rules 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. Both local surfaces can also spawn subagents defined as markdown files under agents/. These share tools and codebase context with the parent and 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 that field keeps a stuck session from grinding on:
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. The plans are 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. Your only hard ceilings are max_acu_limit in the cloud and the model choice locally.
What independent tests say
Three independent data points sit next to Cognition's own claims. Answer.AI gave Devin a month of real work and reported in January 2025. They wrote: "Out of 20 tasks we attempted, we saw 14 failures, 3 inconclusive results, and just 3 successes". They added that Devin "would spend days pursuing impossible solutions rather than recognizing fundamental blockers". That predates Devin 2.0 and every harness change above.
Artificial Analysis runs a Coding Agent Index, mirrored by BenchLM. On it, Devin's Fusion CLI configuration scores 61.7%, against 62.2% for Claude Code and 61.6% for Codex. Those are their numbers, each for the agent's best configuration. Scott Logic rebuilt a spreadsheet as a web app in seven days. The project used "around ≈155 ACUs and cost ≈$350" on the old pay-as-you-go plan. The engineer noted that "it was easy to start tasks without a clear sense of cost".
Across these reports, the harness performs level with the best local ones on bounded, checkable tasks. 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 on prompt order by volatility, Codex on compaction as a trained primitive, and Kimi on preserving thinking. Devin bets that the durable state of an autonomous agent is its environment, and that the environment should be a reviewed file. A reproducible image makes the rest possible. Sessions become disposable, fleets become cheap to start, and a second agent can review the first. A local loop can hand off to a cloud loop without shipping your laptop along.
In exchange, the transcript tools of the other harnesses, such as the cache meter and careful compaction, matter less here. The failure mode moves to setup, where a missing tool in the image looks like a bad model. If you adopt Devin, work in this order, which follows from the mechanism:
- Commit
.devin/blueprint.yamlwithinitialize,maintenanceandknowledgeentries for lint, test and build. Run one session to confirm it finds the commands without asking. - Before you rely on
/handoff, move anything your shell provides into the blueprint or the secret store. - Add a verification skill and a
REVIEW.md. Before you scale past one session, turn on Devin Review. - Work locally with Adaptive or Fusion. 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. Before you start a fleet, pilot one session. - On the CLI, run with
--sandbox. Once every machine can run it, have an admin set enforcement to Required.
I read these docs.devin.ai pages: environment, blueprint reference, differential builds, Skills, Playbooks, CLI Fusion, and Adaptive. I also read handoff, sandbox, Devin Local, Devin Review, API v3, and usage. Other sources are the Devin Desktop changelog, Cognition's pricing post, and the independent reports linked above. I read all of them on September 24, 2026.
Keep reading