MailboxProcessor

Agents serialize access to state. Each processes one message at a time. Use inbox.Scan/TryReceive for selective or timed receives. For distributed actors, see Akka.NET (with Akkling for F#) or Orleans.

// Agents: message-processing actors with private state (no locks needed)
type CounterMsg =
    | Increment of int
    | Get of AsyncReplyChannel<int>
    | Reset

let counter =
    MailboxProcessor.Start(fun inbox ->
        let rec loop count = async {
            let! msg = inbox.Receive()
            match msg with
            | Increment n -> return! loop (count + n)
            | Get reply ->
                reply.Reply count
                return! loop count
            | Reset -> return! loop 0
        }
        loop 0)

counter.Post (Increment 5)
counter.Post (Increment 3)
counter.PostAndReply Get                       // 8
counter.PostAndAsyncReply Get |> Async.RunSynchronously
counter.Post Reset

// A bank account agent that serializes concurrent operations
type AccountMsg =
    | Deposit of decimal
    | Withdraw of decimal * AsyncReplyChannel<Result<decimal, string>>
    | Balance of AsyncReplyChannel<decimal>

let account = MailboxProcessor.Start(fun inbox ->
    let rec loop balance = async {
        match! inbox.Receive() with
        | Deposit amt -> return! loop (balance + amt)
        | Withdraw (amt, reply) when amt <= balance ->
            reply.Reply (Ok (ba
…