On this page

Many agents writing code at once๏ƒ

๐Ÿ”ต Expert ยท Lesson 21

REAL CODEGEN, AND SEVERAL AGENTS DOING IT AT ONCE. Expert 12 drove the loop once, on one thread. This is the shape melder is actually built for: four agents, four rooms, one shared world, concurrent.

HOW DATA COMES BACK OUT OF GENERATED CODE The executor runs the source in a controlled namespace and lifts ONE name out of it:

code = "total = 0\nfor n in range(1, 101):\n total += n\n" "result = total\n" payload = commands.execute_codegen(code, frame_name=...) payload["result"] # 5050

result is the convention, not a guess - CodegenExecutionResult is built with result= taken from the namespace after the code runs. Anything else the code computed stays in the sandbox and dies with it. One name out means the boundary is a value, not a scope an agent can leak through.

THE PAYLOAD IS A VERDICT, NOT A RETURN VALUE accepted and frame_name are always there; reason, runtime_error, validation_issues and result fill in according to what happened. So the SAME shape describes a refusal, a crash, and a success - an agent branches on accepted instead of catching, exactly as expert 12 established.

FOUR AGENTS, FOUR ROOMS, ONE WORLD Each agent opens its OWN rift, so it gets its own room, its own workstation, and its own memory. What they SHARE is the target frame - the world their code lands in. That is the isolation melder actually offers: private benches, shared world.

WHAT IS AND IS NOT SERIALIZED Nothing in this lesson opens a transaction, because generated code that computes a value mutates no structure. Melder serializes STRUCTURAL change; arithmetic in a sandbox is not structural, so four agents run genuinely in parallel and none of them waits. The moment one of them binds or links, the plane underneath arbitrates - and still none of this vocabulary appears in the agent's code.

A ROOM'S MEMORY IS ITS OWN Subscribe on one room and you see that room's commands. The other three are running the same verbs at the same time and none of them appears in your log. Per-agent audit falls out of per-agent rooms rather than being a feature anyone had to add.

Before you run๏ƒ

Use the Expert guide for prerequisite concepts. Run from a checkout with Melder installed and Python 3.14 free-threading selected. The collection download includes the level's local helper modules.

Run the saved script๏ƒ

python UX_and_AIX_experiences/04_expert/21_many_agents_writing_code_at_once.py
py -3.14t UX_and_AIX_experiences/04_expert/21_many_agents_writing_code_at_once.py

Download this collection ยท Source on GitHub

Public surface๏ƒ

several codegen rifts driven from threads, validate_codegen / execute_codegen payloads, the result namespace lift, and per-room memory

