Here's a scenario most agent builders haven't tested: your agent gets permission to do something. Four minutes later, that permission is revoked — a token expires, a setting changes, someone says no. But the agent already has the technical capability queued up. At minute five, it executes anyway. At minute six, some downstream system records it as done.
The agent had permission. Was it still authorized at the moment it actually mattered? Those are different questions, and almost nobody's system can tell them apart.
Worse: if you try to stop the action after authority changes, and the request already left for an external provider, flipping your own app's state to "blocked" doesn't prove anything happened — or didn't. You're guessing, wearing the costume of a system that checked.
Spent this week in a thread with people independently landing on the same fix from completely different systems — WordPress admin tools, AI ops platforms, an app that turns plain English into phone actions. The fix: never let permission be a thing you check once and trust forever. Every action gets a short-lived, parameter-bound token — re-verified the instant before it fires, not five minutes earlier when it was requested. And once something leaves your system's boundary, "blocked" isn't a real status anymore. Only "confirmed clean" or "unresolved" are honest.
I build the version of this for a phone, not a server — say a command, see exactly what it's about to do, and nothing executes on stale authority, ever. Confirmed before it runs, or it doesn't run.
That's StareBrain. Pre-launch, building in public, link in profile if the 9:00-to-9:06 problem is one you've hit too.
The parameter-bound token is the right direction. I would bind it to an objective version and an idempotency key too. If scope changes before the side effect, stop. If the request already crossed the boundary, the honest state is unresolved until the external system confirms what happened.
Idempotency key is the piece I was missing. Parameter binding stops a stale plan from re-executing with different data, but it doesn't stop the same confirmed plan from firing twice if a retry or a duplicate dispatch happens after the boundary — which is a different failure mode I hadn't separated out until you named it.
"Objective version" is also a sharper term than what I've been using. I'd been thinking of it as re-checking specific facts (slot availability, contact record), but versioning the whole object means I can detect drift I didn't think to explicitly check for, not just the fields I anticipated.
On "unresolved until the external system confirms" — agreed, and it's the harder admission: for something like SMS delivery, that confirmation may never arrive with real independence, since the only attester is the provider I'm trying to verify. So "unresolved" isn't always a waiting state that resolves — sometimes it's the honest permanent answer.
Yes, and that permanent
unresolvedstate changes the product design. It needs an owner, an expiry, a compensation path, and a clear rule for what downstream systems may infer from it. Otherwise uncertainty gets treated like a temporary technical glitch and eventually becomes silent success in reports. Sometimes the honest final record is simply: authorized, dispatched, outcome not independently knowable."An owner, an expiry, a compensation path" is the piece that turns this from a labeling decision into an actual product requirement — I'd been thinking of the third state as something I display, not something someone's accountable for. Without an owner it just becomes a status nobody's job it is to look at.
The compensation path is the part I don't have an answer for yet, and it's probably the hardest one. For "did the text send," what does compensation even look like — resend and risk a duplicate, ask the user to manually check, just surface the uncertainty and let them decide? Curious if you think that has to be action-specific, or if there's a general pattern that applies across send/book/call regardless of what the action actually is.
"Authorized, dispatched, outcome not independently knowable" is a better final-record sentence than anything I've written for this state so far. Might steal that exact phrasing.
The gap you're describing — permission at assignment vs. authorization at execution — is one we hit constantly. We ended up re-validating scope immediately before each side effect and logging the decision, which caught a couple of cases where a revoked key still had queued actions. Curious how you'd handle a run already in flight when scope changes mid-execution: fail closed, or checkpoint and hand back to a human?
Good to hear it's a real, observed failure and not just a theoretical one — "revoked key still had queued actions" is exactly the shape of bug this whole thread's been circling.
For mid-execution, I'd lean fail-closed by default, checkpoint-and-return-to-human only for actions that are naturally resumable without re-litigating the whole plan. Concretely: most of my actions (a text, a calendar event, a device toggle) are short enough that "mid-execution" barely exists as a window — they're closer to atomic. So for me, fail-closed is nearly free, since there's rarely meaningful partial progress worth preserving. I'd guess your case is harder specifically because a longer-running agent task probably does have real partial state worth checkpointing, and throwing that away by failing closed has a real cost mine doesn't.
So maybe the actual rule is: fail-closed by default, checkpoint-and-resume only when discarding partial progress is expensive enough to justify the added complexity of resuming safely. Curious whether that tracks with what actually pushed you toward logging + re-validation instead of just hard-stopping on any scope change.