Skip to Content
How-To GuidesRustWaiting for External Input with Golem Promises (Rust)

Waiting for External Input with Golem Promises (Rust)

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 golem_rust crate:

FunctionSignatureDescription
create_promisefn create_promise() -> PromiseIdCreates a new promise and returns its ID
blocking_await_promisefn blocking_await_promise(id: &PromiseId) -> Vec<u8>Blocks until the promise is completed (sync)
await_promiseasync fn await_promise(id: &PromiseId) -> Vec<u8>Awaits promise completion (async)
complete_promisefn complete_promise(id: &PromiseId, data: &[u8]) -> boolCompletes a promise with raw bytes

JSON Helpers

For structured data, use the JSON wrappers from golem_rust::json:

FunctionSignature
blocking_await_promise_json<T: DeserializeOwned>fn(id: &PromiseId) -> Result<T, serde_json::Error>
await_promise_json<T: DeserializeOwned>async fn(id: &PromiseId) -> Result<T, serde_json::Error>
complete_promise_json<T: Serialize>fn(id: &PromiseId, value: T) -> Result<bool, serde_json::Error>

Imports

use golem_rust::{create_promise, complete_promise, blocking_await_promise, await_promise, PromiseId}; // For JSON helpers: use golem_rust::json::{await_promise_json, blocking_await_promise_json, complete_promise_json};

Usage Pattern

1. Create a Promise and Wait (Sync)

let promise_id = create_promise(); // Pass promise_id to an external system... let data: Vec<u8> = blocking_await_promise(&promise_id);

2. Create a Promise and Wait (Async)

let promise_id = create_promise(); // Pass promise_id to an external system... let data: Vec<u8> = await_promise(&promise_id).await;

3. Complete a Promise from Another Agent

complete_promise(&promise_id, b"done"); // Or with JSON: complete_promise_json(&promise_id, MyResponse { status: "approved".into() }).unwrap();

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

use golem_rust::{ agent_definition, agent_implementation, endpoint, create_promise, PromiseId, }; use golem_rust::json::await_promise_json; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, PartialEq)] enum Decision { Approved, Rejected, } #[agent_definition(mount = "/workflows")] pub trait WorkflowAgent { fn new(name: String) -> Self; async fn start_approval(&mut self) -> String; } struct WorkflowAgentImpl { name: String, } #[agent_implementation] impl WorkflowAgent for WorkflowAgentImpl { fn new(name: String) -> Self { Self { name } } #[endpoint(post = "/approve")] async fn start_approval(&mut self) -> String { // 1. Create a promise let promise_id = create_promise(); // 2. Pass promise_id.oplog_idx to an external system (e.g. via RPC, HTTP, etc.) // The agent is now durably suspended. // 3. Wait for external completion let decision: Decision = await_promise_json(&promise_id) .await .expect("Invalid payload"); if decision == Decision::Approved { format!("Workflow {} approved ✅", self.name) } else { format!("Workflow {} rejected ❌", self.name) } } }

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