Skip to main content
SONZAI

Wakeups

Schedule a one-off proactive agent message at a specific future moment — a birthday greeting, appointment reminder, or interest follow-up.

Wakeups let your agent reach out to a user exactly once at a known future moment. Give the agent an intent, a check_type that it sees as context, and a delay in hours — the platform handles delivery. Unlike Scheduled Reminders, which fire on a repeating cadence, a wakeup fires once and is done.

Typical use cases: birthday greetings, appointment reminders, post-event check-ins, interest follow-ups, and time-delayed nudges. If you need the agent to repeat the same outreach, use a schedule instead.

What you can build with it

  • Birthday greetings — schedule a wakeup for 00:00 on a user's birthday so the agent is the first to reach out
  • Appointment reminders — fire 2 hours before a dentist, gym session, or onboarding call without any cron job on your side
  • Interest follow-ups — when a user mentions they are waiting on something, schedule a check-in for the next day ("hey, did you hear back from them?")
  • Post-event check-ins — the day after a job interview, a first date, or a big presentation, the agent proactively asks how it went
  • Time-delayed nudges — a user sets a task as pending; 24 hours later the agent checks in without the user having to remember to ask

Quickstart

Schedule a birthday greeting for a specific date using scheduled_at. For a "N hours from now" wakeup, use delay_hours instead. If both are provided, scheduled_at takes precedence.

import { Sonzai } from "@sonzai-labs/agents";

const client = new Sonzai({ apiKey: process.env.SONZAI_API_KEY! });

// Use scheduled_at for birthdays/appointments with a known date
const wakeup = await client.agents.scheduleWakeup("agent_abc", {
user_id:      "user_123",
check_type:   "birthday",
intent:       "wish the user a happy birthday",
scheduled_at: "2026-06-15T09:00:00Z",  // RFC3339 absolute timestamp
occasion:     "Sarah's 30th birthday",
interest_topic: "celebration and birthday traditions",
});

console.log(wakeup.wakeup_id);   // "wake_01HX..."
console.log(wakeup.scheduled_at); // "2026-06-15T09:00:00Z"

Core concepts

delay_hours and scheduled_at

Two mutually exclusive time inputs are supported:

  • delay_hours — a relative offset from the current moment (e.g. delay_hours: 24 fires tomorrow at roughly this time). The platform computes the absolute fire time at the moment the request is accepted. Use this for "N hours from now" semantics where no specific date matters.
  • scheduled_at — an RFC3339 absolute timestamp (e.g. "2026-06-15T09:00:00Z"). Use this for birthdays, appointments, or any event tied to a specific calendar date. The platform fires the wakeup as close to this time as possible.

If both are provided, scheduled_at takes precedence. scheduled_at in the response is always present and is the authoritative UTC time the wakeup will fire — store it if you want to show the user "your agent will reach out at X".

occasion, interest_topic, and event_description

These optional context fields are included in the agent's wakeup block at fire time, giving it richer material for personalised message composition:

  • occasion — a short human-readable label for the event (e.g. "Sarah's 30th birthday", "dentist appointment"). The agent may reference this directly in the message.
  • interest_topic — a topic or theme the agent should lean on when composing the message (e.g. "celebration and birthday traditions", "dental health tips").
  • event_description — a longer free-form description with any additional context the agent should know (e.g. "User is turning 30 and has mentioned wanting to celebrate with a surprise party").

All three are optional and additive — provide as many or as few as are useful. The agent's underlying model uses them as soft context, not as a rigid template.

check_type and intent

Both fields are free-form strings. The agent receives both as part of its wakeup context at fire time:

  • check_type is a short label that tells the agent the nature of the outreach ("birthday", "appointment_reminder", "interest_followup", etc.). Keep it lowercase and underscore-separated — it is machine-readable context, not a display string.
  • intent is a natural-language instruction to the agent describing what the message should accomplish. Write it as you would write a system instruction: "ask how the job interview went and whether they got an offer".

Neither field has a fixed enum — any string is valid. The agent's underlying model interprets them in context.

Lifecycle and status

A wakeup moves through three statuses:

StatusMeaning
pendingScheduled, not yet fired
executedFired; message delivered to the notification queue
cancelledCancelled before it fired

Once a wakeup reaches executed or cancelled it is immutable. To cancel a pending wakeup, call getWakeups to retrieve the wakeup_id, then cancel it via the API before scheduled_at passes.

One-off, not recurring

Each call to scheduleWakeup creates exactly one future fire. If you need to re-schedule after a wakeup executes (for example, to send a birthday greeting every year), schedule a new wakeup the next time you learn the date. For repeating outreach on a fixed cadence, use Scheduled Reminders instead.

