soma.cell

A population simulation in rounds: every agent of a round sees the same

world (snapshot), results are applied at the end in input order (apply), random() is seeded per task, and each agent remembers its last round (instance) — the same seed gives the same simulation, run after run. on_done starts the next round. Run: SOMA_LLM_MOCK=echo soma run horde_rounds.cell main 1000 10 Test: SOMA_LLM_MOCK=echo soma test horde_rounds.cell

A Soma program from the agents part of the verified corpus: 62 lines, cells Market, Shopper, RoundsTest. It passes soma check with soma 3.2.4.

How it is built

The cell Market keeps 2 memory slots: state (Map<String, Int>, persistent) and history (List<String>, persistent). Handlers: main (line 15), start_round (line 21) and report (line 42). Private helpers: _apply and _close.

The cell Shopper has no face and no memory. Handlers: decide (line 46).

The file also holds 1 test cell (RoundsTest) with 1 assertion, run by soma test.

Generated from soma describe on this file.

The source

soma.toml

[package]
name = "agents-corpus"
version = "0.1.0"
description = "Verified AI-agent example cells (training corpus)"

# Agent LLM config. `mock = "echo"` keeps every example in this directory
# hermetic: `soma test` / `soma run` need no network and no API key, and
# results are deterministic. For a live run, delete the `mock` line (or
# override with SOMA_LLM_MOCK) and provide the key via env.
[agent]
provider = "anthropic"
model    = "claude-opus-4-6"
key      = "${ANTHROPIC_API_KEY}"
mock     = "echo"

# Termination proof for verified_termination.cell's `workflow` machine:
# every path eventually reaches a terminal, no deadlocks.
# `cells` scopes these properties to Solver — the other agents in this
# directory have their own state names and must not inherit them.
[verify]
cells = ["Solver"]
deadlock_free = true
eventually    = ["done", "failed"]

[verify.after.understanding]
eventually = ["solving", "failed"]

[verify.after.solving]
eventually = ["verifying", "failed"]

[verify.after.verifying]
eventually = ["done", "failed"]

horde_rounds.cell

// A population simulation in rounds: every agent of a round sees the same
// world (snapshot), results are applied at the end in input order (apply),
// random() is seeded per task, and each agent remembers its last round
// (instance) — the same seed gives the same simulation, run after run.
// on_done starts the next round.
//
// Run:  SOMA_LLM_MOCK=echo soma run horde_rounds.cell main 1000 10
// Test: SOMA_LLM_MOCK=echo soma test horde_rounds.cell

cell Market {
    memory {
        state: Map<String, Int> [persistent]
        history: List<String> [persistent]
    }
    on main(n: Int, rounds: Int) {
        state.set("n", n)
        state.set("last", rounds)
        state.set("round", 1)
        return start_round()
    }
    on start_round() {
        let r = state.get("round") ?? 1
        let price = state.get("price") ?? 60
        let people = range(0, state.get("n") ?? 10) |> map(i => map("id", "p{i}"))
        return horde(Shopper.decide, people, map(
            "snapshot", map("price", price), "apply", "_apply", "on_done", "_close",
            "seed", 100 + r, "instance", "id", "concurrency", 100, "budget_tokens", 500000))
    }
    on _apply(res: Map) { state.set("demand", (state.get("demand") ?? 0) + res.buy) }
    on _close(h: String) {
        let d = state.get("demand") ?? 0
        let p = state.get("price") ?? 60
        let n = state.get("n") ?? 1
        let next = if d * 2 > n { p + 1 } else { p - 1 }
        state.set("price", next)
        history.push("demand {d} → price {next}")
        state.set("demand", 0)
        let r = (state.get("round") ?? 1) + 1
        state.set("round", r)
        if r <= (state.get("last") ?? 1) { start_round() }
    }
    on report() { return history }
}

cell agent Shopper {
    on decide(me: Map, world: Map) [task] {
        let mood = think("The price is {world.price}. Buy?", map("max_tokens", 20))
        let paid_before = recall("last_price") ?? world.price
        remember("last_price", world.price)
        let patience = random(30)
        let buy = if world.price <= paid_before + 1 && world.price < 50 + patience { 1 } else { 0 }
        return map("id", me.id, "buy", buy)
    }
}

cell test RoundsTest {
    rules {
        let h = Market.main(30, 3)
        assert len(Market.report()) == 3
    }
}

What the toolchain says

Run on a fresh copy of the program at build time; the outputs are pasted unedited.

$ soma check horde_rounds.cell
warning: agent cell 'Shopper' has no state machine — add a state section for verified behavior
✓ 1 warning(s), no errors.
$ soma test horde_rounds.cell
test RoundsTest ...
  ✓ assert len(Market.report()) == 3

1 tests: 1 passed, 0 failed
$ soma verify horde_rounds.cell
Verifying horde_rounds.cell...
note: soma.toml [verify] cells names 'Solver', which this file does not define — its properties are not checked here

Market/termination:

  ⚠ `main` calls `Market.start_round`, which may not terminate
  ⚠ handler `start_round`: mutual recursion start_round → _close → start_round without a provable decreasing measure
  ⚠ handler `_close`: mutual recursion _close → start_round → _close without a provable decreasing measure

0 passed, 3 warnings, 0 failures
  ✓ cost: horde(Shopper.decide, …) in `start_round` ≤ 500000 tokens — budget_tokens: every think() of its tasks and callbacks reserves its bound first (a hard ceiling while the provider honors max_tokens)
soma.toml: 4 user-defined properties loaded — NONE applies to this file ([verify] cells = ["Solver"] names no cell of it)
Temporal: 0 passed, 0 failed
note: state machines are verified per cell. A value crosses a cell boundary by a face contract (`requires` / `ensures` on the signal); a rule between two cells' machines is proven when soma.toml states it — `[verify.before."Pay.paid"] requires = ["Approval.signed_off"]` explores the product of the machines.
VERIFY OK

Builtins used

horde, len, map, random, range, recall, remember, think

Source file: /corpus/agents/horde_rounds.cell · examples/corpus/agents/horde_rounds.cell