Agents — Mapanare

Concurrent actors with typed channels — the fundamental concurrency primitive in Mapanare.

Overview

Agents are concurrent actors that encapsulate state and communicate exclusively through typed message channels. There is no shared mutable state between agents. They run independently, and the compiler understands their lifecycle, channel types, and message flow.

Defining an Agent

agent Counter {
    input increment: Int
    output count: Int
    let mut state: Int = 0
    fn handle(increment: Int) -> Int {
        self.state += increment
        return self.state
    }
    fn on_init() { }
    fn on_stop() { }
}

input and output declare typed channels. handle is called when input arrives. on_init and on_stop are optional lifecycle hooks.

Spawning and Communication

fn main() {
    let counter = spawn Counter()
    counter.increment <- 5       // send (non-blocking)
    let result = sync counter.count  // receive (blocking)
    print(result)  // 5
}

spawn creates and starts an agent. <- sends a message (non-blocking, queued). sync blocks until output.

Lifecycle

init → running → paused → stopped

Native LLVM Backend

When compiled to native code: OS threads (one per agent), lock-free SPSC ring buffers for channels, semaphore scheduling, arena memory management.

Backpressure

When an agent's input buffer reaches capacity, the sender is notified. Strategies: blocking (default), dropping, or timeout with Result.

Supervision

let worker = spawn MyAgent() @restart(policy: "always", max: 3, window: 60)

Policies: always, never, transient.

Multi-Agent Pipelines

pipe ClassifyText { Tokenizer |> Classifier }