Code๏ƒ

  1"""
  2TIER: expert (21)
  3GOAL: REAL CODEGEN, AND SEVERAL AGENTS DOING IT AT ONCE. Expert 12 drove
  4      the loop once, on one thread. This is the shape melder is actually
  5      built for: four agents, four rooms, one shared world, concurrent.
  6
  7      HOW DATA COMES BACK OUT OF GENERATED CODE
  8      The executor runs the source in a controlled namespace and lifts
  9      ONE name out of it:
 10
 11          code = "total = 0\\nfor n in range(1, 101):\\n    total += n\\n"
 12                 "result = total\\n"
 13          payload = commands.execute_codegen(code, frame_name=...)
 14          payload["result"]        # 5050
 15
 16      `result` is the convention, not a guess - `CodegenExecutionResult`
 17      is built with `result=` taken from the namespace after the code
 18      runs. Anything else the code computed stays in the sandbox and
 19      dies with it. One name out means the boundary is a value, not a
 20      scope an agent can leak through.
 21
 22      THE PAYLOAD IS A VERDICT, NOT A RETURN VALUE
 23      `accepted` and `frame_name` are always there; `reason`,
 24      `runtime_error`, `validation_issues` and `result` fill in
 25      according to what happened. So the SAME shape describes a refusal,
 26      a crash, and a success - an agent branches on `accepted` instead
 27      of catching, exactly as expert 12 established.
 28
 29      FOUR AGENTS, FOUR ROOMS, ONE WORLD
 30      Each agent opens its OWN rift, so it gets its own room, its own
 31      workstation, and its own memory. What they SHARE is the target
 32      frame - the world their code lands in. That is the isolation
 33      melder actually offers: private benches, shared world.
 34
 35      WHAT IS AND IS NOT SERIALIZED
 36      Nothing in this lesson opens a transaction, because generated code
 37      that computes a value mutates no structure. Melder serializes
 38      STRUCTURAL change; arithmetic in a sandbox is not structural, so
 39      four agents run genuinely in parallel and none of them waits.
 40      The moment one of them binds or links, the plane underneath
 41      arbitrates - and still none of this vocabulary appears in the
 42      agent's code.
 43
 44      A ROOM'S MEMORY IS ITS OWN
 45      Subscribe on one room and you see that room's commands. The other
 46      three are running the same verbs at the same time and none of them
 47      appears in your log. Per-agent audit falls out of per-agent rooms
 48      rather than being a feature anyone had to add.
 49SURFACE EXERCISED: several codegen rifts driven from threads,
 50                   validate_codegen / execute_codegen payloads, the
 51                   `result` namespace lift, and per-room memory
 52VERIFY: rides the owner's 3.14t harness; asserts are the contract.
 53"""
 54import threading
 55
 56import melder as md
 57
 58
 59class Meter:
 60    def __init__(self) -> None:
 61        self.reading = 1
 62
 63
 64# Four DIFFERENT jobs - this is generated source, the kind an agent
 65# actually emits: it computes something and leaves it in `result`.
 66JOBS = {
 67    "adder": (
 68        "total = 0\n"
 69        "for n in range(1, 101):\n"
 70        "    total += n\n"
 71        "result = total\n"
 72    ),
 73    "counter": (
 74        "hits = []\n"
 75        "for n in range(60):\n"
 76        "    if n % 7 == 0:\n"
 77        "        hits.append(n)\n"
 78        "result = len(hits)\n"
 79    ),
 80    "builder": (
 81        "parts = []\n"
 82        "for n in range(5):\n"
 83        "    parts.append(str(n * n))\n"
 84        "result = '-'.join(parts)\n"
 85    ),
 86    "reducer": (
 87        "value = 1\n"
 88        "for n in range(1, 8):\n"
 89        "    value = value * n\n"
 90        "result = value\n"
 91    ),
 92}
 93
 94EXPECTED = {"adder": 5050, "counter": 9, "builder": "0-1-4-9-16",
 95            "reducer": 5040}
 96
 97FRAME = "factory-world"
 98
 99
