Skip to content
Chiplab logo
Chiplab logo
Back to Now

I was on holiday. My agent shipped the blog post anyway.

Our last post makes an argument: coding agents work because of a feedback loop, and in embedded that loop needs a target the agent can execute on. This post is the receipt. The last post was itself drafted, fact-checked, and validated by an agent, and the firmware transcript in the middle of it is real: compiled, uploaded, and run on a virtual STM32F4 while I was on holiday.

I contributed three messages. Here's what happened between them.

The three messages

The first one:

I want to write a new blog from the list here [Linear board link]. What do you suggest? Something that is easy to do

The agent queried our Linear workspace over MCP, pulled the 71 open issues in the marketing team, grouped them, and recommended a hands-on tutorial because the example code for it already existed in the chiplab repo. Reasonable, but not what I wanted that day. Message two:

mmm can we do sth more generic?

It came back with the four opinion pieces from the backlog, ranked by effort, and recommended the thesis post: "Why your AI coding agent needs a target to run on." Message three, and my last real contribution:

Ok -- go for it, something like 5-10 mins read I guess?

That's the entire spec I provided.

What happened next

Agents write prose fine, the same way they write firmware fine. What's worth looking at is everything around the prose.

First, it gathered ground truth instead of improvising. It pulled the full Linear issue, which contained a four-line outline and a definition of done. It read our previous getting-started post to extract the house style: frontmatter shape, heading conventions, voice. It read the chiplab README for product facts. The draft that came out of this matches our existing post closely enough that I had nothing to fix, because it checked references instead of guessing.

Second, the part I want to dwell on: the issue's definition of done included "code/example verified on Chiplab" and a live transcript as the proof artifact. A lazier workflow would have mocked one up. Plausible-looking terminal output is the easiest thing in the world for a language model to fabricate, and nobody would have caught it in review.

Instead, the agent split the work. It handed the draft to a writing sub-agent running in the background, with instructions to leave an explicitly marked placeholder where the transcript would go. While that ran, it produced the artifact itself:

$ cargo build --release
   Compiling hello-stm32f4-discovery v0.1.0
    Finished `release` profile [optimized] target(s) in 3.78s

[chiplab] issue_upload_ticket → artifact_01kyhbxcw3…
[chiplab] upload hello-stm32f4-discovery (ELF) → OK
[chiplab] run (board: stm32f4_discovery) → run_01kyhbxyqx…
[chiplab] usart2: [host: 0.23s | virt: 0s] Hello world!

It checked my machine had the right Rust cross-compilation targets installed, built the bare-metal STM32F4 example from the public repo, requested an upload ticket from Chiplab over MCP, pushed the ELF, triggered a run on a virtual STM32F4 Discovery, and pulled the captured output back down. The raw run log shows the simulated chip booting for real: the SVD for the STM32F40x loading, the vector table being located at 0x8000000, and the firmware's greeting arriving on USART2 at virtual time zero. The full round trip, upload to output, came back in under a minute.

Then it spliced the real transcript into the draft where the placeholder sat, ran a quick pass for word count and style tics, moved the Linear ticket to In Progress, and left a comment documenting exactly what had been verified, including the run ID, so anyone on the team could trace the claim.

The recursive bit

That sequence is: build an ELF, upload it, run it on a virtual instance of a real chip, read back the UART output.

That's the exact contract the blog post describes. The post arguing that agents need a target to run on was validated by an agent using that target to run on. The proof artifact inside the argument was produced by the mechanism the argument is about. I'd love to claim we planned that symmetry; we didn't. It fell out of the workflow, because once the loop exists, the agent reaches for it on its own.

And it matters for exactly the reason the post gives. The transcript is the one part of that article a language model would confidently hallucinate. Register names, tool output, and UART lines are all trivially fakeable, and all plausible in review. I can put that transcript in a published post without a disclaimer because it's captured output from a run I can look up by ID.

What I actually did

Full disclosure of the human contribution, because posts like this tend to oversell:

I picked the topic, in two messages. I set the length. I read the draft afterwards and am reviewing it before it goes live, same as this one. The agent stack was nothing exotic: an MCP-capable coding agent on my laptop, connected to Linear's MCP server for the backlog and Chiplab's for the firmware runs. No custom automation or one-off pipeline. The same setup from the getting-started post, pointed at a marketing repo instead of a firmware one.

I was also on holiday. The messages have the typos to prove it.

Why this is worth a post

"AI wrote our blog" is barely an anecdote in 2026. This is worth a post because of where the verification happened.

The wall between "the agent produced something" and "the thing actually works" is the same wall in content as it is in firmware. A draft that reads well and a binary that compiles are the same kind of artifact: plausible, unvalidated. What made this workflow feel different was watching the agent treat "verified on Chiplab" in a ticket's definition of done as an instruction to go compile and run firmware, rather than a checkbox to write around.

The last post argued that agents check their work when you give them a way to. This time it's just what happened while I was away.