An AI agent that configures network devices over the serial console

It's 1 a.m. in a data center, a network engineer is on the floor (literally on the floor) next to a rack, a USB-to-serial cable running from his laptop to the console port of a FortiGate. PuTTY is open. The firewall is sitting at FortiGate-60F login: and nothing else, because the management interface isn't configured yet. There is no network path to this box. That's the whole point of the console port: it's the one interface that works when nothing else does.

So he does what every network and security engineer has done for thirty years. He types a command. He reads a wall of text. He hits the spacebar through --More--. He types the next command. He squints at the output to decide what's wrong. Repeat until the box is configured or the sun comes up, whichever is first.

This loop hasn't changed since RS-232. And here's the part that bugs me. We spent the last two years watching AI agents learn to write software, refactor codebases, run test suites, open pull requests, and not one of them can do the single most basic thing a field network engineer does every week. None of them can talk to the switch in the rack.

I want to walk through why that gap exists, why it's harder to close than it looks, and what we actually shipped in sia-cli to close it.

The console is the one place automation never reached

Be clear about what's automated today and what isn't.

If a device is on the network, we have good tools. Ansible, Netmiko, Nornir, vendor APIs. They all assume a reachable IP and an SSH or HTTPS endpoint. That covers steady-state config management well.

The console covers the other situation. The box is new and unconfigured. The management VLAN is down. Someone fat-fingered an ACL and locked everyone out. A firmware upgrade left the thing half-alive. In all of these, there is no IP to SSH to, and the console cable is the only way in. It's where you do first-boot provisioning or break-glass recovery.

That's exactly the work that's still 100% manual, done by a senior person, usually at a bad hour. The console port is the last interface in the building that never got automated, and it's the one that matters most when things are actually broken.

Why the coding agents can't just do this

When people first see this, the natural question is: "Cursor and Claude Code / Codex can run shell commands. Can't they just pip install pyserial and open the port?"

I thought so too. They can't, and the reason is precise and worth understanding, because it shapes everything about how you'd build it.

A console session is stateful, and the state lives on one open file handle. You open /dev/ttyUSB0, you send \r, you're at a login prompt. You authenticate, you're in user-exec. You type enable, you're in privileged-exec. You type configure terminal, you're in config mode. Every one of those transitions only exists because the same file descriptor stayed open the whole time.

A coding agent's shell tool is the opposite of that. Every command runs in a fresh, one-shot process. The model calls bash, the command runs, the process exits, and any file handle it held is gone. So you can absolutely run python -c "import serial; ..." inside Claude Code, and the moment that call returns, the port closes and the session resets. The next tool call opens a brand-new process that knows nothing about the login you just did. You cannot walk a login → enable → configure sequence across a model's turns when the connection dies between every turn.

This isn't a knock on those tools. They're built to edit files and drive compilers, and for that the stateless-shell model is correct. The console just needs the opposite: a long-lived process that holds the port open across many model turns. That's not a flag you toggle. It's a different component.

There's a second reason, more mundane: you can't embed serial into the agent binary anyway. sia ships as a single file compiled with bun build --compile. Bun can't embed native .node addons, and node-serialport crashes under it. Serial access has to live out-of-process no matter what. Which, conveniently, is also where the long-lived stateful connection wants to live.

What we built: a minimalist sidecar and a smart model

So the shape was forced on us, and it turned out to be the right shape.

Three layers, three jobs: the model knows the gear, a skill enforces the discipline, the sidecar just moves bytes. The engine never learns what a device is.

The serial capability is a standalone binary called sia-serial. It's a minimalist Rust program (rmcp + tokio-serial, around 600 lines) that speaks the Model Context Protocol over stdio and exposes six deliberately boring tools: list_ports, open, write, read, send, close. It opens a port, holds it open for the life of the session, matches bytes, strips the echo, moves data. That's it. It knows nothing about Cisco, Juniper, or FortiOS. It has never heard of configure terminal.

The intelligence sits in two places that are not the binary.

The model is the device brain. A frontier model already knows IOS, NX-OS, Junos, FortiOS, PAN-OS. Better than any vendor-profile table we could hand-write and then spend the next five years maintaining. So we don't encode device knowledge anywhere. The model picks the port and baud, knows that a Cisco prompt ends in #, knows terminal length 0 disables paging, and supplies the regex it wants to wait for. The sidecar just matches the bytes the model hands it. The one real design question, "how does it know when a command finished?", is answered by letting the model say so: it passes the prompt pattern to wait for, or a quiet-period timeout. The sidecar holds no idea what those patterns mean.

