Skip to Content
How-To GuidesMoonBitWaiting for External Input with Golem Promises (MoonBit)

Waiting for External Input with Golem Promises (MoonBit)

Overview

A Golem promise lets an agent suspend its execution until an external event completes it. The agent creates a promise, passes the promise ID to an external system (another agent, a webhook, a UI, an HTTP API call), and then awaits the result. The Golem runtime durably suspends the agent — consuming no resources — until the promise is fulfilled.

API

All functions are in the @api package of the Golem MoonBit SDK:

FunctionSignatureDescription
@api.create_promise() -> PromiseIdCreates a new promise and returns its ID
@api.await_promise(PromiseId) -> BytesBlocks until the promise is completed
@api.complete_promise(PromiseId, Bytes) -> BoolCompletes a promise with a byte payload
@api.get_promise(PromiseId) -> PromiseResultGets a handle for polling/getting the result

Usage Pattern

1. Create a Promise and Wait

let promise_id = @api.create_promise() // Pass promise_id to an external system... // Agent is durably suspended here until the promise is completed let data : Bytes = @api.await_promise(promise_id)

2. Complete a Promise from Another Agent

let payload = "approved" @api.complete_promise(promise_id, Bytes::from_array(payload.to_array().map(fn(c) { c.to_int().to_byte() })))

3. Advanced: Poll without Blocking

let promise_result = @api.get_promise(promise_id) let pollable = promise_result.subscribe() // Use pollable with poll infrastructure match promise_result.get() { Some(data) => // promise completed None => // not ready yet }

PromiseId Structure

A PromiseId contains an agent_id and an oplog_idx. To let an external system complete the promise via the Golem REST API, the agent must expose both fields. The external caller then sends:

POST /v1/components/{component_id}/workers/{agent_name}/complete Content-Type: application/json {"oplogIdx": <oplog_idx>, "data": [<bytes>]}

Full Example: Human-in-the-Loop Approval

#derive.agent struct WorkflowAgent { name : String mut last_result : String } fn WorkflowAgent::new(name : String) -> WorkflowAgent { { name, last_result: "" } } /// Start an approval workflow that waits for external input pub fn WorkflowAgent::start_approval(self : Self) -> UInt64 { let promise_id = @api.create_promise() // Return the oplog_idx so the external caller can complete the promise promise_id.oplog_idx } /// Wait for the approval to arrive and return the result pub fn WorkflowAgent::wait_for_approval(self : Self, oplog_idx : UInt64) -> String { let promise_id = @types.PromiseId::{ agent_id: @api.get_self_agent_id(), oplog_idx, } let data = @api.await_promise(promise_id) let result = String::from_array(data.to_array().map(fn(b) { Char::from_int(b.to_int()) })) self.last_result = result result }

Use Cases

  • Human-in-the-loop: Pause a workflow until a human approves or rejects
  • Webhook callbacks: Wait for an external HTTP callback to arrive
  • Inter-agent synchronization: One agent creates a promise, another completes it
  • External event ingestion: Suspend until an IoT sensor, payment gateway, or third-party API sends a signal
Last updated on