Skip to main content

Devin Outposts: Cognition Shipped a Kubernetes Operator Instead of a Bigger Cloud

8 min readDora NodaDora Noda
Share
On this page

Every AI coding agent vendor has the same pitch: send us your repo, we'll run the agent in our cloud, you get pull requests back. Cognition just shipped the opposite of that pitch for Devin. Devin Outposts keeps the expensive part — the model doing the reasoning — in Cognition's cloud, and moves the part that actually touches your systems — every shell command, file edit, and repository operation — onto machines you own. And instead of asking customers to hand-roll that split themselves, Cognition open-sourced a Kubernetes operator, devin-outpost-k8s, that runs it as a native workload on any CAPI-provisioned cluster.

That's a specific, checkable architectural choice, not a marketing line. Here's exactly what Outposts is, what the operator actually deploys, and what a Cluster-API-managed fleet — bex included — would need to add to run Outposts workers as just another workload instead of a bolt-on VM pool.

The split: inference stays remote, execution comes home

Outposts separates Devin's agent loop from its hands. Planning and inference — the actual LLM calls that decide what to do next — continue to run in Cognition's cloud. Everything with side effects — running a shell command, editing a file, cloning a repo, calling an internal service — executes on a "worker" process running on infrastructure the customer operates: a Mac mini, a GPU box in a lab, a VM inside a private VPC, or a pod on a Kubernetes cluster.

The connection between the two is deliberately narrow. A worker opens an outbound HTTPS/WebSocket connection to Cognition's outpost gateway and watches a named queue for work; when a session is waiting, the worker claims it, executes the session's tool calls locally, and goes back to watching the queue when the session ends. Nothing needs to open inbound — no public IP, no listening port, no VPN tunnel into the customer's network. Scaling is just running the worker on more machines: N workers serve N concurrent sessions, and anything beyond that capacity queues until a worker frees up.

That's a genuinely different trust boundary than "upload your code to our sandbox." The reasoning model still sees your code and your terminal output over the wire — Outposts doesn't change what Cognition's cloud can observe — but the credentials, the internal network access, and the actual command execution never leave infrastructure you control. For a team that can't ship customer data or proprietary source off-premises even transiently, or that wants Devin sitting inside a VPC next to services it's not allowed to reach from the public internet, that's the difference between "no" and "yes, on our terms."

What the operator actually ships

devin-outpost-k8s is Cognition's reference implementation of a worker fleet as a Kubernetes-native resource, and it's a small, legible surface:

  • One CRD: OutpostPool. You declare a pool (how many workers, what image, what resource limits) as a Kubernetes object, and the operator's reconciliation loop keeps a running worker fleet matched to that declaration — the same declarative pattern Cluster API itself uses for Machine and MachineDeployment objects, just one layer up the stack, managing pods instead of nodes.
  • A Helm chart (charts/devin-outposts-k8s) with two install paths: a bundled mode that installs the operator, the CRD, and a default pool in one shot (flags for defaultPool.enabled and poolId), or an operator-only mode where you apply OutpostPool manifests yourself.
  • Token-based auth: workers authenticate with a service-account personal access token (cog_...) generated once in the Devin web app under Settings → Environment → Outposts, then stored as a standard Kubernetes Secret (kubectl create secret generic my-pool-token --from-literal=token=<PAT>) and referenced by the pool.
  • Runtime dependencies baked into the worker image contract: git is required; FFmpeg (screen recording) and Chrome/Chromium (browser and computer-use tool calls) are optional; passwordless sudo is optional but explicitly flagged by Cognition's own docs as risky on a shared machine.

Cognition is upfront that this operator ships as a reference implementation, not a fully supported product — the repo's own README notes it isn't covered by the same support tier as the rest of Devin, and deploying it in an enterprise context means looping in your account team. That's a reasonable caveat for a v1 integration, but it also means the CRD surface, the reconciliation behavior under node pressure, and upgrade compatibility are all things a team adopting it should expect to verify themselves rather than assume.

Why an operator, and not just a bigger cloud

