A quick look at decentralized multi-agent logic on the .me kernel (this.me@4.2.0). Every line below comes from the live demos and was run against the published kernel.
There is no global database. Each robot runs its own kernel: Oli (miner) and Tiko (light scout) live on the rock B 612, and Lua (scientist) lives on B 325. A pointer (->) links a robot to its home rock, and reads pass through it.
// Oli's kernel, as set up by the Space demome.robots[1].name("Oli")me.robots[1].role("miner")me.rocks.b612.name("B 612")me.robots[1].home["->"]("rocks.b612")me.robots[1].batteries[1].capacity(60)me.robots[1].batteries[1].charge(60)me.robots[1].batteries[2].capacity(40)me.robots[1].batteries[2].charge(22)me("robots.1.home.name") // → "B 612"
Behaviour is written as rules (=), one text per rule, installed for every robot with the [i] template. The battery level is a 4.2 collection aggregate: batteries[] counts the batteries and batteries[].charge sums their charge. Reads run in-process, with no network call.
me.robots["[i]"]["="]("battery", "robots[i].batteries[].charge / robots[i].batteries[].capacity * 100")me.robots["[i]"]["="]("reserve", "lightDist * costPerRad + margin")me.robots["[i]"]["="]("mustCharge", "battery < reserve")me.robots["[i]"]["="]("charged", "battery >= full")me.robots["[i]"]["="]("goCharge", "mustCharge || charging && !charged")me("robots.1.batteries[]") // → 2me("robots.1.batteries[].charge") // → 82me("robots.1.battery") // → 82// plug in a third battery: the rule stays the sameme.robots[1].batteries[3].capacity(30)me.robots[1].batteries[3].charge(30)me("robots.1.battery") // → 86.15384615384616
The demo now also has a flower on B 612. Oli and Tiko water it only when their own rule allows it:
me.robots["[i]"]["="]("shouldWaterFlower", "flowerThirsty && explore && battery > reserve")me.objects.flower.water(35)me("robots.1.shouldWaterFlower") // → true
Lua has never seen the flower, so in Lua’s kernel the same rule stays undefined.
The same ice, the same rule text, three kernels:
me.robots["[i]"]["="]("iceIsFuel", "mines && objects.ice.seen")me.robots["[i]"]["="]("iceIsHazard", "slips && objects.ice.seen")me.robots["[i]"]["="]("iceIsSample", "studies && objects.ice.seen")me.objects.ice.seen(true)// [iceIsFuel, iceIsHazard, iceIsSample]// Oli (miner): [true, false, false] → fuel// Tiko (light scout): [false, true, false] → hazard// Lua (scientist): [false, false, true] → sample
ContextLab shows the same idea in a single kernel. Four robots point at one canister through different context pointers:
me.robots[id].target["->"]("objects.canister7")me.robots[id].context["->"](input.contextPath) // warehouse, hospital, street, operatingRoomme.robots["[i]"]["="]("canProceed", "canLift && softGripReady && !needsHumanReview && contextAllowsMotion")
Before the live updates, only -1 can proceed: NurseBot-2 needs a sterile check, Courier-3 must yield to traffic, and SurgeonBot-4 also needs a sterile check. After the canister is sterilized and the street clears, all four can proceed. The data is never copied. Pointers change what an object means to each robot; who can read it is decided separately, by secret scopes (_) and me.as(key).
Oli walks into the dark and its batteries run low. You can ask why it decided to charge:
me.robots[1].lightDist(1.2)me.robots[1].batteries[1].charge(10)me.robots[1].batteries[2].charge(0)me.robots[1].batteries[3].charge(0)me("robots.1.battery") // → 7.6923076923076925me("robots.1.reserve") // → 17.85596me.explain("robots.1.goCharge")
{"path": "robots.1.goCharge","value": true,"expr": "mustCharge || charging && !charged","derivation": {"expression": "mustCharge || charging && !charged","inputs": [{ "label": "mustCharge", "path": "robots.1.mustCharge", "value": true, "origin": "public", "masked": false, "status": "resolved" },{ "label": "charging", "path": "robots.1.charging", "value": false, … },{ "label": "charged", "path": "robots.1.charged", "value": false, … }]},"meta": {"dependsOn": ["robots.1.mustCharge", "robots.1.charging", "robots.1.charged"],"lastComputedAt": 1791598177492,"k": 4,"recomputed": ["robots.1.battery", "robots.1.mustCharge", "robots.1.charged", "robots.1.goCharge"],"changed": ["robots.1.battery", "robots.1.mustCharge", "robots.1.goCharge"],"sourcePath": "robots.1.batteries.3.charge",…}}
explain("robots.1.battery") also shows the aggregate: { "collection": "robots.1.batteries", "field": "charge", "op": "sum", "coverage": "public-view", "status": "resolved", "members": 3, "terms": 3, … }.
Autonomous Robotics in Space · .me
Robots that Understand Context - live demo
Autonomous Robots in Space was originally published in Towards AI on Medium, where people are continuing the conversation by highlighting and responding to this story.