Developer setup
Let your Agent send reminders and decisions to your users' phones, have them answer there, and read the same durable result back from your code.
The preview is ready. Publish it to the public page?
3 images and 1 video, about 2.4 MB.
Answer saved
Publish now from iPhone, 2:32 PM
get_task: status "answered"
Prerequisites
Setup needs three things. The first two happen on the web; the third depends on how you connect.
- An account
- Sign in with an email code; the first sign-in creates the account. Use the same email on your computer and your phone.
- A phone with notifications verified
- Sign in on the phone, turn on notifications under Connections, then open the card from the test notification you actually received and press Got it. Unverified devices do not receive ordinary reminders.
- A credential
- Claude Code and Codex connect with one mcp add command plus the client's own sign-in, so there is no key to copy; if the command cannot run, create a token under Connections and configure it by hand. The HTTP SDK uses an Agent token created under Connections; sending reminders to your own product's users needs the master key from Server integration.
Three steps
About ten minutes from nothing to the first reminder on your phone.
Sign in and connect your phone
Open the sign-in page on your computer, then sign in on your phone with the same email. On iPhone, first choose Add to Home Screen in Safari, then open it from the home screen. Go to Connections, press Send test notification, open the card from the notification your phone actually received, and press Got it.
Connect your Agent
Terminal # Add the MCP server over HTTP transport claude mcp add --transport http agent-notify https://your-notiagent.example/mcp # Start a new session, type /mcp and pick agent-notify to sign inThe authorization page lists the operations you are allowing; you can revoke them any time under Connections.
Send the first one and answer it on your phone
Say the sentence below to your Agent. Reminders fire on the server on schedule and keep running after the Agent exits; back in the Agent, read the result of the same task with
get_task.“Remind me to take a break in one minute, with an option for done or another reminder in ten minutes.”
Downloads
All three packages are built locally and not yet published to npm or a public plugin directory; every file matches the SHA-256 in the checksum manifest.
- Download
TypeScript SDK
Typed server-side calls, input and response validation, timeouts and signature verification.
agent-notify-sdk-2.0.0.tgz108.5 KBsha256 03f13c4e2f6ccf73…
- Download
Codex plugin
MCP configuration plus workflow notes for reminders, questions and handoffs.
agent-notify-codex-2.0.0.tar.gz4.1 KBsha256 a27aa07e34d6b529…
- Download
Claude Code plugin
HTTP MCP configuration; sign in and authorize on first connect.
agent-notify-claude-2.0.0.tar.gz3.8 KBsha256 62b8ffe09d923fc3…
Unpack a plugin package, then follow its instructions to run plugin marketplace add . and plugin install; after installing, start a new session and authorize from the host's MCP sign-in entry point.
Check the integration connection
Once you have a credential, confirm who it is and what it can see. These calls are read-only and send no notifications.
| Operation | Key required | Returns |
|---|---|---|
getIdentity | Any integration key | The identity and kind of the current key, and the recipient it is bound to |
getSite | Any integration key | The logical site of the owning account |
listChannels | Any integration key | Channel counts configured for the account or the bound recipient |
listMachines | Master key | Machines that have reported a session |
A configured channel does not mean the device is online or that the notification arrived.
Set it up for your users
When the reminder goes to a user of your product rather than to you: keep the master key in your backend and issue each user a short-lived key bound to them for the Agent, or create a sign-in-free answer link directly.
| Operation | Key required | Purpose |
|---|---|---|
enrollRecipient | Master key | Create a recipient for an external_id and generate its setup link |
issueBoundKey | Master key | Issue an Agent key pinned to that recipient |
getReachability | Master or bound key | The channels that can reach this user right now |
createDecision | Master or bound key | Create a durable decision; the master key plus approval_url also returns a sign-in-free answer link |
getDecision | Master or bound key | Read once with getDecision; waitForDecision waits up to 25 seconds |
revokeApprovalLink | Master key | Revoke only the link, without cancelling the decision |
revokeBoundKey | Master key | End that Agent session's access |
import { createAgentNotify } from "@agent-notify/sdk";
const APP_ORIGIN = process.env.AGENT_NOTIFY_APP_ORIGIN ?? "https://your-notiagent.example";
const backend = createAgentNotify({
baseUrl: APP_ORIGIN,
apiKey: process.env.AGENT_NOTIFY_SERVER_KEY!,
});
export async function requestPublication(
user: { id: string },
run: { id: string },
deliver: (url: string) => Promise<void>,
) {
const decision = await backend.createDecision({
body: {
subject: { tool_name: "publish", external_id: user.id },
question: "Publish this preview?",
type: "confirm",
approval_url: true,
idempotency_key: `${run.id}-publish`,
},
});
if (decision.status === "stopped") return; // the site was stopped by its owner
if (decision.approval_url) {
await deliver(decision.approval_url); // deliver the link through your own channel
}
return decision;
}The answer link is returned only when it is first created and lasts at most 12 hours. When the owner has stopped the site, creation returns a status: "stopped" receipt instead of a decision, so check the status before reading any field.
Answers and callbacks
Once the user answers the card, your code has three ways to get the result: polling, a signed callback, or submitting on their behalf from your own interface.
| Operation | Key required | Purpose |
|---|---|---|
getTask and waitForResponse | Agent credential | Read once or wait once; a wait timeout does not cancel the task |
answerDecision | Master key | Submit the answer on behalf of a user your backend has already authenticated; the card records the source |
getWebhookSecret | Master key | Get the account callback secret, used to verify X-Pushary-Signature |
rotateWebhookSecret | Master key | Rotate the secret; subsequent attempts resolve the current signing key and retain delivery history |
verifyWebhookSignature | No network needed | Verify the raw body, then parse the JSON |
Error handling
Server endpoints return a flat error, code, status and request_id. Read the HTTP status first, then the code.
| Status | Meaning | What to do |
|---|---|---|
| 400 | The input breaks the contract, or the idempotency key disagrees with the identity in the body | Fix the fields against the OpenAPI document and retry |
| 401 | The credential is invalid or revoked | Check where the key came from and reissue it if needed |
| 403 | The key kind is not enough, for example a bound key calling a master-key endpoint | Use the right key instead of raising the Agent's privileges |
| 405 | Method not supported | The Allow response header lists the usable methods |
| 409 | Idempotency conflict, or no reachable channel under require_reachable | Use a new key for a new operation; tell the user to configure a channel first |
| 429 | Over the rate or capacity limit | Wait for Retry-After, then retry |
| 5xx | Server error; the write may already have happened | Retry with the same key and the same parameters; do not switch keys |
The SDK maps these to AgentNotifyError, carrying code, status, requestId and outcomeUnknown; when the last one is true, do not assume the request had no effect.