October 20, 2026
Building Miro’s Software Factory
Andrew Eacott (Sr. Principal Engineer), Cole Hoffer (Sr. Staff Engineer), Ben Kramer (Head of Engineering)
AI can complete a task. Making it a dependable part of everyday engineering takes more work. At Miro, we built Easel so teams could delegate code reviews, alert investigations, and repository changes without maintaining their own agent infrastructure. Nearly 48,000 runs later, it has reviewed more than 6,300 pull requests across 115 repositories and authored more than 800. A small platform team took Easel from inception to company-wide availability in about two months. Teams across Miro are now bringing their own workflows to the factory, expanding what it can do without rebuilding the infrastructure underneath.
AI can complete a task. A software factory turns that capability into a dependable way to build and operate software.
At Miro, engineers were solving the same problem in parallel: standing up bots, writing local automations, and building bespoke agent orchestrators. The use cases differed, but the infrastructure they needed kept repeating.
One-off agents are easy to demo and hard to operate at scale. Work arrives from people, repositories, CI events, and schedules. Each task needs different tools, permissions, runtimes, and output formats. Without a shared foundation, teams build the orchestration themselves—and inherit the hidden state, security gaps, duplicate work, and delivery failures that come with it.
We built Easel to make that foundation shared. It accepts work from Slack, GitHub, Jira, schedules, and APIs, authenticates the request, and records an explicit execution contract. It then runs the task in a clean, ephemeral sandbox, captures a validated result, and returns it to the originator.
A small platform team took Easel from inception to company-wide availability at Miro in about two months. Agents produced the production code; engineers set direction and reviewed the system as it developed. Since its first internal production run in June, Easel has executed nearly 48,000 runs, including more than 14,000 automated and scheduled runs. It has reviewed more than 6,300 pull requests across 115 repositories and authored more than 800 across 85 repositories.
Teams then began self-onboarding use cases the platform group had not anticipated. A successful local workflow could become a reusable capability without its team having to build and maintain another agent platform. Engineers could delegate work from the tools they already used, while improvements to the shared infrastructure benefited the workflows running on it.
That changes the economics of experimentation. Teams can test new use cases quickly, keep the ones that prove useful, and spend less time maintaining one-off infrastructure for each idea.
Usage figures reflect lifetime production activity, including internal evaluations, through October 16, 2026; workload categories overlap.
What the factory produces today
Easel supports several kinds of engineering work on the same execution system.
It can review a pull request and return findings directly to GitHub. It can triage service alerts, investigate production symptoms, prepare repository changes, run maintenance jobs, and answer ad hoc questions from Slack.
Across overlapping lifetime cohorts, Easel has handled more than 13,400 Slack entry points, more than 7,800 AI code review findings, about 9,200 operational-triage jobs, and more than 4,800 pull-request maintenance runs. Automated and scheduled work accounts for more than 14,000 runs.
These workloads do not run as a collection of independent bots. They share infrastructure for ingress, identity, policy, isolation, execution, artifact validation, and delivery, giving each new use case the same operating foundation.
Once agents move from demonstrations into production, the central problem is not whether a model can generate code or reason about an alert. The important question is how thousands of pieces of delegated work can execute safely, reproducibly, and usefully without requiring a bespoke integration for each new use case. The rest of this article follows one run through the system we built to answer that question.

Easel runs start with an explicit contract
A request can begin in Slack, on a pull request, through an API or MCP client, or on a schedule. Those surfaces look different to the person asking for work. Easel turns them into the same execution contract.
Before work begins, Easel creates an immutable RunSpec. It records the declared repository, the runtime bundle and image, the tools and credentials the job may use, the artifact it must produce, and where that artifact should go. A runtime bundle is the versioned set of instructions, skills, and configuration selected for a task.
A prompt describes what someone wants; the RunSpec records what the system has agreed to execute. Capturing that agreement at ingress keeps retries and clarification turns attached to the same contract, so the worker does not reinterpret destination or output policy halfway through a run.
Since Easel’s first production run, more than 31,500 runs have been repository-scoped. Those runs carried a declared repository, runtime bundle, and image reference into execution. The current system also freezes the output contract before compute is allocated.

