Mark Emelianov
EN

Hard controls · Agents · Draft

A tiny host agent: no model, no inbound port

Status: this is a written design, a draft; not yet built and not in use. Rollout is planned facts-only and read-only first, commands last.

Most talk about AI agents is about what they can do. This article is about a piece that is deliberately designed to do very little: a small agent that would live on a host. It would contain no model. It would report facts about the host, run only commands from a fixed list, take its instructions as signed messages over git, and listen on no inbound port.

It is the smallest example of the idea running through this series: when you cannot make a component trustworthy by asking it nicely, make it small enough that there is little to trust.

What it is for

Some hosts are not controlled by an AI assistant at all. They still need to be known and, in narrow ways, managed: what runs on them, what state they are in, and a handful of routine actions. The tiny host agent is designed to sit on such a host and do exactly that and nothing more.

It would do three things. It would report host facts. It would receive instructions as signed messages. It would run a command only if the command is on its allow-list.

A host agent robot on the left, a git service in the middle and a signer robot on the right. The signer pushes signed messages to the git service, the host pulls them and reports facts back to it. A band says the host always reaches out and nothing reaches in: no inbound port.
Figure 1: the host pulls, the signer pushes, the host never listens

Why each design choice

Each choice is there for what it takes away from the attack surface.

No model. A model can be argued with: text it reads can steer what it does. A small fixed program cannot be talked into an action, and it is small enough for a person to read and review in one sitting. Removing the model removes a whole class of manipulation from the host.

An allow-list. The agent would refuse any command that is not on its list. A mistake, a bad message or a forged request can then reach only what the list permits. Unknown means refused.

Signed messages. The host would act only on instructions whose signature it can verify. Being able to reach the channel is not enough; only the holder of the signing key can instruct the host.

Git as the channel. The host would ask git for new messages, instead of waiting to be called. Every instruction becomes a commit, so history is a record of what was asked and by whom, and the transport needs nothing special.

No inbound port. Because the host would always reach out and nothing would reach in, there is no listening service to scan, probe or exploit from the network.

Five rows. Each design choice on the left, no model, allow-list, signed messages, git as the channel and no inbound port, points to what it removes from the attack surface on the right. A band says each choice takes something away and the next picture shows what is left.
Figure 3: what each design choice removes

One message, five fixed steps

Every message would go through the same steps in the same order: pull it, verify the signature, check the command against the allow-list, run the one listed command, report the result and host facts. If any step fails, the message stops there. Unsigned, unknown or unlisted means nothing runs, and there is no judgement in the middle for anyone to lean on.

Five boxes in a row, each with a small robot: pull a new message, verify its signature, check the command against the allow-list, run one listed command, report the result and host facts. A band says any step that fails stops the message, so unsigned, unknown or unlisted means nothing runs.
Figure 2: one message, five fixed steps

What it would cost

Small and strict has a price.

What this design does not protect against

Naming the limits matters more than listing the strengths.

The signing key. Whoever holds the signing key can send valid messages. The allow-list limits what they can ask for, but a harmful action that is on the list would be carried out. How the key is held, and how it would be replaced, is an open design point.

Replay. A genuine signed message can be sent again later. The design requires a way to tell fresh messages from old ones, such as an expiry or a counter; without it, replay is possible.

A compromised git service. The service cannot forge signatures, but it can withhold messages, delay them, or show old ones. That affects availability and freshness, not authenticity.

A bad allow-list. The allow-list is the real permission boundary. It is only as safe as its entries and the arguments they accept; a broad entry is a broad permission.

A compromised host. A host that has been taken over can report false facts about itself. The damage is limited to that host's own paths: it would not reach other hosts through this design.

Five cards, each with a small robot: the signing key as an open design point, replay of an old signed message, a compromised git service, a bad allow-list, and a compromised host that can report false facts limited to its own paths. A band says small allow-lists, fresh messages, careful keys and monitoring narrow the damage but these risks remain.
Figure 4: what this design does not protect against

These risks would be narrowed by small allow-lists with fixed arguments, fresh messages, careful handling of keys, and monitoring of what the host reports. They are not removed.

How it fits the rest of the series

The host agent would be the lowest layer of the same picture. Agents above it propose, people approve, and signed, recorded messages carry the approved instruction down. At the bottom there would be a piece that follows its list and keeps a record, and that has little else to attack.