100def _open_room(nexus, agent_name: str):
101    """One agent's private room, pointed at the shared world."""
102    configuration = nexus.create_rift_configuration()
103    configuration.with_space_type("codegen")
104    rift = nexus.create_rift(configuration=configuration,
105                             rift_name=f"agent-{agent_name}")
106    rift.mark_active()
107    rift.create_frame_link(FRAME)
108    return rift.space
109
110
111def main() -> None:
112    # THE SHARED WORLD. One frame, postured for codegen (expert 11).
113    book = md.Spellbook(aetheric_frame=FRAME)
114    book.bind(spell=Meter, existence="unique", binding_name="factory-meter")
115    book.configure_aether_frame(
116        system_state="dynamic",
117        disposal=None,
118        disposal_method_names=None,
119        rift_enabled=True,
120        ai_native=True,
121    )
122    book.conjure(name="factory-root")
123
124    nexus = md.Nexus()
125    system_configuration = nexus.create_configuration()
126    system_configuration.with_rift_creation_enabled(True)
127    system_configuration.with_allowed_target_frame_names([FRAME])
128    system_configuration.with_multiple_target_frames(True)
129    system_configuration.with_max_target_frame_count(4)
130    nexus.activate(system_configuration)
131    print("one shared world:", FRAME)
132
133    # ONE AGENT FIRST, SLOWLY, SO THE PAYLOAD IS VISIBLE.
134    solo = _open_room(nexus, "solo")
135    verdict = solo.command_system.validate_codegen(
136        JOBS["adder"], frame_name=FRAME,
137    )
138    print()
139    print("validate ->", verdict)
140    assert verdict["accepted"] is True
141
142    payload = solo.command_system.execute_codegen(
143        JOBS["adder"], frame_name=FRAME,
144    )
145    print("execute  -> keys:", sorted(payload))
146    assert payload["accepted"] is True
147    assert payload["frame_name"] == FRAME
148    assert payload["result"] == 5050
149    print("execute  -> result:", payload["result"])
150    print("  the code set `result`; the executor lifted THAT ONE NAME out")
151    print("  everything else it computed died with the sandbox")
152
153    # NOW FOUR AGENTS AT ONCE, EACH IN ITS OWN ROOM.
154    rooms = {}
155    outcomes = {}
156    errors = []
157    guard = threading.Lock()
158    ready = threading.Barrier(len(JOBS))
159
160    def run_agent(agent_name: str) -> None:
161        try:
162            room = _open_room(nexus, agent_name)
163            with guard:
164                rooms[agent_name] = room
165            # Line them up so the executions genuinely overlap.
166            ready.wait(timeout=10)
167            result = room.command_system.execute_codegen(
168                JOBS[agent_name], frame_name=FRAME,
169            )
170            with guard:
171                outcomes[agent_name] = result
172        except Exception as error:  # noqa: BLE001 - reported, not swallowed
173            with guard:
174                errors.append((agent_name, repr(error)))
175
176    threads = [
177        threading.Thread(target=run_agent, args=(name,), name=f"agent-{name}")
178        for name in JOBS
179    ]
180    for thread in threads:
181        thread.start()
182    for thread in threads:
183        thread.join(timeout=30)
184
185    assert not errors, f"agent failures: {errors}"
186    assert len(outcomes) == len(JOBS)
187    print()
188    print("four agents ran their own code concurrently:")
189    for agent_name in sorted(outcomes):
190        result = outcomes[agent_name]
191        assert result["accepted"] is True
192        assert result["result"] == EXPECTED[agent_name]
193        print(f"   {agent_name:<8} -> {result['result']!r}")
194    print("  none of them waited on another - computing a value is not")
195    print("  a structural change, so there was nothing to serialize")
196
197    # PRIVATE BENCHES. Four rooms, four workstations, four ids.
198    workstation_ids = {name: room.workstation.workstation_id
199                       for name, room in rooms.items()}
200    assert len(set(workstation_ids.values())) == len(rooms)
201    print()
202    print("four rooms ->", len(set(workstation_ids.values())),
203          "distinct workstations")
204    print("  private bench each, one shared world - that is the isolation")
205
206    # AND A ROOM'S MEMORY IS ITS OWN. Subscribe on one; run on two.
207    watcher = rooms[sorted(rooms)[0]]
208    other = rooms[sorted(rooms)[1]]
209    seen = []
210    subscription = watcher.memory_system.register_memory_callback(seen.append)
211    assert watcher.memory_system.memory_enabled is True
212
213    watcher.command_system.execute_codegen(JOBS["adder"], frame_name=FRAME)
214    other.command_system.execute_codegen(JOBS["adder"], frame_name=FRAME)
215
216    print()
217    print("subscribed to ONE room, then ran in two:")
218    print("   records captured:", len(seen))
219    print("  the other room's identical call is absent - per-agent audit")
220    print("  falls out of per-agent rooms, nobody had to build it")
221    watcher.memory_system.unregister_memory_callback(subscription)
222
223    print()
224    print("four agents, four benches, one world, no ceremony")
225    print("`result` is the whole boundary: one value out, nothing leaks")
226
227
228if __name__ == "__main__":
229    main()

Check the outcome๏ƒ

The script contains its own assertions or demonstrated refusal paths. Run it to evaluate those checks against your installed version. The code above is taken directly from the saved file; no run output is invented here.

More expert examples ยท Level guide