<!-- markdown mirror of https://impire.io/imps/ — generated from the built page; the canonical HTML lives at that URL -->

research · imps · autonomous agents

# An agent you don't drive.

You're in a loud room. Dozens of conversations, music, the clatter of glasses, and you are thinking about none of it. Your ears take in everything; the sound washes straight past. Then, somewhere across the room, someone says your name. You snap around. Nothing changed about the noise. **Something changed about your attention.**

That gap between hearing everything and thinking about almost none of it is the most useful trick your brain has. It runs cheaply, all the time, and it spends real effort only on the rare thing that earns it. An imp is built around that trick.

Most things called agents today are tools you drive. Claude Code, Hermes, pi.dev: you open them, you type, they work, then they wait for you to type again. Genuinely useful, and not autonomous. Nothing happens until a person picks up the controls.

An imp is meant to run on its own. It is small, watches one slice of the world, and reads everything that crosses it for almost nothing. It reaches for real thought only when what it saw crosses a line worth acting on. No one is driving.

**imps** is a Go framework for building agents shaped that way, running on NATS. You give an imp its inbound channels, a cheap awareness function that runs on every message, an expensive thinking function that runs only when awareness decides a message has earned it, and a little local memory. The framework wires up the subscriptions, the dispatch, and the outbound sends.

This is early. Two features are shipped, both with a real test suite. What runs today is the core of the idea; the rest of the vision below is honestly still ahead.

### Awareness is cheap; thinking is expensive

Awareness runs on every single message. It stays local and bounded, and it returns one of three verdicts: ignore this, hold a note about it, or escalate it to thinking. Most messages get ignored, and ignoring is nearly free. Thinking runs only on escalation, and thinking is where the expensive work lives: model calls, multi-step tool use, recall over a large corpus. Because thinking runs rarely, an imp can pay attention to a firehose and still cost almost nothing most of the time.

### The compiler enforces the line

This is the part that makes it real rather than a good intention. The boundary between cheap awareness and expensive thinking is not a rule you are trusted to remember. It is built into the types. The context awareness runs in can issue one request and wait for one reply, and that is all it can do. It has no way to fan out, no way to fire off a publish, no way to grab the raw connection. **Awareness code that tries to publish does not compile.**

The test suite proves it from the outside. Three build configurations exist whose only job is to fail to compile; if any of them ever builds, that is caught as a regression. You cannot accidentally make awareness expensive, because the expensive surface is not there to reach for.

### One imp does one thing

A complaint-watcher watches incoming email for complaints. It does not also chase late invoices. If you want both, you build two imps. The reason is practical: a specialist has a small, known surface, which makes it cheap to test, cheap to reason about, and cheap to run. The intended payoff is many small imps cooperating to produce something no single one could, each simple on its own.

### What's true today

**Shipped.** The core surface: channels that decode inbound NATS messages and route them by entity, the awareness and thinking functions with the compiler-enforced split between them, per-entity local memory, and the outbound sends (a single request-and-reply, fan-out request-to-many, and fire-and-forget publish). A runnable echo example. A test suite that runs under the race detector alongside the compile-must-fail checks. Go 1.25 or newer, with one runtime dependency, `nats.go`. The license is fair-code, under the Sustainable Use License.

**Not built yet.** The parts that turn one imp into a colony. Sleeping when idle and waking on a message, so an imp with nothing to do costs no compute, is designed and not written. The capability services an imp reaches for while thinking, for inference and knowledge and tools, are designed and not written. Coordination between imps over a shared stream is designed and not written. Today you can build one imp and run it against NATS; the always-on, self-suspending, cooperating colony is the direction, not the current state.

### Build one

`go get` the module, write the five parts, point it at a NATS server. The echo imp that subscribes to one subject and republishes to another is about forty lines, and it comes with a test that runs an embedded server so you can watch it work before you wire it to anything.

fair-code · Go 1.25+ · one runtime dependency (nats.go) · early, and built in the open
