Creating Ephemeral Agents with Effect
An ephemeral agent gets a fresh implementation for every invocation. Its agent id fields still describe its logical identity, but values captured by one invocation's handlers are discarded when that invocation completes. The oplog remains available for inspection, but Golem does not replay it to recover an ephemeral agent.
Use ephemeral agents for independent request handling, transformations, validation, adapters, and other work where one call must not depend on an earlier call. Use a durable agent instead for counters, carts, workflows, long-running orchestration, or external operations that require durable recovery.
Define and Implement the Agent
Set mode: "ephemeral" in defineAgent(...). Declare constructor and method contracts with Effect
Schema, return Effect values from every handler, and omit snapshot for a stateless agent:
import { Effect, Schema } from "effect";
import { defineAgent, method } from "@golemcloud/effect-golem";
export const TextProcessorAgent = defineAgent({
name: "TextProcessorAgent",
mode: "ephemeral",
id: {
processorName: Schema.String,
},
methods: {
toUpper: method({
input: { input: Schema.String },
success: Schema.String,
}),
toLower: method({
input: { input: Schema.String },
success: Schema.String,
}),
},
}).implement({
init: () => Effect.void,
methods: () => ({
toUpper: ({ input }) => Effect.succeed(input.toUpperCase()),
toLower: ({ input }) => Effect.succeed(input.toLowerCase()),
}),
});
The .implement({ init, methods }) call registers the agent eagerly when the module is evaluated. Import the
implementation module from the component entry point so registration occurs:
// src/main.ts
import "./text-processor-agent.js";
Generated Effect projects use ESM and NodeNext module resolution, so local imports use the emitted
.js suffix.
Fresh Invocation Semantics
For every invocation, Golem:
- Starts a fresh ephemeral agent instance.
- Runs
initand thenmethodsto obtain that instance's handlers. - Runs the requested handler.
- Discards the instance and its captured in-memory values.
Do not add Snapshot.define(...) or create mutable state merely to
represent a stateless handler. Omitting snapshot disables snapshotting. If calls must observe or
update shared state, the agent is not stateless; use a durable agent and the normal snapshot-backed
state pattern instead.
Effect and CLI Conventions
- Import Effect APIs from
effectand Golem APIs from@golemcloud/effect-golem. - Use
Schemavalues for agent id fields, method parameters, successes, and typed errors. - Handlers receive named parameter records and return Effects; do not use plain
asyncor Promise-returning handlers from the non-Effect TypeScript SDK. - Method names use TypeScript casing. For the example above, invoke
toUpperandtoLower, not snake_case names. - Effect components report TypeScript as their source language, so CLI agent IDs and method arguments use TypeScript value syntax.
- Constructor parameters remain part of the CLI agent ID. The example is addressed as
TextProcessorAgent("processor-1"). - Ephemeral agents can still expose HTTP routes, call other agents, and use Golem host APIs; ephemeral mode changes instance lifetime and recovery, not the available capabilities.
- Do not call a runner or registration helper. The top-level
.implement({ ... })call plus thesrc/main.tsside-effect import is the registration path.
Choosing Ephemeral Mode
Choose mode: "ephemeral" when every invocation is independent and losing its in-memory values at
the end of the call is intentional. Keep the default durable mode when:
- a result depends on an earlier invocation;
- an agent coordinates a workflow or saga;
- state must survive suspension, failure, or update; or
- host-operation replay and durable recovery are part of the correctness model.