Under the hood

How She Thinks

The conversation you have is one model, doing the work. But a layer of small, independently-run checks — microagents — watches what she's about to say and do, and can overrule her before you ever see it. The model having the conversation can't be retrained on the fly — no one can teach it something new mid-chat. This layer around it can: it learns from what actually happened, on real tasks, continuously.

Not a bigger prompt — a second opinion

Caroline's main model (Claude, or whichever account you've connected) does the actual thinking, holds the conversation, and decides what to do. A system prompt asking it to behave a certain way is a request, not a guarantee — confirmed the hard way, more than once: an instruction can be perfectly clear and still get missed in the moment, especially a few turns after it mattered.

Microagents are the fix for that gap. Each one is a small, separate model call with exactly one job, checking a specific thing independently of whatever the main model just decided — a second opinion that doesn't share the main model's blind spots, because it isn't the same call. Some run on the backing service, some run in Caroline's own process on your machine — more on that split below.

What a microagent actually is

Every microagent is the same shape: a strict input, a strict output, and a prompt that does exactly one job — classify, rewrite, decide yes-or-no. Nothing is ever compared by hand-written code where the comparison is genuinely fuzzy (does this name match that one, does this reply leak something it shouldn't, did the user actually say yes) — that's always the model's call, every single time, not a keyword list that quietly stops matching the day someone phrases something differently.

A call starts on the cheapest model that can plausibly do the job, and only escalates to a stronger one if the cheap one's answer fails validation — bad structure, a failed sanity check — never just because the answer seemed like it might be wrong. Getting a valid-but-debatable answer doesn't burn a more expensive model for no reason.

RungWhen it's used
nanoEvery call starts here
nano, told what failedOnly if the first answer didn't validate
miniOnly if it still doesn't validate

Where she runs them: a universal backend, not a dumping ground

Camerlengo — the backing service behind Caroline, shared with other products built on the same infrastructure — is deliberately kept universal. Nothing specific to one product is allowed to live there. Memory, document indexing, and the address book are genuine shared infrastructure, so they stay on the server. But her own judgment calls — does this reply leak something, does she actually have your OK — are Caroline's business alone, so those run in her own process, on your machine. The server's only remaining job for them is handing back one raw model answer at a time, through a single generic command that has no idea which agent or which product is even asking. Your provider keys and billing never leave the server either way — what moved is only whose code decides what to ask and whether the answer is good enough.

The microagents running today

On the server: what you'd expect from shared infrastructure — deciding what's worth remembering, matching a name in conversation to someone already in your contacts, finding which stored memory a question is actually about, indexing a document you've saved.

On your machine: everything that's Caroline's own judgment about you and this conversation — spotting a pending send or spend before it happens, checking who it would go out under, reviewing her own reply for leaks or off-topic drift, deciding whether she actually has your OK, tracking whether a message she just sent actually delivered what it claimed to. Three of these are the most directly about trust rather than just usefulness — worth a closer look.

reply.review — checking her own reply before you see it

Every message that reaches you — including the small "still working on it" updates while she's in the middle of something — gets checked by its own model call first, for three things: is it actually about the task at hand, does it leak anything about her own internal plumbing (a tool name, an internal retry, an internal error) instead of just talking about the work, and does it read like a person wrote it rather than a system describing itself. Fails any of those, and it gets rewritten before it ever reaches your screen — not just asked nicely not to happen.

turn.permission.guard — silence isn't a yes

The problem this exists for is a specific, observed one: Caroline would ask "can I do this?" and then, a message or two later, go ahead and do it anyway — because nothing told her the question had gone unanswered. Now an unanswered yes/no question is treated as a no, not as license to proceed.

The same strict rule applies even when she never asked out loud: anything that communicates with someone else on your behalf — a message, an email, a reply to a third party — or anything that touches your money needs a clear, specific approval already on record. A general "sure, go ahead" for the task doesn't count as approval for a particular send or a particular spend; only an answer that's actually about that exact thing does.

When approval isn't there, the whole turn stops — the same hard stop as pressing the app's own Stop button — and she's told plainly that she needs to ask you directly and wait for a real answer before trying again.

Approval itself is now tracked explicitly, as a short-lived record of the exact bounded action ("send the renewal email to Jessica Zhou") rather than re-derived from a scrollable window of recent conversation on every single check — a real approval you already gave can no longer scroll out of view on a busy day and get asked again.

turn.delivery.completeness — did she actually show you the thing

The mirror-image failure to the one above: Caroline believing she showed you something — a drafted reply, a specific figure, an attachment — when the message that actually reached you never contained it. This check runs on every outbound message, right after review, comparing what the text claims or implies it's delivering against what's actually there. It never blocks the send itself; catching the gap just prompts her to immediately follow up with the thing she meant to include in the first place.

Why not just tell her not to, in the prompt? That was tried first, for both of these. It's the instruction every assistant already gets, and it's exactly what kept quietly failing — the system prompt is advisory, these checks are not. Defense in depth: the instruction stays, the independent check is what actually holds the line.

Learning from experience, without retraining the model

The model actually holding your conversation — Claude, or whichever account you've connected — can't be retrained on the fly. No one can sit it down and teach it something new between one message and the next; whatever it knows, it knew before the conversation started. That's just what a large language model is. But the microagents around it are a different story: each one is just a prompt plus a small model call, and a prompt can be rewritten, tried, and judged against reality, continuously, without touching the model underneath at all. That's the real point of this whole layer — not only "catch her mistakes in the moment," but "get measurably better at catching them, from what actually happens."

Concretely: Camerlengo can clone one of these prompts, write a genuinely different variant of it, and run that variant head-to-head against the current version, on the exact same real task — not a synthetic test, the actual thing you asked for right now. Both answers go to an independent judge, blind to which one is the established version, which picks whichever one actually served the role's own stated purpose better for that case. Win, lose, or tie gets recorded; a challenger has to keep winning consistently, over real calls, before it ever becomes the new default — and once it does, there's no gradual rollout or shadow period, it's just the version Caroline uses from then on. A version that doesn't hold up gets quietly retired instead, and nothing about your conversation ever looked different while that was being decided — every comparison runs invisibly, alongside the one answer you actually needed.

Most calls never trigger any of this at all — the ordinary, already-working version just answers, same as always, at no extra cost. The experiment only runs often enough to keep finding real improvements, never so often that it gets in the way of the actual conversation.

Source

The server-side microagents live in the backing service's own repository. Caroline's own judgment-call microagents — everything described above as running on your machine — are in Caroline's own open-source tree, alongside the rest of her client code.

Browse Caroline's own source