Skip to main content
This reference documents the low-level host functions that workflows call from WebAssembly. Most users should use the high-level Rust SDK wrappers instead.

Overview

Workflows execute in a WebAssembly sandbox and communicate with the Slung host through imported functions. These functions use a Region-based memory protocol for passing non-primitive data.

Memory Protocol

The host and guest exchange data using the Region struct:
#[repr(C)]
pub struct Region {
    offset: usize,
    capacity: usize,
    length: usize,
}
Guest modules export allocate() and deallocate() functions for the host to manage memory:
extern "C" fn allocate(capacity: usize) -> usize
extern "C" fn deallocate(region_addr: usize)

Host Functions

u_query_live

uint64_t u_query_live(usize filter_ptr)
Register a live query with the host.
filter_ptr
usize
required
Guest pointer to a Region containing UTF-8 filter bytes

Returns

Query handle (u64), or 0 on failure.

Usage

let filter = Region::build(filter.as_bytes());
let filter_ptr = &*filter as *const Region;
let handle = unsafe { u_query_live(filter_ptr as usize) };

u_query_history

double u_query_history(usize filter_ptr)
Execute a historical aggregation query.
filter_ptr
usize
required
Guest pointer to a Region containing UTF-8 filter bytes

Returns

Aggregated value (f64). Returns 0.0 on failure or for valid zero results.

Usage

let filter = Region::build(filter.as_bytes());
let filter_ptr = &*filter as *const Region;
let result = unsafe { u_query_history(filter_ptr as usize) };

u_poll_handle

usize u_poll_handle(uint64_t handle)
Poll a live query handle for the next event.
handle
uint64_t
required
Query handle returned by u_query_live

Returns

Guest pointer to a Region containing JSON event data, or 0 if no event is available.

Usage

let data_ptr = unsafe { u_poll_handle(handle) };

if data_ptr != 0 {
    let data = unsafe { Region::consume(data_ptr as *mut Region) };
    let event: Event = serde_json::from_slice(&data)?;
}

u_free_handle

uint32_t u_free_handle(uint64_t handle)
Free a live query handle and release host resources.
handle
uint64_t
required
Query handle to free

Returns

0 on success, non-zero on failure.

Usage

let result = unsafe { u_free_handle(handle) };
if result != 0 {
    return Err(std::io::Error::other("Failed to free handle"));
}

u_write_event

uint32_t u_write_event(usize timestamp_ptr, usize value_ptr, usize tags_ptr)
Write a new event to the host.
timestamp_ptr
usize
required
Guest pointer to a Region containing UTF-8 timestamp string
value_ptr
usize
required
Guest pointer to a Region containing UTF-8 value string
tags_ptr
usize
required
Guest pointer to a Region containing UTF-8 CSV tags

Returns

0 on success, non-zero on failure.

Usage

let timestamp = Region::build(timestamp.to_string().as_bytes());
let value = Region::build(value.to_string().as_bytes());
let tags = Region::build(tags.join(",").as_bytes());

let result = unsafe {
    u_write_event(
        &*timestamp as *const Region as usize,
        &*value as *const Region as usize,
        &*tags as *const Region as usize
    )
};

u_writeback_ws

uint32_t u_writeback_ws(uint64_t producer_ptr, usize data_ptr)
Send data to a WebSocket producer connection.
producer_ptr
uint64_t
required
Producer connection ID
data_ptr
usize
required
Guest pointer to a Region containing data to send

Returns

0 on success, non-zero on failure.

Usage

let data = Region::build(data.as_bytes());
let result = unsafe {
    u_writeback_ws(destination, &*data as *const Region as usize)
};

u_writeback_http

usize u_writeback_http(usize url_ptr, usize data_ptr, uint32_t method_ptr)
Send an HTTP request through the host.
url_ptr
usize
required
Guest pointer to a Region containing UTF-8 URL
data_ptr
usize
required
Guest pointer to a Region containing request body
method_ptr
uint32_t
required
HTTP method: 0 = GET, 1 = POST, 2 = PUT, 3 = DELETE

Returns

Guest pointer to a response Region, or 0 if no response body is available or the request fails.

Usage

let url = Region::build(destination.as_bytes());
let data = Region::build(data.as_bytes());
let method = 1; // POST

let result = unsafe {
    u_writeback_http(
        &*url as *const Region as usize,
        &*data as *const Region as usize,
        method
    )
};

if result != 0 {
    let body = unsafe { Region::consume(result as *mut Region) };
}

Region Utilities

Region::build()

pub fn build(data: &[u8]) -> Box<Region>
Create a Region describing an existing byte slice. Does NOT take ownership - the host must NOT call deallocate on this region.

Region::release_buffer()

pub fn release_buffer(data: Vec<u8>) -> *mut Region
Consume a Vec and return a Region pointer. The host MUST call deallocate to free both the Region and the Vec memory.

Region::consume()

pub unsafe fn consume(ptr: *mut Region) -> Vec<u8>
Consume a Region pointer and return the owned Vec. Frees the Region struct but captures ownership of the referenced memory.

Best Practices

Direct use of host functions requires careful memory management. Use the high-level Rust SDK wrappers unless you need low-level control.
  1. Use Region::build() for passing data to the host
  2. Use Region::consume() for receiving data from the host
  3. Never manually free regions created with Region::build()
  4. Always free regions returned by host functions
  5. Check for null/zero pointers before consuming regions

Next Steps

Workflow API Reference

High-level Rust SDK API documentation

Rust Workflow Guide

Building workflows with the Rust SDK

Build docs developers (and LLMs) love