Skip to content

Behaviors as Values

In most actor frameworks, an actor is defined by subclassing a base class and overriding a receive method. Casty takes a different approach: behaviors are values, not classes.

A behavior is a frozen dataclass that describes how an actor processes messages. You compose behaviors using the Behaviors factory:

Factory Purpose
Behaviors.receive(handler) Create a behavior from an async message handler (ctx, msg) -> Behavior
Behaviors.setup(factory) Run initialization logic with access to ActorContext, then return the real behavior
Behaviors.ignore() Accept any message and keep the current behavior — useful for terminal states
Behaviors.same() Keep the current behavior unchanged (returned from a message handler)
Behaviors.stopped() Stop the actor gracefully
Behaviors.unhandled() Signal that the message was not handled
Behaviors.restart() Explicitly restart the actor
Behaviors.supervise(behavior, strategy) Wrap a behavior with a supervision strategy
Behaviors.with_lifecycle(behavior, ...) Attach lifecycle hooks (pre_start, post_stop, etc.)
Behaviors.event_sourced(...) Persist actor state as a sequence of events
Behaviors.persisted(events) Return from a command handler to persist events and update state
Behaviors.sharded(entity_factory, ...) Distribute entities across cluster nodes via sharding
Behaviors.singleton(factory) Run exactly one actor instance across the cluster
Behaviors.broadcasted(behavior) Enable broadcasting messages to all instances across the cluster
Behaviors.discoverable(behavior, key=...) Auto-register the actor with the cluster receptionist on spawn
Behaviors.spy(behavior, observer) Observe all messages an actor processes

Because behaviors are values, they compose naturally. A behavior can be wrapped with supervision, decorated with lifecycle hooks, and backed by event sourcing — all through function composition, not class inheritance.


Next: Functional State