When coding agents first became useful, I made the same mistake many engineers make: I invested in the space around the model.

The agents were capable, but they could not reliably manage a large job. So I built a task queue. I decomposed work into atomic tasks and fed them to a coding CLI one by one. It worked. More importantly, it stopped me from sitting in front of a terminal all day waiting to submit the next prompt.

Two weeks later, the product added its own task queue.

I kept going. I built more orchestration around the agents and connected them to a small remote instrument setup. The goal was natural-language test automation: ask for a measurement, let the system operate the bench, and receive a report.

Then agent platforms gained native scheduling, tool use, remote execution, and richer workflows. Once again, much of my orchestration layer became redundant.

That experience changed how I think about AI engineering:

Do not build your moat at the edge of the model. If an orchestration idea is broadly useful, the model vendor will probably absorb it. Build the part the model can never own: your project knowledge, your engineering constraints, your proven procedures, and your physical test environment.

For embedded development, I call that durable layer the AI Harness.

The Harness Is More Than Test Automation

In traditional engineering, a test harness is the machinery around a system under test: fixtures, drivers, stimuli, measurements, and assertions. An AI Harness expands that idea to the entire development system.

It gives an agent enough context to make a change, enough capability to execute it, and enough evidence to decide whether the change actually works.

flowchart TB Human["Engineer
goals, trade-offs, acceptance"] Agent["AI agent
plan, change, diagnose"] subgraph Harness["Project-level AI Harness"] Knowledge["Knowledge
Git history, project context, specs"] Skills["Skills
proven procedures and constraints"] Tools["Tools and interfaces
build, flash, debug, test"] Lab["Programmable lab
board, UART, scope, relays, loads"] Evidence["Evidence
tests, logs, waveforms, reports"] end Human --> Agent Agent --> Knowledge Agent --> Skills Skills --> Tools Tools --> Lab Lab --> Evidence Evidence --> Agent Agent --> Human

The diagram matters because the agent is only one component. A stronger model improves the reasoning box, but it does not automatically know your system contract, connect to your instruments, interpret target-specific behavior, or decide what evidence is sufficient for release.

The Harness supplies those missing pieces.

Five Assets That Compound

My current model of a Harness has five parts. None is particularly exotic. The leverage comes from connecting them.

1. Git history as engineering memory

A repository is already a structured knowledge system. It contains versions, branches, reviews, and the reasons recorded in commit messages.

During debugging, an agent can use that history much like an experienced engineer:

  • identify the last known-good revision;
  • reproduce the behavior on old and new revisions;
  • isolate the relevant diff;
  • test a root-cause fix rather than add another patch.

This only works when the history is trustworthy. Small commits, meaningful messages, and reproducible revisions are no longer just team hygiene. They are machine-readable debugging infrastructure.

2. Markdown as an executable contract

A longer prompt is not a substitute for a project model.

I prefer to keep a concise project-context document in the repository. The filename is not important; its job is to describe the current system rather than an aspirational roadmap:

  • product scope and non-goals;
  • system topology;
  • component responsibilities;
  • protocol and safety boundaries;
  • terminology;
  • key source anchors;
  • build and test commands;
  • acceptance criteria.

Requirements, plans, task cards, and runbooks also live as versioned Markdown. The important shift is to treat these documents as inputs to execution, not as documentation written after implementation.

The sequence becomes:

requirement → acceptance criteria → plan → atomic tasks → implementation → evidence

If the system contract changes, update the contract before asking the agent to change the code. This makes inconsistency visible and reviewable.

3. Skills as experience encoded

A successful debugging session is valuable once. A reusable procedure is valuable every time the problem class returns.

I use Skill to mean a callable engineering procedure with:

  • a clear trigger;
  • required inputs;
  • an ordered sequence of actions;
  • allowed tools and safety limits;
  • explicit completion checks;
  • known anti-patterns and failure paths.

For example, an embedded driver skill might require the agent to read the register specification, draft the interface contract, implement the driver, add host-side tests, build the target, flash a board, capture UART output, and update the project pack. Each step has a success condition.

That is very different from a wiki page titled “How We Usually Add Drivers.” A wiki page transfers information to a person. A Skill constrains the next execution.

Some Skills can be shared across many repositories, such as language style, commit policy, release rules, or audit format. Others remain local, such as how to enter a bootloader, recover a target, or reproduce a device-specific failure.

4. Tools as stable capabilities

Agents need reliable interfaces to the existing toolchain:

  • compiler and linker;
  • programmer and flash utility;
  • debugger and GDB server;
  • static analysis;
  • unit and integration tests;
  • issue tracker and CI;
  • instrument-control libraries.

Whether the interface is a CLI, Python module, API, or MCP server is less important than its contract. The agent should receive structured results, meaningful exit codes, timeouts, and enough diagnostic output to choose the next action.

A tool that prints “failed” is weak. A tool that reports the command, target identity, firmware hash, failure stage, and captured log is part of an engineering Harness.

5. Infrastructure as physical leverage

This is where embedded development differs from most software work.

The board and instruments must become programmable:

  • UART or RTT capture;
  • a programmer and debugger;
  • oscilloscopes and logic analyzers;
  • power supplies and electronic loads;
  • protocol analyzers;
  • relay matrices and port switchers;
  • cameras when visual state matters.

The goal is not remote button clicking. The goal is deterministic control and machine-readable evidence.

A relay action should have a named channel and a verified state. A flash operation should record the image hash and target. A scope capture should include configuration and timestamps. A power test needs current limits and an abort policy.

Once these interfaces exist, the agent can participate in the same feedback loop as a firmware engineer.

From Code Generation to Closed-Loop Engineering

The common description of AI-assisted development is “the model writes code.” That is the least interesting part.

The real change is that an agent can now traverse the whole engineering loop:

sequenceDiagram actor E as Engineer participant A as AI Agent participant R as Repository participant T as Toolchain participant H as Hardware Harness E->>A: Goal and acceptance criteria A->>R: Read project contract, code, and history A->>A: Plan atomic tasks and risks A->>R: Implement a bounded change A->>T: Build and run static or host tests T-->>A: Diagnostics and test evidence A->>H: Flash, stimulate, and capture H-->>A: UART logs, measurements, waveforms alt Acceptance criteria fail A->>R: Diagnose from evidence and revise else Acceptance criteria pass A->>R: Update docs and prepare review A-->>E: Change, evidence, and residual risks end

I have watched an agent add temporary log points, print state and voltage information, reproduce a failure, modify the implementation, retest it, and then remove the temporary instrumentation. That is recognizable engineering behavior.

But it becomes trustworthy only when the loop is bounded. The Harness must define:

  • what the agent may energize or switch;
  • current, voltage, temperature, and time limits;
  • which actions require human approval;
  • how to return the bench to a safe state;
  • what constitutes a pass;
  • when to stop iterating and escalate.

Autonomy without an acceptance protocol is just unattended experimentation.

Execution Loop and Learning Loop

A useful Harness runs two loops.

The execution loop gets one task done:

  1. converge the problem;
  2. freeze the intended behavior;
  3. split the work into atomic tasks;
  4. implement;
  5. audit;
  6. validate on the appropriate target.

The learning loop makes the next task cheaper:

  1. retain useful success and failure evidence;
  2. identify the recurring pattern;
  3. encode the procedure as a Skill, test, template, or tool improvement;
  4. review it;
  5. reuse it;
  6. measure where it still fails.

This is how tokens become assets. The objective is not to use fewer tokens. It is to prevent expensive reasoning from disappearing inside a chat transcript.

If a model spends an hour discovering a reliable recovery sequence for a locked board, the durable output is not the conversation. It is the recovery Skill, the timeout added to the flashing tool, the new test fixture, and the evidence attached to the commit.

The more often that asset is reused, the lower its effective cost.

Why I Use Multiple Models for Audits

One model can plan, implement, and review its own work, but those roles still share blind spots. Telling the same model to “act as a skeptical reviewer” does not create genuine independence.

For higher-risk changes, I prefer multiple model families or agent CLIs to inspect the same frozen source and the same audit contract independently. Each finding must point to code, a specification, or reproducible behavior.

Agreement raises confidence. Disagreement identifies a path that deserves human attention.

This is not voting. Three unsupported opinions are still unsupported. The unit of value is evidence.

The same rule applies to the final change: a clean build is evidence for buildability, a host test is evidence for logic under simulation, and a hardware trace is evidence for behavior on that board under those conditions. They are not interchangeable.

A Practical Adoption Path

You do not need to build an autonomous laboratory before this approach becomes useful. Start with one narrow, frequent, testable loop.

Stage 1: Make the repository legible

Create a project pack. Record real commands, boundaries, terms, and acceptance checks. Remove stale instructions. Give the agent a deliberate reading order.

Stage 2: Make one workflow reproducible

Pick a recurring task: build a firmware image, add a register-map driver, reproduce a boot failure, or run a protocol test. Turn the human runbook into commands with reliable output.

Stage 3: Close a software-only loop

Let the agent change code, compile, run host tests, inspect failures, and retry within a bounded task. Keep the diff small enough for a human to review.

Stage 4: Add one hardware observation

Connect UART capture or a programmer first. Then add controlled power, relays, or measurement equipment as the use case demands. Every new actuator needs a safety policy; every new sensor needs a data contract.

Stage 5: Capture what worked

Convert repeated procedures into Skills. Add tests for failures you have already paid to understand. Promote genuinely general Skills to a shared template, while keeping board- and project-specific knowledge in the repository that owns it.

The first success criterion is not “the AI completed an entire project.” It is much smaller:

Can a new agent enter the repository, execute one meaningful task, produce real evidence, and leave the project easier for the next agent to understand?

If the answer is yes, the compounding loop has started.

The Engineer’s Role Moves Up the Stack

When code generation gets cheaper, the bottleneck moves.

In my own work, less time is spent typing syntax. More time is spent clarifying requirements, defining what “done” means, diagnosing ambiguous failures, choosing trade-offs, and communicating with other people.

That does not make embedded engineers less important. It makes domain judgment more visible.

The engineer owns:

  • the product goal;
  • system boundaries;
  • safety;
  • the acceptance protocol;
  • architectural trade-offs;
  • the decision to ship.

The agent can explore implementations, operate tools, and collect evidence. The Harness makes that work repeatable and reviewable.

The emerging paradigm is not “AI replaces firmware engineers.” It is:

People define intent and judgment. Agents orchestrate implementation. The Harness connects them to reality.

Build What Survives the Next Model

Models will keep improving. Task queues, memory layers, planning modes, and orchestration features will keep moving into the platform.

That is good news. Let the model vendors build the generic machinery.

Our job is to build what survives the next release:

  • a repository that explains the real system;
  • engineering knowledge encoded as callable practice;
  • tools with reliable contracts;
  • a programmable, safe hardware lab;
  • evidence that closes the loop;
  • a learning process that leaves the project stronger after every task.

That is the embedded AI Harness.

It is not another wrapper around a model. It is the environment in which a model can finally do engineering.