Execution starts after the contract is complete.
The RunSpec records the execution boundary: who may act, any declared repository, the runtime bundle and image, the expected artifact, and its destination before compute is allocated. Retries inherit that contract instead of reinterpreting the original request.
Each job gets a clean room
The accepted RunSpec becomes a running workload inside a fresh, isolated, ephemeral sandbox. The sandbox starts from a versioned image, receives the selected runtime bundle, and gets the tools and credentials selected for that job.
This clean-room model removes hidden state from the engineer’s laptop and from previous jobs. A repository starts from the requested revision. Tools arrive through the selected runtime bundle. Credentials are injected for the life of the run and removed with the sandbox.
The control plane owns the boring but essential work around the agent: provisioning, bundle delivery, credential injection, heartbeats, lifecycle records, and teardown. Across more than 46,500 runs with complete lifecycle data, the median time from provisioning started to sandbox ready was 17.6 seconds.
Models are useful because they are general, but production use requires the surrounding system to give that capability a precise boundary. Isolation controls what each job can touch and limits how far failures can spread, while lifecycle records make those boundaries visible.

The workspace is temporary. The evidence is not.
The control plane provisions an isolated checkout, selects the harness, limits tool access, and captures the resulting artifact and trace. The room can disappear after the run because the evidence needed to inspect it survives.
Keeping sandboxes observable
Easel runs agents in Kata Containers on shared Kubernetes. The runtime, harness, model, and task can vary, but the platform contract makes runs observable in the same way.
Each sandbox follows an agent contract protocol for real-time, two-way communication with the control plane. The protocol is stable even when the implementation inside the sandbox changes.
Harness bridges translate control-plane messages into harness-specific instructions. In the other direction, they capture streamed harness output and normalize it into a common event model.
The control plane persists normalized event streams for tasks, allowing engineers to reconstruct what an agent received, discovered, struggled with, and produced. The record supports security and audit work, everyday troubleshooting, and a feedback loop in which Easel agents analyze prior runs and propose evidence-backed changes to the platform. The team reviews and merges those changes through the normal engineering process.

Different harnesses. One observable protocol.
The bridge translates harness-specific instructions and output into a stable event stream. That record makes each run inspectable, helps engineers diagnose failures, and gives Easel evidence it can use to improve itself.
The output is evidence, not a vibe
A production agent should leave behind more than a convincing final message. Its result should be typed, inspectable, and useful to the system that requested the work.
Easel separates the execution transcript from the promised output. The transcript is a chronological record of model turns, tool calls, status changes, and errors. The output artifact is the durable result: a report, structured payload, assistant message, or summary.
Since launch, Easel has assigned runs to four durable output forms, each selected before execution:
- 27,000+ reports
- 15,800+ structured results
- 3,300+ assistant messages
- 150+ summaries
AI code review shows why this matters. More than 6,700 durable review records cover more than 6,300 pull requests in 115 repositories, with more than 7,800 findings and more than 2,800 records with no recorded findings. Easel has also authored more than 800 pull requests across 85 repositories, leaving a durable account of what it found and changed.
The harness is part of the product
Easel is not coupled to a single proprietary coding runtime. Our custom agent harness, built on pi, runs through the same lifecycle, policy, authorization, observability, artifact, and delivery machinery that we originally established for Claude Code.
That separation lets us choose the strongest combination of harness and model for each workload. It also gives us a practical way to compare execution paths through offline replay, move suitable presets one at a time, and roll back without changing the factory around them.
In a controlled shadow AI code review evaluation, we compared our pi harness with Claude Code using the same Sonnet 4.6 baseline. Across a large and diverse set of historical pull requests, manual non-blinded adjudication found no overall quality winner between the harnesses. Reviewers judged each output against the changed source and original review request, prioritizing blocking correctness, material coverage, and false-positive control before severity calibration, actionability, instruction adherence, and presentation. A better-written review could not win by glossing over a correctness or coverage gap. In this evaluation, the pi harness used fewer tokens and turns, lowered cost, and completed work faster.
That is the result we care about: comparable quality with better execution economics, plus the freedom to improve the harness independently of the model. We still evaluate each workload separately and keep Claude Code available when it is the stronger fit.

Same model. Different execution profile.
Same model, different harness. Manual adjudication across a large and diverse set of historical pull requests found no overall quality winner. In this evaluation, the pi harness used fewer resources, with Claude Code as the 100% baseline.
The goal is repeatable engineering work
For us, the useful unit of AI engineering is a bounded piece of work with a clear contract, isolated execution, an observable run history, and inspectable evidence, not simply a model response.
Easel gives teams a shared way to produce that work. They can introduce new entry points, capabilities, models, and harnesses without rebuilding authorization, execution, observability, and result handling each time, so a workflow that succeeds locally can become infrastructure the rest of the organization can reuse.
That is where we are continuing to invest: making useful agent workflows easier for other teams to adopt, operate, and improve.