Skip to Content
Next — You're reading the unreleased preview docs. APIs and pages may change before the next release.Switch to the current docs →
How-To GuidesMoonBitScheduling a Future Agent Invocation (MoonBit)

Scheduling a Future Agent Invocation (MoonBit)

Overview

A scheduled invocation enqueues a method call on the target agent to be executed at a specific future time. The call returns immediately; the target agent processes it when the scheduled time arrives.

This is for agent-to-agent scheduled calls from code. To schedule an invocation from the CLI, see the golem-schedule-agent-moonbit skill instead.

Usage

Methods with recursively stream-free inputs and outputs have a generated schedule_ variant. These examples use durable clients. Ephemeral clients require scoped_new_phantom or scoped_get_phantom, not scoped. Use AgentClient::scoped inside an async function to obtain a client and call the synchronous enqueue method with a scheduled_at instant and the method arguments. The scoped helper and its callback are async even though scheduling itself is synchronous:

AgentClient::scoped("param", async fn(client) { client.schedule_increment(scheduled_at) })

Full Example

AgentClient::scoped("my-counter", async fn(client) { // Schedule increment to run 60 seconds from now let now = @systemClock.now() let scheduled_at = @systemClock.Instant::{ seconds: now.seconds + 60, nanoseconds: 0, } client.schedule_increment(scheduled_at) })

Schedule with arguments

ReportAgentClient::scoped("daily", async fn(client) { let scheduled_at = @systemClock.Instant::{ seconds: tomorrow_midnight, nanoseconds: 0, } client.schedule_generate_report(scheduled_at, "summary") })

Datetime Type

Import "golemcloud/golem_sdk/interface/wasi/clocks/system-clock" @systemClock in moon.pkg. The scheduled_at parameter is a @systemClock.Instant with signed Int64 seconds and UInt nanoseconds since the Unix epoch. tomorrow_midnight above must be Int64; convert a UInt64 delay with .to_int64() only after checking it fits:

let scheduled_at = @systemClock.Instant::{ seconds: 1700000000, // Unix timestamp in seconds nanoseconds: 0, // Sub-second precision }

Cancelable Variant

Stream-free methods on durable clients also have a schedule_cancelable_ variant that returns a CancellationToken. Ephemeral clients return a receipt containing the token and invocation metadata instead. Call .cancel() on the token to prevent the scheduled invocation from firing:

AgentClient::scoped("my-counter", async fn(client) { let now = @systemClock.now() let scheduled_at = @systemClock.Instant::{ seconds: now.seconds + 60, nanoseconds: 0, } let token = client.schedule_cancelable_increment(scheduled_at) defer token.drop() // Later, to cancel: token.cancel() // cancel() borrows the token; defer releases it whether cancelled or not. })

Use Cases

  • Periodic tasks: Schedule the next run at the end of each invocation
  • Delayed processing: Process an order after a cooling-off period
  • Reminders and notifications: Send a reminder at a specific time
  • Retry with backoff: Schedule a retry after a delay on failure