Welcome to the new Golem Cloud Docs! 👋
Waiting 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