Full API

All wakeup methods live under client.agents.* (TS/Python) or client.Agents.Wakeups (Go). Full request and response shapes are in the API reference.

MethodReturnsDescription
scheduleWakeup(agentId, opts)WakeupResponseSchedule a one-off wakeup
getWakeups(agentId, { status?, limit? })WakeupResponse[]List wakeups (optionally filtered by status)

scheduleWakeup input fields:

FieldTypeDescription
user_idstringRequired. The user the wakeup is for.
check_typestringRequired. Short label for the nature of the outreach (e.g. "birthday", "appointment_reminder").
intentstringRequired. Natural-language instruction for the agent describing what the message should accomplish.
delay_hoursnumberRelative offset from now. Mutually exclusive with scheduled_at; scheduled_at wins if both are set.
scheduled_atstring (RFC3339)Absolute fire time. Use for birthdays, appointments, or any event with a specific date.
occasionstringOptional short label for the event (e.g. "Sarah's 30th birthday"). Included in the agent's wakeup context.
interest_topicstringOptional topic or theme for the agent to lean on when composing the message.
event_descriptionstringOptional longer description with additional context for the agent.

WakeupResponse fields: wakeup_id, agent_id, user_id, scheduled_at, check_type, status, intent, occasion, interest_topic, event_description, last_topic, research_summary, executed_at, created_at.

Combines with other features

With Scheduled Reminders — one-off vs recurring

Schedules and Wakeups are complementary proactive primitives. The rule is simple: if the agent should reach out more than once on a predictable cadence, use a schedule. If the agent should reach out exactly once at a known moment, use a wakeup. Both feed into the same downstream delivery channels.

// Recurring: a daily morning check-in schedule
await client.schedules.create("agent_abc", "user_123", {
  cadence: {
    simple: { frequency: "daily", times: ["09:00"] },
    timezone: "Asia/Singapore",
  },
  intent: "morning mood and sleep check-in",
  check_type: "reminder",
});

// One-off: a wakeup on the day of the user's birthday
await client.agents.scheduleWakeup("agent_abc", {
  user_id:     "user_123",
  check_type:  "birthday",
  intent:      "wish the user a happy birthday on their 30th",
  delay_hours: 48,
});

A common pattern is to use both together: a recurring schedule for everyday outreach, and a wakeup for a special moment that doesn't fit the cadence.

With Memory — context-aware wakeup scheduling

The agent can read memory facts to decide when and what to schedule. For example, if a user mentions their anniversary date, the agent can search memory to retrieve that date and schedule a wakeup for the right moment. The wakeup then fires with the agent already knowing why it is reaching out.

// 1. User mentioned an upcoming anniversary — find it in memory
const memories = await client.agents.memory.search("agent_abc", {
  query: "anniversary date",
  limit: 5,
});

// 2. Parse the date from the top result and compute delay_hours
const anniversaryFact = memories.results[0].content;
// e.g. "User's wedding anniversary is April 30"
const hoursUntilAnniversary = computeHoursUntil("2026-04-30");

// 3. Schedule a wakeup for that exact moment
// Use scheduled_at for a known date, or delay_hours for "N hours from now"
await client.agents.scheduleWakeup("agent_abc", {
  user_id:          "user_123",
  check_type:       "anniversary",
  intent:           "wish the user a happy anniversary and ask how they are celebrating",
  scheduled_at:     "2026-04-30T09:00:00Z",  // the anniversary date
  occasion:         "User's wedding anniversary",
  event_description: anniversaryFact,
});

Because the agent has memory of the conversation in which the user shared the anniversary date, the wakeup message will feel naturally aware of the context — not generic.

With Webhooks & Notifications — receiving the fired message

When a wakeup fires, the generated message lands in the agent's notification queue. Your backend can consume it via SSE polling or a registered webhook. The event type is the same as any other proactive message; you don't need special handling for wakeup-originated messages vs schedule-originated ones.

// Poll for any pending proactive messages (wakeups or schedules)
const notifications = await client.agents.notifications.poll("agent_abc", {
  user_id: "user_123",
});

for (const n of notifications) {
  console.log(n.content);     // the agent's message text
  console.log(n.source_type); // "wakeup" | "schedule"
}

See Webhooks & Notifications for webhook registration, signature verification, and SSE consumption patterns.

Tutorials

No dedicated tutorial yet. The Scheduled Reminders tutorial covers the same delivery infrastructure — most concepts transfer directly.

Next steps

On this page