The interesting decision here isn't that Cognition built BYOC support — Namespace, Modal, NVIDIA Brev, Daytona, E2B, and Cloudflare all already run Outposts workers on their own sandbox infrastructure, which tells you Cognition designed Outposts as a protocol other platforms could implement against, not a single closed integration. The interesting decision is that Cognition chose to ship a Kubernetes operator as one of the first-class ways to run it, rather than leaving "run our worker binary on your infra" as a bare shell command a platform team has to wire up by hand.

That choice matters for two reasons. First, it's an admission that the actual demand isn't "run Devin somewhere," it's "run Devin next to the internal services, secrets, and network boundaries we already manage with Kubernetes primitives" — RBAC, namespaces, network policies, existing GitOps pipelines. A shell command doesn't compose with any of that; a CRD does. Second, it puts the operational burden where a platform team already has tooling to absorb it: pool sizing, secret rotation, and worker lifecycle become one more object type reconciled by controllers a Kubernetes-native team already runs, instead of a snowflake VM someone has to remember exists.

Cognition's own docs are candid about the tradeoff this shifts onto the customer: "provisioning, isolation, access controls, capacity management, monitoring, and recovery" of the worker fleet become the customer's job, not Cognition's. For a team without a Kubernetes platform already in place, that's a real cost. For a team that already runs one — which is exactly bex's target user — it's close to free, because the machinery for reconciling a declared pool state against a running fleet already exists on the cluster.

What a Cluster-API fleet needs to add

A Cluster-API-managed platform like bex already runs its own CRDs and controllers reconciling tenant workloads onto Hetzner nodes via CAPH. Hosting OutpostPool as just another workload on top of that — rather than as a special-cased VM sitting outside the fleet's normal lifecycle — is mostly additive, not architecturally new work, but it's not zero work either:

  • Node pool headroom, sized by concurrency, not by request rate. Because one worker serves exactly one concurrent session — N workers, N sessions, everything past that queues — a pool's size is a direct, provisionable capacity number rather than something an autoscaler has to infer from request volume. That's a simpler sizing problem than typical HTTP-traffic autoscaling, but it means under-provisioning shows up immediately as queued Devin sessions rather than degraded latency, which is a different failure mode a platform team needs to alert on.
  • Egress-only network policy, which CAPH's Hetzner private-network defaults already assume. Outposts workers need outbound HTTPS/WebSocket and nothing inbound — that maps cleanly onto a fleet that already runs tenant workloads behind private networking with no public ingress by default. No new firewall posture required, just confirming the pool's namespace doesn't accidentally get a broader egress allowlist than the worker needs.
  • Secret handling folded into the fleet's existing tenant-secret story, not a one-off kubectl create secret a human runs by hand. The PAT is long-lived and shown once at creation — treating it like any other tenant credential (rotation policy, least-privilege scoping to one pool) rather than a static value pasted into a manifest is the gap between the quickstart and something safe to run multi-tenant.
  • Resource requests sized for bursty, not steady-state, load. A worker sits mostly idle watching a queue, then spikes to real CPU/memory usage — running builds, tests, browser automation — for the duration of a claimed session. Static resource requests sized for the idle case will get sessions OOM-killed mid-task; sized for the peak case, they waste capacity across every idle worker. This is a genuinely different bin-packing profile than a typical stateless web service, and it's the one piece of the four that doesn't have an off-the-shelf answer yet.
  • No conflict with Cluster API's own reconciliation loop, because they operate at different layers. CAPI's Machine/MachineDeployment controllers manage node lifecycle; OutpostPool's controller manages pods on top of nodes that already exist. Running both on the same management cluster is additive — one more controller watching one more CRD — not a competing control plane fighting over the same resources.

None of that is exotic. It's the same category of work bex already does for every tenant workload it schedules — pool sizing, network policy, secret scoping, resource tuning — applied to one more workload type. That's arguably the actual point of building on Cluster API in the first place: a new class of workload showing up doesn't mean a new architecture, it means one more CRD reconciled by the same fleet.

Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own, with AI agents as first-class operators of the platform's own API. Star the repo on GitHub or deploy your first app today.

Sources

Related articles

Give your agents a chain backend

Autonomous agents hit RPC endpoints very differently than people do. See what bex router handles on their behalf.

Read the agents guide