Using Pagr
Texting your agents
You do not have to learn a command language. You do have to know what Pagr can act on — because the set of actions is small and fixed, and everything you say resolves to one of them.
How a message is handled#
Every inbound message goes through the same pipeline:
- Identity. The sending number is hashed and matched to a linked account. An unknown number can only do one thing: send a
CONNECTcode. - Compliance. A bare uppercase
STOPorSTARTis handled before anything else. - Storage. The message is stored, keyed on the provider's message id, so a webhook retry can never repeat an action.
- Entitlement. An expired trial or subscription stops here.
- Fast path. A short list of unambiguous phrasings is answered deterministically, without a model.
- Model. Everything else goes to the router, which may call up to four tools before it has to answer.
- Reply and audit. One text back; every side effect written to the audit log.
The model chooses which tool to call. It never chooses what a tool is allowed to do, and it has no say at all in how risky an approval is — that classification is deterministic and runs outside the model. See approvals.
Intent reference#
Each row is a real capability with a real name. Phrase it however you like; these are examples, not syntax.
| Say something like | What happens |
|---|---|
| “what's running?”, “status” | Lists your active sessions with project, agent and state. Read-only. Answered without a model. |
| “what did codex say?”, “why did it stop?” | One session's current status plus its most recent events — what the agent last said, and whether it is blocked. |
| “which projects do I have?” | Lists registered projects with their aliases and which Mac they live on. |
| “are my macs online?” | Lists paired Macs, online state, and which agents are connected on each. |
| “what's waiting on me?” | Lists pending approvals with the preview of each action and its risk tier. |
| “start codex on checkout-api and run the tests” | Starts a new session on a registered project with that instruction. Requires an active subscription, the provider connected on that Mac, and the Mac online — if it is offline the command queues for up to 12 hours and you are told so. |
| “tell claude to skip the migration for now” | Sends a follow-up instruction to an existing session. Steered into the live turn where the provider supports it, otherwise queued until the turn ends. |
| “stop”, “stop codex”, “cancel the ios-app one” | Interrupts a running session. The current turn is aborted. |
| “approve”, “yes”, “deny”, “no”, “approve 2” | Answers one pending approval, bound to that exact request and preview. Tier C is answerable too, flagged as high-risk in the message — unless you have turned offApprove high-risk actions by text, which sends a signed link instead. |
| “when claude finishes have codex review it” | Starts a durable review workflow: the reviewer starts once the implementer finishes, read-only where the provider supports it, and you get the findings as a message. |
| “make codex my default reviewer” | Remembers which agent reviews when you say “have it reviewed” without naming one. |
| “don't text me unless something is blocked or done” | Changes your notification policy. See notifications. |
Fast paths#
Some phrasings are unambiguous enough that sending them to a model would only add latency and risk. These are handled by a pure function of your text and the current state:
- Status. “status”, “what's running”, “what's going on”, “anything running”, “what's everyone doing”, “what are they doing”, “what's happening”.
- Approve. “approve”, “approved”, “yes”, “y”, “ok”, “okay”, “go ahead”, “allow”, “do it”, “yep”, “yup”, “sure”.
- Deny. “deny”, “denied”, “no”, “n”, “reject”, “don't”, “nope”, “block”.
- Stop. “stop”, “cancel”, “halt”, “abort”, optionally followed by an agent or project name.
- Help. “help” or “?” returns a short list of things you can say and a link to the dashboard.
Punctuation and curly apostrophes are normalised away, so “What’s running?” and “whats running” are the same message.
Disambiguation#
Pagr will not guess when guessing could act on the wrong thing. If two sessions could match a “stop”, or two approvals could match a “yes”, it asks — and it asks with enough information to answer in one word:
There are 2 things waiting on you:1. checkout-api · Codex: npm run db:migrate2. ios-app · Claude: rm -rf ./buildWhich one? (e.g. "approve 1" or "deny the checkout-api one")A bare “yes” with nothing pending is not treated as an approval; it goes to the router, which will usually ask what you meant.
How references resolve#
- Projects match on display name or any alias you registered, so
--alias checkout,apiis worth setting. - Agents match on “claude” or “codex”.
- Pronouns — “tell him”, “stop it” — resolve against the session the conversation last talked about.
- A recently completed session is still a valid target for a follow-up: the bridge resumes it rather than starting a new one.
Keywords that are not instructions#
Three inputs are handled before anything else and are matched only as bare, uppercase words:
| Message | Effect |
|---|---|
STOP | Carrier opt-out. All outbound messages to that number are disabled and Pagr does not even reply. Also matches UNSUBSCRIBE, CANCEL, END, QUIT. |
START | Re-enables outbound messages. Also matches UNSTOP. |
CONNECT <code> | Links this phone number to your account. The only thing an unlinked number can do. |
What a message can never do#
The router can only call tools, and the tools can only send the nine typed protocol commands. No phrasing reaches past that:
- Run an arbitrary command. There is no shell tool. “Run
rm -rf /” can at most become an instruction to an agent, which then has to raise its own approval and clear Pagr's risk tiering. - Read or write a file directly. No file tool exists.
- Name a filesystem path. Tool arguments are opaque Pagr ids. A path where an id belongs fails validation.
- Touch an unregistered folder. Project ids only resolve against the local registry on your Mac.
- Change how much a text is allowed to approve. Tier C is approvable by text only because Approve high-risk actions by text is on; nothing you can send from the thread can turn that setting on or off, or widen a tier.
- Reach another account. Every tool is scoped to the user the number is linked to.