Golem SDK for MoonBit — build durable, fault-tolerant agents on the Golem platform
///|
#derive.agent
struct Counter {
name : String
mut value : UInt64
}
///|
/// Creates a new counter with the given name
fn Counter::new(name : String) -> Counter {
{ name, value: 0, }
}
///|
/// Increments the counter
pub fn Counter::increment(self : Self) -> Unit {
self.value += 1
}
///|
/// Returns the current value
pub fn Counter::get_value(self : Self) -> UInt64 {
self.value
}///|
#derive.golem_schema
pub(all) enum Priority {
Low
Medium
High
} derive(Eq)
///|
#derive.golem_schema
pub(all) struct TaskInfo {
title : String
priority : Priority
description : String?
}///|
pub(all) struct ReportMimeTypes {}
///|
impl @schema.AllowedMimeTypes for ReportMimeTypes with fn mime_types() {
["text/csv"]
}
///|
#derive.endpoint(get="/report")
pub fn ReportAgent::report(
self : Self,
) -> Result[@schema.UnstructuredBinary[ReportMimeTypes]?, String] {
Ok(Some(@schema.UnstructuredBinary::inline(self.csv, mime_type="text/csv")))
}///|
fn stream_values(values : Array[UInt]) -> @schema.AgentStream[UInt] {
@schema.AgentStream::produce(async fn(writer) {
for value in values {
match writer.write_one(value) {
@schema.Accepted => ()
@schema.PeerDropped => return
}
}
})
}
///|
pub async fn Counter::sum(
self : Self,
input : @schema.AgentStream[UInt],
) -> UInt {
let _ = self
defer input.drop()
let mut total = 0U
for ;; {
match input.read() {
Some(value) => total += value
None => return total
}
}
}///|
enum WeatherError {
#derive.error(kind="usage-error", exit_code="2")
UnknownCity(city~ : String)
}
///|
/// Look up current weather conditions.
#derive.tool("weather", version="1.0.0")
struct Weather {}
///|
#derive.arg("city", scope="positional", doc="city to query")
pub fn Weather::weather(city : String) -> Result[String, WeatherError] {
if city == "" {
Err(UnknownCity(city~))
} else {
Ok("Sunny")
}
}
///|
#derive.arg("days", scope="option", short="d", min="1", max="10")
pub fn Weather::forecast(
city : String,
days : UInt?,
) -> Result[Array[String], WeatherError] {
// ...
}let client = WeatherClient::new()
let current : Result[String, @tool.ToolError[WeatherError]] =
client.weather("London")
client.drop()///|
#derive.tool("messages")
struct Messages {}
///|
pub fn Messages::send(message : String) -> String {
message
}
///|
#derive.tool_middleware("message-policy", presented="Messages")
struct MessagePolicy {}
///|
pub async fn MessagePolicy::send(
underlying : MessagesUnderlying,
message : String,
) -> Result[String, @toolMiddleware.ToolInvokeError[@tool.NoToolError]] {
if message.contains("blocked") {
// Zero underlying calls: this invocation is short-circuited.
Err(
@toolMiddleware.ToolInvokeError::ConstraintViolation(
"messages containing 'blocked' are not allowed",
),
)
} else {
// One underlying call: forward to the next inner layer.
underlying.send(message)
}
}
///|
fn main {
}///|
#derive.universal_tool_middleware("audit")
pub async fn audit(
invocation : @toolMiddleware.RawToolInvocation,
underlying : @toolMiddleware.UnderlyingTool,
) -> Result[
@toolMiddleware.RawInvocationResult,
@toolMiddleware.ToolInvokeError[@toolMiddleware.RawTypedSchemaValue],
] {
ignore(invocation.tool_name())
ignore(invocation.tool_metadata())
ignore(invocation.principal())
underlying.invoke_raw(
invocation.command_path(),
invocation.input(),
invocation.stdin(),
)
}import {
"golemcloud/golem_sdk/tool-core" @tool,
"golemcloud/golem_sdk/tool-middleware" @toolMiddleware,
}
supported_targets = "+wasm"
options(
"is-main": true,
)components:
myorg:message-middlewares:
templates: moonbit
dir: message_middlewaresTool middleware '<middleware>' references tool '<tool>' outside its package; GOL-34 supports same-package tool shapes only///|
#derive.tool_middleware("file-adapter", presented="PublicFiles", expected="Storage")
struct FileAdapter {}
///|
pub async fn FileAdapter::read(
underlying : StorageUnderlying,
path : String,
) -> Result[String, @toolMiddleware.ToolInvokeError[@tool.NoToolError]] {
underlying.fetch("files/" + path)
}///|
let policy = try! @api.Policy::exponential(@api.Duration::millis(100), 2.0)
.max_retries(4)
.only_when(
@api.Predicate::eq(@api.Props::error_type(), @api.Value::text("transient")),
)
.to_raw()
///|
let result = @api.retry_local(policy, () => call_remote_service(), properties=error => {
[("error-type", @api.PredicateValue::Text(error.kind()))]
})| Package | Description |
|---|---|
| agents | Agent registry, RawAgent trait, register_agent, dispatch runtime |
| schema | IntoSchema / FromSchema traits and impls for primitives, Option, Array, Result, records/enums/variants, rich types, and UnstructuredText / UnstructuredBinary |
| schema_model | The recursive SchemaType / SchemaValue model + SchemaGraph / SchemaBuilder and WIT (golem:core/types@2.0.0) conversions |
| multimodal | Multimodal[T] + MultimodalModality trait (schema-native list<variant> with role = multimodal) |
| config | Code-first configuration (Config[T], Secret[T], #derive.config) |
| errors | AgentError construction/decoding helpers |
| logging | Structured logging with named loggers and level filtering |
| context | Span-based tracing and invocation context |
| rpc | Agent-to-agent RPC helpers |
| http | Canonical HttpRequest, HttpResponse, HttpHeader, openapi_json, and outbound WASI HTTP |
| reflection | Runtime discovery, reflected JSON packing, caller-defined static clients, and fully dynamic value invocation |
| tool-core | Host-neutral tool descriptors, schemas, canonical input handling, and error model |
| tool | Ordinary tool registry, dispatch, help rendering, and ambient typed RPC client runtime |
| tool-middleware | Host-neutral middleware registry, opaque invocation carriers, typed/universal underlying capabilities, and ownership enforcement |
| interface/ | WIT-generated bindings (Golem host APIs, WASI interfaces) |
| gen/ | WIT-generated WASM export glue code |
Install
Download zipGolem SDK for MoonBit — build durable, fault-tolerant agents on the Golem platform