The safety lives in a skill, not in code. This is the part I care about most. At the byte level, show running-config and configure terminal are identical. Both are just "write these bytes to the wire." There is no honest way to mechanically tell a safe read from a dangerous write inside the sidecar, because the difference is meaning, and only the model has the meaning. So the read-vs-write discipline ships as a retrieved skill the model reads at runtime: run diagnostics freely, but stop and get explicit operator confirmation before entering config mode, before any change, and especially before anything that persists or could lock you out. On a FortiGate that matters more than on a Cisco box, because FortiOS saves on end: there's no separate "write memory" safety net. The model knows that. The skill tells it to pause anyway.

Three layers, each owning what it's actually good at: the model brings CLI knowledge, the skill brings operational judgment, the sidecar moves bytes. The engine, sia-core, gets zero serial code. That was a hard rule, and we kept it.

What it looks like

This is a real session against a real Cisco Catalyst Switch on my desk, on an FTDI cable, nothing faked:

Then I asked it to change the hostname. It stopped, told me exactly what it was about to send, and waited for me to say yes, because that's a write, and on this box a write is immediately persistent. That pause is the whole product. The model understood the command, so the confirmation landed on the one operation that actually changes the firewall, not on every get.

The engineer is still in the loop, watching every line in the terminal. That's not a fallback we tolerate; it's a layer we designed for. The console is the wrong place to be fully hands-off in v1, and we say so.

Turning it on

For a field engineer there are no build tools, no SDK, nothing to compile. It's a download:

#1 Install sia-cli agent on any Windows/Linux/MacOS machine
#2 sia serial enable
#1 Install sia-cli agent on any Windows/Linux/MacOS machine
#2 sia serial enable
#1 Install sia-cli agent on any Windows/Linux/MacOS machine
#2 sia serial enable

sia serial enable pulls the sia-serial binary for your platform, verifies it against a SHA256 manifest, registers it as an MCP server, and pins the safety skill. It's built and published for macOS, Linux, and Windows x64. The last one matters, because most field network engineers live on Windows laptops, and a tool that only runs on a developer's Mac is useless to them. Plug in the cable, run sia, talk to the device.

The honest part

This write-up is for engineers, so here's what's rough, because you'll hit it.

The binaries aren't code-signed yet. On Windows you'll see a SmartScreen warning; on macOS Gatekeeper may quarantine the download. Both are clickable-through today, and Authenticode/notarization is the next thing on the list.

Credentials in v1 are not private. When you type a device password into the sia conversation, the model sees it, and it lands in the transcript and the audit log like any other input. The secret goes to the device, but it is exposed. Use a lab or break-glass credential for now, not your production enable secret. A keychain-backed input channel is the obvious next step and it isn't done.

It's local serial only. No console servers, no ser2net, no RFC2217 over TCP yet, though the sidecar was built so a tcp:// backend drops in without changing the tool contract. And on Windows the safety skill doesn't auto-install cleanly because the skill's directory name contains a colon, which Windows paths reject. The plumbing works; that one polish item doesn't.

None of these are architectural. They're a v1 being honest about being a v1.

Why this is the interesting part

We didn't add serial because serial is exciting. RS-232 is the opposite of exciting. We added it because the console port is the last manual frontier in network and security operations, and closing it is what turns "an AI that helps you write a script" into "an AI that can actually do the night-shift work."

A coding agent operates on files and code. That's a real and valuable world, and Cursor, Claude Code, and Codex are excellent in it. But the network engineer's world is gear in racks, half-bricked firewalls, and a blue cable that's the only way in. That world has its own primitives: a UART, a stateful session, a prompt you wait for, a change you confirm. None of them map onto "edit this file." Sia is built for IT and network operations, so those primitives are in scope for us in a way they aren't for a tool built to ship software.

The console was always going to be the hardest interface to automate, because it's the one you reach for when everything else has already failed. It's also the one where autonomous ops has the most to give back: the senior engineer who used to drive to a site at 1 a.m. can hand the rote part to the agent and supervise, instead of typing --More-- two hundred times.

That's the direction. This is the first cable plugged in.

sia serial is live in sia-cli today. Install sia-cli, run sia serial enable, and point it at a console cable. The sidecar, the six-tool contract, and the architecture are documented in the repo. Tell us what breaks. We're early, and the console is unforgiving.

Written by

Karan Singh

Co-founder & CTO

Published on