# Golem Stateless Agent Moonbit

> Creating ephemeral (stateless) agents in a MoonBit Golem project. Use when the user wants a stateless agent, a fresh instance per invocation, no shared state between calls, or a request-handler style agent.

- Skill: `golemcloud/golem-stateless-agent-moonbit` (Agent Skill)
- Install (CLI): `npx skillmds@latest add golemcloud/golem-stateless-agent-moonbit`
- Raw SKILL.md: https://api.skillmd.com/api/skills/golemcloud/golem-stateless-agent-moonbit/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: golemcloud (https://skillmd.com/u/golemcloud)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/golemcloud/golem-stateless-agent-moonbit

---


# Creating Ephemeral (Stateless) Agents (MoonBit)

## Overview

An **ephemeral agent** is a Golem agent that gets a **fresh instance for every invocation**. Unlike the default durable agents, ephemeral agents:

- **No shared state**: Each invocation starts from a clean `new()` — field values set in one call are gone by the next
- **No replay**: An oplog is still recorded lazily (useful for debugging via `golem agent oplog`), but it is never used for replay — no automatic recovery on failure
- **No persistence**: The agent's memory is discarded after each invocation completes
- **Same identity model**: The agent is still addressed by its constructor parameters, but every call behaves as if the agent was just created

This makes ephemeral agents ideal for **pure request handlers**, **stateless transformers**, **adapters**, and **serverless-style functions** where each call is independent.

## How to Create an Ephemeral Agent

Use `#derive.agent("ephemeral")` instead of `#derive.agent`:

```moonbit
#derive.agent("ephemeral")
struct RequestHandler {
}

fn RequestHandler::new() -> RequestHandler {
  {  }
}

pub fn RequestHandler::handle(self: Self, input: String) -> String {
  "processed: " + input
}
```

## What "Fresh Instance Per Invocation" Means

Consider a durable agent vs an ephemeral one:

```moonbit
// DURABLE (default) — state accumulates across calls
#derive.agent
struct DurableCounter {
  mut count: UInt
}

fn DurableCounter::new() -> DurableCounter {
  { count: 0 }
}

pub fn DurableCounter::increment(self: Self) -> UInt {
  self.count = self.count + 1
  self.count
}

// Call increment() three times → returns 1, 2, 3

// EPHEMERAL — state resets every call
#derive.agent("ephemeral")
struct EphemeralCounter {
  mut count: UInt
}

fn EphemeralCounter::new() -> EphemeralCounter {
  { count: 0 }
}

pub fn EphemeralCounter::increment(self: Self) -> UInt {
  self.count = self.count + 1
  self.count
}

// Call increment() three times → returns 1, 1, 1
```

Each invocation of an ephemeral agent:
1. Calls `new()` to create a fresh instance
2. Executes the method
3. Discards the instance entirely

## When to Use Ephemeral Agents

| Use Case | Why Ephemeral? |
|----------|---------------|
| Stateless HTTP API (REST adapter, proxy) | No state to persist between requests |
| Data transformation / format conversion | Pure function — input in, output out |
| Validation service | Each validation is independent |
| Webhook receiver that forwards events | No need to remember previous webhooks |
| Stateless computation (math, encoding) | No side effects worth persisting |

## When NOT to Use Ephemeral Agents

- **Counters, accumulators, shopping carts** — need state across calls → use durable (default)
- **Workflow orchestrators, sagas** — need oplog for recovery → use durable (default)
- **Agents calling external APIs** where at-least-once semantics matter → use durable (default)
- **Any agent where one call's result depends on a previous call** → use durable (default)

## Key Points

- Ephemeral mode is set at the **agent type level** — all instances of the type are ephemeral
- Constructor parameters still define identity — you can have multiple ephemeral agents with different parameters
- Ephemeral agents can still call other agents via RPC, make HTTP requests, and use all Golem APIs
- The oplog is still recorded lazily, so you can inspect what an ephemeral agent did via `golem agent oplog` — but it is never replayed
- **Never edit generated files** — `golem_reexports.mbt`, `golem_agents.mbt`, and `golem_derive.mbt` are auto-generated by `golem build`

