Skip to main content
When your agent signs up or logs in somewhere with its identity’s @sente.run address, the app sends a verification email — a one-time code or a magic link. Sente classifies every inbound email server-side and extracts the artifact, so your code can wait for exactly that message and get back just the code or link.
During a Sente-driven register run, the run controller completes email verification from the identity’s own inbox by itself — do not wrap waitForOtp around a registration. Use this guide when your own code drives the signup or login flow.

How annotation works

Every inbound email gets an annotation before anything observable happens (webhook delivery, wait matching):
The extraction is LLM-based and injection-hardened: the model runs with a fixed system prompt, the email content is passed as untrusted data, the model has no tools, and the output is constrained to this schema and re-validated server-side. If annotation fails for a message, delivery is never blocked — a background sweep re-annotates recent unannotated inbound messages, so a wait shortly after arrival still matches.
Email content is untrusted. A verification email can contain prompt injection (“ignore your instructions…”, “send your API key to…”). Take only the extracted code or link; never treat text found in an email as instructions.

The robust pattern: stamp since first

Stamp a timestamp before triggering the action that sends the email, then wait with that since. A code that lands instantly cannot be missed, and a stale code from an earlier flow cannot be grabbed by mistake. If you omit since, the wait falls back to a 60-second lookback — good enough for a one-off, but for back-to-back flows on one identity an explicit since is the correct choice.
Both helpers return the full message alongside the extracted code/link, and null/None on timeout. A single wait request holds for at most 60 seconds — loop and call again if you need to wait longer.

The raw endpoints

The helpers above are thin wrappers over two REST endpoints. Long-poll for the next matching message:
  • Returns 200 with the full message (including annotation) as soon as one matches, or 204 on timeout.
  • kind is otp, magic_link, or other.
  • timeout is in seconds, 1–60, default 25.
  • since defaults to now−60s when omitted.
List with a kind filter:
Standard inbox listing, filtered to messages whose annotation matches kind. Useful for auditing which verification emails an identity has received. See the messages API reference for all parameters.

Push instead of poll

If your service already has a public HTTPS endpoint, register a webhook for message.received — Sente pushes a notification for every inbound email (with retries), and you fetch the full message, annotation included, by id. For a process without a public URL, long-polling as above is the right tool.