C3PO, part 2: a real agent and a chat interface
In part 1, Claude Code drove a simulated Unitree G1 through an MCP server, from my terminal. That proved the loop works — and made the limits obvious: the whole thing ran only on my machine, inside a tool built for editing code. Nobody else could talk to the robot.
This month was about making C3PO a system instead of a hack.
The agent moves to the backend
C3PO was already a monorepo with a SvelteKit frontend and an Elysia backend on Bun; the robot side just hadn’t touched them. Now the backend runs its own agent: a streaming loop on the Vercel AI SDK with Claude as the model, thinking enabled, capped at a dozen tool steps per turn.
The interesting part is that nothing about the robot changed. The skills live in a registry with JSON schemas; the backend converts them into tools for the model, and every call is dispatched over MCP (streamable HTTP this time, instead of stdio) to the same Python bridge from part 1. The skill layer doesn’t know or care who’s driving — Claude Code, this agent, whatever comes next. Swapping the brain’s host didn’t touch the skills, the bridge, or the protocol.
Two details I’m glad I got in early: tool failures are returned to the model as errors instead of killing the stream, so it can react and retry — and the system prompt has an honesty rule, because some skills are logged-only in the sim: never claim the robot moved when it didn’t.
A chat interface
The terminal is my natural habitat, but “type into a CLI on my laptop” is not how you talk to a robot. C3PO now has a proper console: a chat where responses stream in and every skill invocation shows up as a little monospace pill with its status — pending, done, failed. There’s a stop button, and next to the chat, a live map that polls the robot’s state every couple of seconds (pose, heading, travel trail, battery, latency), a live camera view streamed over WebRTC from the sim’s head and wrist cameras, and a big red PARAR button wired straight to stop_everything.
The part I’m actually excited about
The simulator has been the point all along — and it’s about to stop being the point. A real Unitree G1 is on its way, arriving in a few weeks. The groundwork is already in the repo: the real robot speaks different DDS topics than the sim, so there’s a full protocol catalogue mapping every skill to the real firmware’s API, and a fault decoder that understands its error codes, down to the emergency stop.
Part 3 will be written next to a robot.
Code: github.com/mercho40/C3PO.