An actor protocol is the typed set of messages an actor accepts: its API and the only route by which other actors communicate with it. A behavior such as Behavior[Int] accepts integers; sending another type fails at compile time. This makes protocol changes safer during refactoring because stale send sites are caught before the application runs. section 2.2 section 2.2.3 section 2.6
Begin with a narrow protocol, then model real operations as a sealed message hierarchy. A wallet can expose Command messages such as Increase(amount) and Decrease(amount), while its behavior handles each message sequentially and returns the behavior for the next message. Sealing the hierarchy lets the compiler warn when pattern matching misses a case. section 2.3
object WalletState {
sealed trait Command
final case class Increase(amount: Int) extends Command
final case class Decrease(amount: Int) extends Command
...
}
This message hierarchy makes the actor’s accepted commands explicit and gives the behavior a single protocol type. section 2.3
Keep request and reply directions distinct:
- Commands define messages that callers may send to the actor and therefore determine its actor type. section 3.1.7
- Responses are produced by the actor for another actor; they are not messages that callers can send back to the worker. section 3.1.7
- Include an ActorRef for replies in a command when a worker must report a result; a manager can adapt that response into one of its own protocol messages. section 3.1.6
Wallet commands and worker replies
A wallet begins with an Int protocol, then becomes a Command protocol with Increase and Decrease. Separately, a worker accepts Parse(replyTo, text) and sends Done(text) to the supplied reply address. The manager uses a message adapter to translate Worker.Done into a message it can receive, preserving each actor’s own protocol boundary. section 2.2.1 section 2.3 section 3.1.6
