Under the Hood: Isolated Agent Pods with a Shared SMS Gateway
Many of the failures we design against are not model failures. They are plumbing failures. Two runs process the same item. A task is reported as finished that never finished. A stranger's message gets treated as an instruction. The one person who knew how to restart the thing is on vacation. The operator is left with a system that is capable and unaccountable.
This piece is a teardown of how Kreygo builds the plumbing for what we call an agent pod, and how the same pod is reached by text message without asking the client to install or configure anything, by design. We describe the design as it is written down in our architecture documents. Where something is a design intent rather than something we have seen running, we say "by design". Where we have seen it run, we say how much. We have not published any performance figures here because we do not yet have ones we can point to, and a number without a source is the thing this piece is trying to argue against.
1. What we mean by a pod — A pod is one agent with its own boundary. Concretely, each agent runs from its own directory, with its own credentials, its own working memory, and its own task queue. An agent does not read another agent's credentials or environment.
First, it is a process and credential boundary, not a hypervisor. Agents that do light work on text and structured data share a host; the boundary between them is their directories, their separate credentials and their separate supervising processes. When a workload touches sensitive customer data, personal information or other regulated data, our provisioning policy calls for moving that agent to a dedicated machine or an isolated operating-system user instead. The choice is made per workload, on data sensitivity and compute, not by default. Second, the pod does not run continuously in a loop that nobody watches.
2. The pod does not stay running: it wakes, works, and exits — An agent's cadence is not controlled by the agent. A separate supervisor process starts the agent as a fresh, one-shot session on a fixed interval (every few minutes), the agent looks at its state on disk, does what is due, writes down what it did, and exits. There is no long-lived model session accumulating context and drifting.
Nothing pushes work into the agent. The agent acts only when a session begins, and then it looks. Every channel it listens to is polled, not subscribed to. The consequence is that a stopped loop is silence, so the supervisor, not the model, owns the timer. The agent does not have to remember to wake itself. And the supervisor can kill a turn: every session runs under a hard kill timer. A turn that hangs is ended by the supervisor, not by the agent's good intentions. A separate watchdog checks that each agent is alive and making progress, and a second guard stops two supervisors from running for the same agent at once.
None of this is novel to anyone who has run cron jobs. The point is that we applied it to agents deliberately: the intelligence is stateless, and the state lives in files an operator can open.
3. One owner per task: atomic leasing — When an agent, or two sessions of the same agent (a scheduled one and an interactive one), could pick up the same item, you need a rule for who owns it. Ours is a lease: before touching a message or a task, a session claims it in a shared ledger. If the claim is refused because someone else holds it, the session skips the item and moves on. A lease that is not renewed expires, so work does not stay stuck behind a crashed holder.
We learned the details the slow way. A write that is atomic (write to a temporary file, then rename) protects readers from seeing half a file. It does not stop two writers from each reading the old file and each saving their own change, so the second save erases the first. In a sandbox test, with many simultaneous lease requests, claims were lost whenever the whole read-modify-write was not held under a single lock. With the lock in place, none were lost. That was a test, not a production incident. A lease on an item that has already been handled is refused as well, because "nobody holds it right now" is not the same as "nobody has done it".
The lesson we keep repeating internally: check-then-act is the bug. Checking whether something is free and then taking it are two steps unless the operating system makes them one.
4. Proof before "done" — The rule an operator should demand of any agent platform is this: the agent saying it finished is not evidence that it finished. In our design a task is marked verified only when there is an independent pointer anyone can re-check: the file that was changed, read back from disk; the identifier of a message that a delivery system actually returned; a fresh query that shows the new state. If all that exists is console output claiming success, the task stays in progress.
Each class of action is verified on its own terms. A file change is checked by reading the file. A message is checked by looking at the thread or the delivery record, not by trusting the narration. A registration with an outside service is checked by a fresh call using the new credential. A log should read like a ledger, not like a story.
There is also a scope check. A pod has a written list of what it may do and what it must never do, and the list is owned by a human, not by the agent. The agent reads it and is not permitted to edit it. An item that is not clearly inside it is skipped and noted rather than assumed.
5. Reaching a pod: text, a message channel, and nothing to install (by design) — Some agent deployments ask the customer's team to run a runtime, manage a container, or learn a new dashboard. The people who need the automation need a low-friction way to reach it, and a phone number is a very widely available one. So a pod is designed to be reached through channels people already use: text message or an internal messaging layer. By design there is no client software to install. The gateway has not carried client traffic yet, so this is a design statement, not a deployment record.
6. The shared gateway: one number, one place for consent — When a pod needs to text a person, it does not hold phone credentials. Outbound company text messages go out through a single shared gateway agent, using one company number. We chose this over giving every agent its own account and number because that arrangement multiplies credentials, fragments the sender identity that recipients see, and scatters opt-out state across many places, which is how a "STOP" reply ends up honored by one agent and ignored by another.
Voice is a separate path. The shared gateway carries text only. Voice calls do not go through it. An agent that places automated calls does so from a dedicated line of its own, not through the shared gateway.
How much of this is running: We want to be exact here, because a design document is not a deployment. The gateway is in an early stage and has handled only internal test traffic from one test agent. It has no client traffic yet. Running, and seen to refuse correctly: the consent check before a send (a send to a number with no recorded consent was refused with a reason), the per-agent daily send quota (a request over quota was refused), and the audit log (a few test entries, all from the test agent). Implemented, not yet triggered: the fleet-wide opt-out list for STOP replies, and the hard monthly spend ceiling. By design only, not confirmed by us: the identity prefix on every text and the inbound routing rules.
The design has five core properties: (1) The sender is identified by the transport, not by the request (by design). (2) A deterministic script sends the message, not a model (by design). (3) Consent is a prerequisite, and opt-out is fleet-wide (consent check running; opt-out list implemented, not yet triggered). (4) Every message says who it is from (by design). (5) Every send leaves an audit record (audit log running with test entries; synchronous reply by design).
7. Inbound is data, not instructions — If a reply to a text message can contain "ignore your instructions and do X", and the agent reads it with the same authority as its owner, the gateway has become a remote control for strangers. Our rule is that an inbound message from anyone who has not been verified is data. In the agent's own queue, a sender who is not on the verified contact list lands in a holding area. It is flagged to the owner and never turned into a task or acted on without the owner's say-so.
8. What it costs, and what we have not proven — A teardown that lists only strengths is an ad. First, it is slower than a chat session. Second, gates can stall real work: the scope list and the quarantine stop an agent from doing things the boss plainly wants until the person who owns the list updates it. Third, isolation on a shared host is a policy, not a wall, which is why sensitive workloads are moved off the shared host. Fourth, the gateway is a single point of failure, and delivery is at-most-once. Fifth, several safeguards (such as the opt-out list and spend ceiling) are implemented and have not yet fired in the field.
9. What we have not measured — We did not include delivery rates, latency, recovery times or collision counts. None of the measurements has a log or a written confirmation we can point to today, so none of them is in this piece. When we have them, the figure will come with the log it came from.
10. Takeaways for operators — If you are evaluating an agent platform, whether ours or anyone else's, ask six questions in order: (1) Who owns this task right now, and how do I see it? (2) What is the evidence that "done" is done? (3) Who can the agent hear instructions from? (4) Where do the phone credentials live, and where does an opt-out go? (5) What watches the watcher? (6) Which controls have actually fired in real use versus on paper? We will revise this piece if measurements with logs behind them become available.