Pushary
Blog
Engineering

The gap between notifying a human and getting a decision back

Notification APIs consider the job done at delivery. An agent approval's job starts there: hold the agent, collect the answer, fail closed, keep the record.

AG
Aadil Ghani
Founder, Pushary
Jul 17, 20263 min read
Share

A notification tells a person something happened. A decision stops the machine until a person says what should happen. Notification infrastructure is built for the first job and measures itself on delivery. AI agents increasingly need the second job, and the gap between the two is where approval systems quietly fail.

Key takeaways

  • Delivery is where a send API's responsibility ends and where an approval's responsibility begins: holding the agent, collecting the answer, enforcing the timeout, keeping the record.
  • Retrofitting a decision loop onto a send API means owning pending state, correlation, timeout policy, restart recovery, and audit yourself. The failure modes are silent.
  • The unit of value for an agent approval is a resolved decision, and the storage that matches it is a ledger, which is a different animal from a send log.

Two jobs that look alike for one second

Both jobs begin with a push message landing on a phone, which is why they get conflated. Watch what happens after the tap.

For a notification, nothing needs to happen. The person read it, the system's promise is kept, and the send log records a delivery. This is the right shape for "your agent finished the migration" and "the overnight run hit an error."

For a decision, the interesting part has not started. Somewhere an agent is holding at a step it must not pass alone. The person's tap has to become an answer, the answer has to find its way back to exactly that waiting agent, a clock has to be running so that silence eventually resolves the wait, and the resolution has to land on the safe side. Then somebody, months later, may need to see who decided what.

The parts you end up building

Teams that wire agent approvals over a plain send API build the second half themselves, usually discovering the parts one incident at a time.

Pending state. The question must exist somewhere other than the agent's memory, or a crash erases the fact that anyone was ever asked.

Correlation. The answer arrives on a different connection than the question left on. Something has to match them, reliably, across retries and duplicate taps.

Timeout policy. Silence must become an outcome. The safe mapping is silence means no, and it has to be enforced by the system rather than remembered by every caller.

Recovery. Deploys happen mid-wait. The waiting has to survive the process that started it, which pushes you toward a poll-the-ledger or webhook-resume design whether you planned one or not.

Routing. The right person has to receive it on a device they actually check, which for a product with many users means an enrollment story, not a hardcoded channel.

The record. When the agent acted, someone approved it. When it did not, someone declined or nobody answered. Both belong in a durable, queryable trail.

None of these is exotic. Together they are a real distributed-systems project, and every one of them fails silently: a lost pending row, a mismatched correlation, a timeout that never fired. The notification was delivered. The approval never worked.

The ledger is the tell

You can tell which job a system was built for by looking at what it stores. Send-oriented systems keep a send log: message, channel, delivery status. Decision-oriented systems keep a ledger: question, person, answer or fail-closed expiry, timestamps, and enough durability that the wait itself can lean on it. Pushary's decisions.ask() is the second kind. The call blocks until a real answer exists, the pending decision lives in the ledger rather than in a process, and the resolution is recorded next to the question.

That is also why "we added an approve button to our notification" is not the same feature. The button produces a tap. The loop produces a resolved decision.

Use both, on purpose

The practical architecture is not notifications versus decisions, it is notifications and decisions with a clear rule. If the agent may proceed either way, send a notification and keep moving. If the agent must not proceed without a person, create a decision and block on it. One enrollment, one delivery path, and one audit surface can carry both, which is how Pushary's two-call integration is shaped: notifications for the telling, decisions.ask() for the deciding, and a person on their phone at the end of both.

Frequently asked questions

Is a push notification enough for an AI agent approval?

No. A notification only delivers the message. An approval needs the agent held open, the answer collected and correlated back, a fail-closed timeout, and a record of the outcome. That second half is a distributed-systems problem the send API does not touch.

What do I have to build if I use a plain notification API for approvals?

A pending-decision store, correlation between question and answer, a timeout policy that fails closed, recovery so a restart does not lose the wait, per-user routing to the right device, and an audit record. Each is unglamorous, and each has a silent failure mode.

When is a plain notification the right tool?

Whenever nothing hinges on a reply: completion alerts, error pings, digests, status updates. The rule is simple. If the agent may proceed either way, notify. If the agent must not proceed without a person, that is a decision, and it needs the blocking loop.

AG
Aadil Ghani
Founder, Pushary

Building Pushary so an AI agent can reach you on your phone and wait for a yes before it does something you would not want.

Read next

Engineering

Build vs buy: the real cost of a human-in-the-loop approval loop

The prototype takes a weekend. The system that will not silently approve a refund takes a quarter. An honest itemization, including when building is right.

Jul 17, 20263 min readAadil Ghani
Engineering

Fail-closed by default: why agent approvals should block instead of fire and forget

The failure case for approvals is not exotic. It is a phone in a pocket. Fail-closed design decides in advance that the ordinary case means stop.

Jul 17, 20263 min readAadil Ghani
Engineering

Stop making your agent ask permission for everything. Or nothing.

Reads run free. The irreversible slice is small, and it is the only thing that should be allowed to interrupt you.

Jul 4, 20265 min readAadil Ghani

Get a push the moment your agent needs you

Approvals, done alerts, and a kill switch for Claude Code, Codex, Cursor, and the rest. It takes a couple of minutes to set up.