Orb is a programming language in which every program is a composition of finite-state behaviors represented as data. The compiler checks every path, and one source compiles to five platforms.
npx -y @almadar/orb mcpOrb provides a Model Context Protocol (MCP) server. Any MCP-capable agent can run it through npx and use its tools to write and check programs.
Build me a chat app in Orb.
Orb runs through npx. Register its MCP server with `npx -y @almadar/orb mcp install --client <your client>`, or start it directly with `npx -y @almadar/orb mcp`.
Then build with its tools: read `reference`, find behaviors with `behaviors` and `describe_behavior`, compose them, run `validate` until it reports 0 errors and 0 warnings, `play` the machine, and run it with `npx -y @almadar/orb serve <file>`.The checkout below is an Orb program from the standard library. Each step is a transition, and the diagram is generated from the same source.
trait CheckoutRules -> @rebindable Checkout [interaction, instance] {
state step1 {
INIT -> step1
(set @entity.customerName "")
(set @entity.email "")
(set @entity.orderTotal 0)
(set @entity.shippingAddress "")
(set @entity.status draft)
CHECKOUT_STARTED -> step1
(set @entity.customerName "")
(set @entity.email "")
(set @entity.orderTotal 0)
(set @entity.shippingAddress "")
(set @entity.status draft)
DRAFT -> step1
(set @entity.customerName ?data.customerName)
(set @entity.email ?data.email)
(emit CheckoutStepEntered {
customerName: ?data.customerName
email: ?data.email
step: step1
})
NEXT -> step2 when (and ?data.customerName ?data.email)
(set @entity.customerName ?data.customerName)
(set @entity.email ?data.email)
(emit CheckoutStepEntered {
customerName: ?data.customerName
email: ?data.email
step: step2
})
NEXT -> step1
(render-ui toast <Alert dismissible message={"Enter your name and email to continue."} variant={warning} />)
(emit CheckoutNextRefused { step: step1 })
}
state step2 {
INIT -> step1
(set @entity.customerName "")
(set @entity.email "")
(set @entity.orderTotal 0)
(set @entity.shippingAddress "")
(set @entity.status draft)
CHECKOUT_STARTED -> step1
(set @entity.customerName "")
(set @entity.email "")
(set @entity.orderTotal 0)
(set @entity.shippingAddress "")
(set @entity.status draft)
DRAFT -> step2
(set @entity.shippingAddress ?data.shippingAddress)
(emit CheckoutStepEntered {
customerName: @entity.customerName
email: @entity.email
shippingAddress: ?data.shippingAddress
step: step2
})
NEXT -> step3 when (and @entity.customerName @entity.email ?data.shippingAddress)
(set @entity.shippingAddress ?data.shippingAddress)
(emit CheckoutStepEntered {
customerName: @entity.customerName
email: @entity.email
shippingAddress: ?data.shippingAddress
step: step3
})
NEXT -> step2
(render-ui toast <Alert dismissible message={"Enter a shipping address to continue."} variant={warning} />)
(emit CheckoutNextRefused { step: step2 })
PREV -> step1
(emit CheckoutStepEntered { step: step1 })
}
state step3 {
INIT -> step1
(set @entity.customerName "")
(set @entity.email "")
(set @entity.orderTotal 0)
(set @entity.shippingAddress "")
(set @entity.status draft)
CHECKOUT_STARTED -> step1
(set @entity.customerName "")
(set @entity.email "")
(set @entity.orderTotal 0)
(set @entity.shippingAddress "")
(set @entity.status draft)
PAYMENT_DONE -> review when (and @entity.customerName @entity.email @entity.shippingAddress)
(emit CheckoutStepEntered {
customerName: @entity.customerName
email: @entity.email
orderTotal: @entity.orderTotal
shippingAddress: @entity.shippingAddress
step: review
})
PAYMENT_DONE -> step3
(render-ui toast <Alert dismissible message={"Complete the customer and shipping steps before paying."} variant={warning} />)
(emit CheckoutNextRefused { step: step3 })
PAYMENT_FAILED -> step3
(emit CheckoutPaymentFailed { code: ?code, error: ?error })
PREV -> step2
(emit CheckoutStepEntered {
customerName: @entity.customerName
email: @entity.email
shippingAddress: @entity.shippingAddress
step: step2
})
}
state review {
INIT -> step1
(set @entity.customerName "")
(set @entity.email "")
(set @entity.orderTotal 0)
(set @entity.shippingAddress "")
(set @entity.status draft)
CHECKOUT_STARTED -> step1
(set @entity.customerName "")
(set @entity.email "")
(set @entity.orderTotal 0)
(set @entity.shippingAddress "")
(set @entity.status draft)
COMPLETE -> complete when (and @entity.customerName @entity.email @entity.shippingAddress)
(set @entity.status placed)
(persist create Checkout @entity {
emit: { failure: CheckoutSaveFailed, success: CheckoutSaved }
})
(emit ORDER_PLACED {
customerName: @entity.customerName
email: @entity.email
id: @entity.id
orderTotal: @entity.orderTotal
shippingAddress: @entity.shippingAddress
})
(render-ui toast <Alert dismissible message={"Order placed successfully"} variant={success} />)
(emit CheckoutStepEntered { step: complete })
COMPLETE -> review
(render-ui toast <Alert dismissible message={"This order is missing details and can't be placed."} variant={warning} />)
(emit CheckoutNextRefused { step: review })
PREV -> step3
(emit CheckoutStepEntered {
customerName: @entity.customerName
email: @entity.email
shippingAddress: @entity.shippingAddress
step: step3
})
}
state complete {
INIT -> step1
(set @entity.customerName "")
(set @entity.email "")
(set @entity.orderTotal 0)
(set @entity.shippingAddress "")
(set @entity.status draft)
CHECKOUT_STARTED -> step1
(set @entity.customerName "")
(set @entity.email "")
(set @entity.orderTotal 0)
(set @entity.shippingAddress "")
(set @entity.status draft)
CheckoutSaved -> complete
CheckoutSaveFailed -> complete
(render-ui toast <Alert dismissible message={"Your order could not be completed — please contact support"} variant={error} />)
RESTART -> step1
(set @entity.customerName "")
(set @entity.email "")
(set @entity.orderTotal 0)
(set @entity.shippingAddress "")
(set @entity.status draft)
(emit CheckoutStepEntered { step: step1 })
}
emits {
ORDER_PLACED -> external {
id : string
customerName : string
email : string
shippingAddress : string
orderTotal : money
}
@description "Indicates a purchase order has been successfully submitted."
@synonyms "purchased, confirmed, completed, finalized"
@tier "domain"
CheckoutStepEntered {
step : string!
customerName : string
email : string
shippingAddress : string
orderTotal : money
}
@description "The wizard moved to a step; the payload carries what the step shows."
@synonyms "step changed, wizard advanced"
@tier "internal"
CheckoutNextRefused -> external {
step : string!
}
@description "A wizard step was refused because its required inputs are missing."
@synonyms "step refused, cannot continue"
@tier "domain"
CheckoutPaymentFailed {
error : string
code : string
}
@description "The card payment was declined; the payment step stays open for a retry."
@synonyms "payment failed, card declined"
@tier "domain"
CheckoutSaved -> internal {
id : string
}
@description "Indicates a checkout configuration has been successfully saved."
@synonyms "saved, persisted, stored"
@tier "presentation"
CheckoutSaveFailed -> internal {
error : string
code : string
}
@description "Indicates a failure during the saving of checkout data."
@synonyms "error, failure, problem, unsuccessful"
@tier "internal"
}
listens {
CheckoutPayment.ServiceStripeStripeCompleted -> PAYMENT_DONE
CheckoutPayment.ServiceStripeStripeFailed -> PAYMENT_FAILED
CHECKOUT_STARTED {
id : string!
}
@description "The customer chose to go to the full checkout wizard."
@synonyms "begin, start, purchase"
@tier "domain"
DRAFT {
data : { customerName : string, email : string, shippingAddress : string }
}
@description "Keeps what the customer has entered on the current step without moving on, so the step shows it."
@synonyms "draft, save progress, fill in"
@tier "domain"
NEXT {
data : { customerName : string, email : string, shippingAddress : string }
}
@description "Indicates navigation to the next item or step."
@synonyms "next, forward, advance"
@tier "domain"
PREV
@description "Navigates to the previous screen or item."
@synonyms "back, previous, rewind"
@tier "domain"
PAYMENT_DONE {
result : { id : string!, status : string! }
}
@description "Indicates a payment transaction has completed successfully."
@synonyms "paid, processed, confirmed, finalized"
@tier "domain"
PAYMENT_FAILED {
error : string
code : string
}
@description "Indicates a payment transaction was unsuccessful."
@synonyms "error, declined, rejected, unsuccessful"
@tier "domain"
COMPLETE
@description "Indicates a process or transaction has finished successfully."
@synonyms "finished, done, succeeded, finalized"
@tier "domain"
CheckoutSaved {
id : string
}
@description "Indicates a checkout configuration has been successfully saved."
@synonyms "saved, persisted, stored"
@tier "presentation"
CheckoutSaveFailed {
error : string
code : string
}
@description "Indicates a failure during the saving of checkout data."
@synonyms "error, failure, problem, unsuccessful"
@tier "internal"
RESTART
@description "Starts a new checkout."
@synonyms "start over, new order"
@tier "domain"
}
}Each component on the screen is a library behavior. The application imports it and supplies its data, event names and configuration; the state machine is defined by the library.
uses Browse from "std/behaviors/std-browse"
uses Stats from "std/behaviors/std-stats"
uses Graphs from "std/behaviors/std-graphs"
trait DemoStockPageList = Browse.traits.BrowseItemBrowse -> DemoStockItem {
config {
browseLook: "dense"
searchField: "name"
orderBy: "position"
displayPageSize: 12
itemClickEvent: VIEW
}
}An assistant composed into an application uses the application's declared inputs as its tools. It acts as the signed-in user, through the same transitions as user interaction.
Each added module extends the assistant's available actions.
Guards and access rules apply to the assistant as they apply to a user.
The state machine, not the prompt, determines the outcome.
orbital KflowAssistant = Agent.orbitals.AgentAssistantOrbital {
config {
appName: "KFlow"
tools: [
{ event: Learner.KflowCompanionTools.COMPANION_READ_PATHS },
{ event: Learner.KflowCompanionTools.COMPANION_READ_CONCEPT },
{ event: Learner.KflowCompanionTools.COMPANION_CREATE_GOAL },
{ event: Learner.KflowCompanionTools.COMPANION_MARK_LEARNED }
]
}
}Counted from the installed catalog. A model selects from this closed vocabulary rather than inventing an API, and each error is reported with a code and a source location.
operators
UI patterns
validation codes, each with a suggested fix
A program can be written with English, Arabic or Slovenian keywords; all versions compile to the same code. Further languages can be added by the community as language packs.
trait DemoStockPageDesk -> DemoStockItem [lifecycle, instance] {
initial: idle
state idle {
INIT -> idle
(fetch DemoStockItem { emit: { success: STOCK_LOADED } })
SELL_VASES -> idle
(persist update DemoStockItem { id: "item-3", onHand: 0, status: "out" } {
emit: { success: STOCK_CHANGED }
})
}
listens {
DemoStockPageTour.TOUR_STEP -> SELL_VASES
when (= ?event "SELL_VASES")
}
}Dungeon Delver, a dungeon crawl based on the D&D 5e rules. Dice, the character sheet, turn-based combat and dungeon generation are each a separate behavior.
trait BoardCombat -> @rebindable DelverGame [lifecycle, instance] {
state active {
INIT -> active
(set @entity.phase idle)
ENCOUNTER_START -> active when (and true (> (array/len ?units) 0))
(set @entity.units (array/map ?units (fn u (object/merge { actionUsed: false, moveLeft: 0 } @u))))
(set @entity.combatTiles (if (> (array/len ?tiles) 0) ?tiles (array/flatten (array/map (array/range 0 14) (fn gy (array/map (array/range 0 20) (fn gx {
id: (str/concat t- @gx "-" @gy)
passable: true
room: 1
x: @gx
y: @gy
})))))))
(set @entity.round 0)
(set @entity.turnIndex 0)
(set @entity.pending {
kind: initiative
rolls: {}
})
(set @entity.monsterQueue (array/map ?units (fn u (object/get @u id))))
(set @entity.phase rolling-initiative)
(emit ROLL {
bonus: (object/get (array/first @entity.units) dexMod)
count: 1
mode: normal
purpose: (str/concat "initiative:" (object/get (array/first @entity.units) id))
sides: 20
})
MOVE -> active when (and true (and (or (== @entity.phase player-turn) (== @entity.phase ended)) (and (== (array/len (array/filter @entity.units (fn u (and (== (object/get @u id) ?unitId) (and (== (object/get @u team) hero) (> (object/get @u hp) 0)))))) 1) (and (grid/in-bounds { x: ?x, y: ?y } 20 14) (and (== (object/get (array/find @entity.combatTiles (fn t (and (== (object/get @t x) ?x) (== (object/get @t y) ?y)))) passable) true) (and (== (array/len (array/filter @entity.units (fn o (and (!= (object/get @o id) ?unitId) (and (> (object/get @o hp) 0) (and (== (object/get @o x) ?x) (== (object/get @o y) ?y))))))) 0) (array/includes (array/map (path/reachable {
x: (object/get (array/find @entity.units (fn u (== (object/get @u id) ?unitId))) x)
y: (object/get (array/find @entity.units (fn u (== (object/get @u id) ?unitId))) y)
} (object/get (array/find @entity.units (fn u (== (object/get @u id) ?unitId))) moveLeft) (array/concat (array/map (array/filter @entity.combatTiles (fn t (not (object/get @t passable)))) (fn t {
x: (object/get @t x)
y: (object/get @t y)
})) (array/map (array/filter @entity.units (fn o (and (!= (object/get @o id) ?unitId) (> (object/get @o hp) 0)))) (fn o {
x: (object/get @o x)
y: (object/get @o y)
}))) 20 14) (fn c (str/concat (object/get @c x) "-" (object/get @c y)))) (str/concat ?x "-" ?y))))))))
(set @entity.units (array/map @entity.units (fn u (if (== (object/get @u id) ?unitId) (object/merge @u {
moveLeft: (- (object/get @u moveLeft) (- (array/len (path/astar {
x: (object/get @u x)
y: (object/get @u y)
} { x: ?x, y: ?y } (array/concat (array/map (array/filter @entity.combatTiles (fn t (not (object/get @t passable)))) (fn t {
x: (object/get @t x)
y: (object/get @t y)
})) (array/map (array/filter @entity.units (fn o (and (!= (object/get @o id) ?unitId) (> (object/get @o hp) 0)))) (fn o {
x: (object/get @o x)
y: (object/get @o y)
}))) 20 14)) 1))
x: ?x
y: ?y
}) @u))))
(emit UNIT_MOVED {
unitId: ?unitId
x: ?x
y: ?y
})
ATTACK -> active when (and true (and (== @entity.phase player-turn) (and (== (array/len (array/filter @entity.units (fn u (and (== (object/get @u id) ?attackerId) (and (== (object/get @u team) hero) (and (> (object/get @u hp) 0) (== (object/get @u actionUsed) false))))))) 1) (and (== (array/len (array/filter @entity.units (fn u (and (== (object/get @u id) ?targetId) (and (== (object/get @u team) monster) (> (object/get @u hp) 0)))))) 1) (<= (grid/manhattan-distance {
x: (object/get (array/find @entity.units (fn u (== (object/get @u id) ?attackerId))) x)
y: (object/get (array/find @entity.units (fn u (== (object/get @u id) ?attackerId))) y)
} {
x: (object/get (array/find @entity.units (fn u (== (object/get @u id) ?targetId))) x)
y: (object/get (array/find @entity.units (fn u (== (object/get @u id) ?targetId))) y)
}) 1)))))
(set @entity.pending {
attackerId: ?attackerId
crit: false
kind: attack
targetId: ?targetId
})
(set @entity.units (array/map @entity.units (fn u (if (== (object/get @u id) ?attackerId) (object/merge @u { actionUsed: true }) @u))))
(emit ROLL {
bonus: (object/get (array/find @entity.units (fn u (== (object/get @u id) ?attackerId))) attackBonus)
count: 1
mode: normal
purpose: (str/concat "attack:" ?attackerId)
sides: 20
})
COMBAT_DASH -> active when (and true (and (== @entity.phase player-turn) (== (array/len (array/filter @entity.units (fn u (and (== (object/get @u team) hero) (and (> (object/get @u hp) 0) (== (object/get @u actionUsed) false)))))) 1)))
(set @entity.units (array/map @entity.units (fn u (if (== (object/get @u team) hero) (object/merge @u {
actionUsed: true
moveLeft: (+ (object/get @u moveLeft) (object/get @u speed))
}) @u))))
(emit UNIT_DASHED {
unitId: (object/get (array/find @entity.units (fn u (== (object/get @u team) hero))) id)
})
COMBAT_DODGE -> active when (and true (and (== @entity.phase player-turn) (== (array/len (array/filter @entity.units (fn u (and (== (object/get @u team) hero) (and (> (object/get @u hp) 0) (== (object/get @u actionUsed) false)))))) 1)))
(set @entity.units (array/map @entity.units (fn u (if (== (object/get @u team) hero) (object/merge @u { actionUsed: true, dodging: true }) @u))))
(emit UNIT_DODGING {
unitId: (object/get (array/find @entity.units (fn u (== (object/get @u team) hero))) id)
})
DICE_ROLLED -> active when true
(if (str/startsWith ?purpose "initiative:") (do (set @entity.pending {
kind: initiative
rolls: (object/set (object/get @entity.pending rolls) (str/slice ?purpose 11) ?total)
}) (set @entity.monsterQueue (array/drop @entity.monsterQueue 1)) (if (> (array/len @entity.monsterQueue) 0) (emit ROLL {
bonus: (object/get (array/find @entity.units (fn u (== (object/get @u id) (array/first @entity.monsterQueue)))) dexMod)
count: 1
mode: normal
purpose: (str/concat "initiative:" (array/first @entity.monsterQueue))
sides: 20
}) (do (set @entity.initiative (array/map (array/sort (array/map @entity.units (fn u {
id: (object/get @u id)
sortKey: (+ (* (object/get (object/get @entity.pending rolls) (object/get @u id)) 100) (object/get @u dexMod))
})) sortKey desc) (fn e (object/get @e id)))) (set @entity.round 1) (set @entity.turnIndex 0) (set @entity.pending {}) (if (== (object/get (array/find @entity.units (fn u (== (object/get @u id) (array/first @entity.initiative)))) team) hero) (let ((hero (array/find @entity.units (fn u (== (object/get @u team) hero))))) (if (and (<= (object/get @hero hp) 0) (not (== (object/get @hero stable) true))) (do (set @entity.phase player-turn) (emit TURN_STARTED {
round: @entity.round
unitId: (object/get @hero id)
}) (emit ROLL {
bonus: 0
count: 1
mode: normal
purpose: deathsave
sides: 20
})) (if (== (object/get @hero stable) true) (do (set @entity.phase monster-turn) (set @entity.turnIndex (+ @entity.turnIndex 1)) (set @entity.monsterQueue (array/filter @entity.initiative (fn iid (== (object/get (array/find @entity.units (fn u (== (object/get @u id) @iid))) team) monster)))) (emit MONSTER_STEP {
remaining: (array/len @entity.monsterQueue)
})) (do (set @entity.phase player-turn) (set @entity.units (array/map @entity.units (fn u (if (== (object/get @u team) "hero") (object/merge @u {
actionUsed: false
dodging: false
moveLeft: (object/get @u speed)
}) @u)))) (emit TURN_STARTED {
round: @entity.round
unitId: (object/get @hero id)
}))))) (do (set @entity.phase monster-turn) (set @entity.monsterQueue (array/filter @entity.initiative (fn iid (== (object/get (array/find @entity.units (fn u (== (object/get @u id) @iid))) team) monster)))) (emit MONSTER_STEP {
remaining: (array/len @entity.monsterQueue)
})))))) (if (str/startsWith ?purpose "attack:") (let ((attacker (array/find @entity.units (fn u (== (object/get @u id) (object/get @entity.pending attackerId))))) (target (array/find @entity.units (fn u (== (object/get @u id) (object/get @entity.pending targetId)))))) (let ((nat (array/first ?kept))) (let ((crit (== @nat 20))) (let ((hit (and (!= @nat 1) (or @crit (>= ?total (object/get @target ac)))))) (if @hit (do (set @entity.pending (object/merge @entity.pending { crit: @crit })) (emit ROLL {
bonus: (object/get (object/get @attacker damage) bonus)
count: (if @crit (* 2 (object/get (object/get @attacker damage) count)) (object/get (object/get @attacker damage) count))
mode: normal
purpose: (str/concat "damage:" (object/get @attacker id))
sides: (object/get (object/get @attacker damage) sides)
})) (do (set @entity.pending {}) (emit ATTACK_RESOLVED {
attackerId: (object/get @attacker id)
crit: false
damage: 0
hit: false
targetId: (object/get @target id)
}) (if (== @entity.phase monster-turn) (emit MONSTER_STEP {
remaining: (array/len @entity.monsterQueue)
}) null))))))) (if (str/startsWith ?purpose "damage:") (let ((attackerId (object/get @entity.pending attackerId)) (targetId (object/get @entity.pending targetId))) (let ((target (array/find @entity.units (fn u (== (object/get @u id) @targetId))))) (let ((isHero (== (object/get @target team) hero))) (let ((newHp (- (object/get @target hp) ?total))) (do (set @entity.units (array/map @entity.units (fn u (if (== (object/get @u id) @targetId) (object/merge @u { hp: @newHp }) @u)))) (if @isHero (do (set @entity.units (array/map @entity.units (fn u (if (== (object/get @u id) @targetId) (object/merge @u { stable: false }) @u)))) (emit HERO_DAMAGE {
amount: ?total
crit: (object/get @entity.pending crit)
})) null) (if (and (not @isHero) (<= @newHp 0)) (do (set @entity.initiative (array/filter @entity.initiative (fn iid (!= @iid @targetId)))) (emit MONSTER_SLAIN {
cr: (object/get @target cr)
id: @targetId
kind: (object/get @target kind)
xpValue: (object/get @target xpValue)
}) (emit HERO_GAIN_XP {
amount: (object/get @target xpValue)
})) null) (emit ATTACK_RESOLVED {
attackerId: @attackerId
crit: (object/get @entity.pending crit)
damage: ?total
hit: true
targetId: @targetId
}) (set @entity.pending {}) (if (> (array/len (array/filter @entity.units (fn u (and (== (object/get @u team) monster) (> (object/get @u hp) 0))))) 0) (if (== @entity.phase monster-turn) (emit MONSTER_STEP {
remaining: (array/len @entity.monsterQueue)
}) null) (do (set @entity.phase ended) (set @entity.units (array/map @entity.units (fn u (if (and (== (object/get @u team) hero) (> (object/get @u hp) 0)) (object/merge @u {
moveLeft: (object/get @u speed)
}) @u)))) (emit COMBAT_ENDED { result: won, round: @entity.round })))))))) null)))
(if (== ?purpose deathsave) (do (emit DEATH_SAVE {
roll: (array/first ?kept)
}) (if (!= @entity.phase ended) (do (set @entity.phase monster-turn) (set @entity.turnIndex (+ @entity.turnIndex 1)) (set @entity.monsterQueue (array/filter @entity.initiative (fn iid (== (object/get (array/find @entity.units (fn u (== (object/get @u id) @iid))) team) monster)))) (emit MONSTER_STEP {
remaining: (array/len @entity.monsterQueue)
})) null)) null)
COMBAT_END_TURN -> active when (and true (== @entity.phase player-turn))
(set @entity.phase monster-turn)
(set @entity.turnIndex (+ @entity.turnIndex 1))
(set @entity.monsterQueue (array/filter @entity.initiative (fn iid (== (object/get (array/find @entity.units (fn u (== (object/get @u id) @iid))) team) monster))))
(emit MONSTER_STEP {
remaining: (array/len @entity.monsterQueue)
})
MONSTER_STEP -> active when (and true (== @entity.phase monster-turn))
(if (== (array/len @entity.monsterQueue) 0) (let ((hero (array/find @entity.units (fn u (== (object/get @u team) hero))))) (if (and (<= (object/get @hero hp) 0) (not (== (object/get @hero stable) true))) (do (set @entity.phase player-turn) (set @entity.round (+ @entity.round 1)) (set @entity.turnIndex (+ @entity.turnIndex 1)) (emit TURN_STARTED {
round: @entity.round
unitId: (object/get @hero id)
}) (emit ROLL {
bonus: 0
count: 1
mode: normal
purpose: deathsave
sides: 20
})) (if (== (object/get @hero stable) true) (do (set @entity.phase monster-turn) (set @entity.turnIndex (+ @entity.turnIndex 1)) (set @entity.monsterQueue (array/filter @entity.initiative (fn iid (== (object/get (array/find @entity.units (fn u (== (object/get @u id) @iid))) team) monster)))) (emit MONSTER_STEP {
remaining: (array/len @entity.monsterQueue)
})) (do (set @entity.phase player-turn) (set @entity.round (+ @entity.round 1)) (set @entity.turnIndex (+ @entity.turnIndex 1)) (set @entity.units (array/map @entity.units (fn u (if (== (object/get @u team) "hero") (object/merge @u {
actionUsed: false
dodging: false
moveLeft: (object/get @u speed)
}) @u)))) (emit TURN_STARTED {
round: @entity.round
unitId: (object/get @hero id)
}))))) (let ((mid (array/first @entity.monsterQueue))) (if (== (array/len (array/filter @entity.units (fn u (and (== (object/get @u id) @mid) (> (object/get @u hp) 0))))) 0) (do (set @entity.monsterQueue (array/drop @entity.monsterQueue 1)) (emit MONSTER_STEP {
remaining: (array/len @entity.monsterQueue)
})) (let ((m (array/find @entity.units (fn u (== (object/get @u id) @mid)))) (hero (array/find @entity.units (fn u (== (object/get @u team) hero))))) (let ((walk (array/reduce (array/range 0 (object/get @m speed)) {
stuck: false
x: (object/get @m x)
y: (object/get @m y)
} (fn (acc i) (if (object/get @acc stuck) @acc (let ((dx (- (object/get @hero x) (object/get @acc x))) (dy (- (object/get @hero y) (object/get @acc y)))) (let ((useX (and (!= @dx 0) (>= (math/abs @dx) (math/abs @dy))))) (let ((cand (if @useX {
x: (+ (object/get @acc x) (math/sign @dx))
y: (object/get @acc y)
} (if (!= @dy 0) {
x: (object/get @acc x)
y: (+ (object/get @acc y) (math/sign @dy))
} null))) (alt (if @useX (if (!= @dy 0) {
x: (object/get @acc x)
y: (+ (object/get @acc y) (math/sign @dy))
} null) (if (!= @dx 0) {
x: (+ (object/get @acc x) (math/sign @dx))
y: (object/get @acc y)
} null)))) (if (and (!= @cand null) (and (grid/in-bounds @cand 20 14) (and (== (object/get (array/find @entity.combatTiles (fn t (and (== (object/get @t x) (object/get @cand x)) (== (object/get @t y) (object/get @cand y))))) passable) true) (== (array/len (array/filter @entity.units (fn o (and (!= (object/get @o id) @mid) (and (> (object/get @o hp) 0) (and (== (object/get @o x) (object/get @cand x)) (== (object/get @o y) (object/get @cand y)))))))) 0)))) {
stuck: false
x: (object/get @cand x)
y: (object/get @cand y)
} (if (and (!= @alt null) (and (grid/in-bounds @alt 20 14) (and (== (object/get (array/find @entity.combatTiles (fn t (and (== (object/get @t x) (object/get @alt x)) (== (object/get @t y) (object/get @alt y))))) passable) true) (== (array/len (array/filter @entity.units (fn o (and (!= (object/get @o id) @mid) (and (> (object/get @o hp) 0) (and (== (object/get @o x) (object/get @alt x)) (== (object/get @o y) (object/get @alt y)))))))) 0)))) {
stuck: false
x: (object/get @alt x)
y: (object/get @alt y)
} {
stuck: true
x: (object/get @acc x)
y: (object/get @acc y)
})))))))))) (do (set @entity.monsterQueue (array/drop @entity.monsterQueue 1)) (if (or (!= (object/get @walk x) (object/get @m x)) (!= (object/get @walk y) (object/get @m y))) (do (set @entity.units (array/map @entity.units (fn u (if (== (object/get @u id) @mid) (object/merge @u {
x: (object/get @walk x)
y: (object/get @walk y)
}) @u)))) (emit UNIT_MOVED {
unitId: @mid
x: (object/get @walk x)
y: (object/get @walk y)
})) null) (if (<= (grid/manhattan-distance {
x: (object/get @walk x)
y: (object/get @walk y)
} {
x: (object/get @hero x)
y: (object/get @hero y)
}) 1) (do (set @entity.pending {
attackerId: @mid
crit: false
kind: attack
targetId: (object/get @hero id)
}) (set @entity.units (array/map @entity.units (fn u (if (== (object/get @u id) @mid) (object/merge @u { actionUsed: true }) @u)))) (emit ROLL {
bonus: (object/get @m attackBonus)
count: 1
mode: (if (== (object/get @hero dodging) true) disadvantage normal)
purpose: (str/concat "attack:" @mid)
sides: 20
})) (emit MONSTER_STEP {
remaining: (array/len @entity.monsterQueue)
}))))))))
HERO_DIED -> active when (and true (!= @entity.phase ended))
(set @entity.phase ended)
(emit COMBAT_ENDED { result: lost, round: @entity.round })
HERO_DOWN -> active when true
(set @entity.units (array/map @entity.units (fn u (if (== (object/get @u team) hero) (object/merge @u { hp: 0, stable: false }) @u))))
HERO_REVIVED -> active when true
(set @entity.units (array/map @entity.units (fn u (if (== (object/get @u team) hero) (object/merge @u { hp: 1 }) @u))))
HERO_STABLE -> active when true
(set @entity.units (array/map @entity.units (fn u (if (== (object/get @u team) hero) (object/merge @u { stable: true }) @u))))
RESTART -> active
(set @entity.units [])
(set @entity.combatTiles [])
(set @entity.initiative [])
(set @entity.round 0)
(set @entity.turnIndex 0)
(set @entity.phase idle)
(set @entity.pending {})
(set @entity.monsterQueue [])
}
emits {
ROLL -> external {
sides : number
count : number
bonus : number
mode : string
purpose : string
}
@description "Dice request for the dice atom: initiative, attack, and damage rolls all flow through this single channel, purpose-tagged initiative:<id> / attack:<id> / damage:<id>"
@tier "domain"
HERO_DAMAGE -> external {
amount : number
crit : boolean
}
@description "Damage dealt to the hero unit; the hero-sheet atom applies it to hp and runs the 0-hp down path (crit doubles the death-save failures when the hero is already down)"
@tier "domain"
DEATH_SAVE -> external {
roll : number
}
@description "A death-save d20 adjudicated by the hero-sheet atom; rolled organically by this atom (purpose deathsave) when the hero unit starts a turn at 0 hp"
@tier "domain"
HERO_GAIN_XP -> external {
amount : number
}
@description "XP awarded to the hero when a monster is slain (the monster's xpValue); the hero-sheet atom levels on thresholds"
@tier "domain"
MONSTER_SLAIN -> external {
id : string
kind : string
cr : number
xpValue : number
}
@description "A monster dropped to 0 hp: removed from initiative but KEPT in units as a corpse (every occupancy/targeting guard filters hp > 0) so board renderers can hold its death pose; loot/quest listeners react"
@tier "domain"
ATTACK_RESOLVED -> external {
attackerId : string
targetId : string
hit : boolean
crit : boolean
damage : number
}
@description "An attack fully resolved (roll + damage applied); combat log and fx listeners render the outcome"
@tier "domain"
TURN_STARTED -> external {
unitId : string
round : number
}
@description "A side's turn began (hero player-turn or the monster queue); UI highlights the active side"
@tier "domain"
UNIT_MOVED -> external {
unitId : string
x : number
y : number
}
@description "A unit's grid position changed (hero MOVE or monster AI step); board renderers listen"
@tier "domain"
UNIT_DASHED -> external {
unitId : string
}
@description "The hero took the Dash action: movement refilled by speed, action spent; narrators/loggers listen"
@tier "domain"
UNIT_DODGING -> external {
unitId : string
}
@description "The hero took the Dodge action: attacks against them roll with disadvantage until their next turn; narrators/loggers listen"
@tier "domain"
COMBAT_ENDED -> external {
result : string
round : number
}
@description "Encounter over: won when the last monster died, lost on HERO_DIED; round-flow listeners route to victory/defeat"
@tier "domain"
MONSTER_STEP -> external {
remaining : number
}
@description "Internal hop that drives the monster queue one monster per transition; this atom listens to its own emit to chain the queue"
@tier "domain"
}
listens {
BoardDice.DICE_ROLLED -> DICE_ROLLED
BoardHero.HERO_DIED -> HERO_DIED
BoardHero.HERO_DOWN -> HERO_DOWN
BoardHero.HERO_REVIVED -> HERO_REVIVED
BoardHero.HERO_STABLE -> HERO_STABLE
DndDelverPlay.ATTACK -> ATTACK
DndDelverPlay.COMBAT_DASH -> COMBAT_DASH
DndDelverPlay.COMBAT_DODGE -> COMBAT_DODGE
DndDelverPlay.COMBAT_END_TURN -> COMBAT_END_TURN
DndDelverPlay.ENCOUNTER_START -> ENCOUNTER_START
DndDelverPlay.MOVE -> MOVE
DndDelverPlay.RESTART -> RESTART
ENCOUNTER_START {
units : [{ id : string!, team : string!, x : int, y : int, hp : int, maxHp : int, speed : int, dexMod : int, attackBonus : int, moveLeft : int, actionUsed : boolean, dodging : boolean, stable : boolean, ac : int, kind : string, damage : { count : int, sides : int, bonus : int }, cr : number, xpValue : int }]
tiles : [{ id : string!, x : int!, y : int!, passable : boolean!, room : int! }]
}
MOVE {
unitId : string
x : number
y : number
}
ATTACK {
attackerId : string
targetId : string
}
COMBAT_DASH
COMBAT_DODGE
DICE_ROLLED {
purpose : string
rolls : [number]
kept : [number]
total : number!
}
COMBAT_END_TURN
MONSTER_STEP {
remaining : number
}
@description "Internal hop that drives the monster queue one monster per transition; this atom listens to its own emit to chain the queue"
@tier "domain"
HERO_DIED {
id : string
}
HERO_DOWN {
id : string
}
HERO_REVIVED {
id : string
}
HERO_STABLE {
id : string
}
RESTART
}
config {
gridHeight : number = 14
@label "Grid Height"
@description "Grid row count clamping move + AI bounds"
@tier "domain"
gridWidth : number = 20
@label "Grid Width"
@description "Grid column count clamping move + AI bounds"
@tier "domain"
running : boolean = true
@label "Running"
@description "When true, encounter intents are applied; toggle to freeze the encounter"
@tier "internal"
}
}An inventory screen composed from library behaviors: totals, a chart and a table over browser-stored records.
trait DemoStockPageDesk -> DemoStockItem [lifecycle, instance] {
state idle {
INIT -> idle
(fetch DemoStockItem {
emit: { success: STOCK_LOADED }
})
STOCK_CHANGED -> idle
(fetch DemoStockItem {
emit: { success: STOCK_LOADED }
})
SELL_TABLES -> idle
(persist update DemoStockItem {
id: item-1
onHand: 1
position: 2.5
status: low
stockValue: 640
} {
emit: { success: STOCK_CHANGED }
})
SELL_VASES -> idle
(persist update DemoStockItem {
id: item-3
onHand: 0
position: 0.5
status: out
stockValue: 0
} {
emit: { success: STOCK_CHANGED }
})
RESTOCK_CHAIRS -> idle
(persist update DemoStockItem {
id: item-4
onHand: 24
position: 9
status: in-stock
stockValue: 2880
} {
emit: { success: STOCK_CHANGED }
})
REORDER_SHELVES -> idle
(persist update DemoStockItem {
id: item-9
onHand: 12
position: 10
status: in-stock
stockValue: 2520
} {
emit: { success: STOCK_CHANGED }
})
STOCK_RESET -> idle
(persist update DemoStockItem {
id: item-1
onHand: 6
position: 4
status: in-stock
stockValue: 3840
})
(persist update DemoStockItem {
id: item-3
onHand: 2
position: 1
status: low
stockValue: 76
})
(persist update DemoStockItem {
id: item-4
onHand: 0
position: 0
status: out
stockValue: 0
})
(persist update DemoStockItem {
id: item-5
onHand: 14
position: 5
status: in-stock
stockValue: 756
})
(persist update DemoStockItem {
id: item-6
onHand: 3
position: 2
status: low
stockValue: 237
})
(persist update DemoStockItem {
id: item-7
onHand: 22
position: 7
status: in-stock
stockValue: 572
})
(persist update DemoStockItem {
id: item-8
onHand: 9
position: 6
status: in-stock
stockValue: 1260
})
(persist update DemoStockItem {
id: item-9
onHand: 1
position: 3
status: low
stockValue: 210
} {
emit: { success: STOCK_CHANGED }
})
}
emits {
STOCK_LOADED {
data : [DemoStockItem]
}
@description "The products were read; the numbers and charts regroup them."
@tier "internal"
STOCK_CHANGED
@description "The desk changed a stock level; the list reloads."
@tier "internal"
}
listens {
DemoStockPageTour.TOUR_STEP -> SELL_TABLES when (= ?event SELL_TABLES)
DemoStockPageTour.TOUR_STEP -> SELL_VASES when (= ?event SELL_VASES)
DemoStockPageTour.TOUR_STEP -> RESTOCK_CHAIRS when (= ?event RESTOCK_CHAIRS)
DemoStockPageTour.TOUR_STEP -> REORDER_SHELVES when (= ?event REORDER_SHELVES)
DemoStockPageTour.TOUR_RESET -> STOCK_RESET
}
}std-agent-builder produces a program from a request: it ranks the installed behaviors by semantic similarity, constructs the program as data with quasiquote, and validates it with the compiler before saving.
Describe the app you want…
trait BuilderPipeline -> BuilderProcess [lifecycle, instance] {
state idle {
INIT -> idle
(set @entity.status idle)
(render-ui main <Typography content={"Ready to build."} variant={caption} />)
START -> searching
(set @entity.request ?request)
(set @entity.orbitalName ?orbitalName)
(set @entity.context (str/default ?context ""))
(set @entity.step 0)
(set @entity.repairs 0)
(set @entity.status searching)
(emit BUILD_PROGRESS {
status: searching
tier: ""
})
(call-service llm embed {
texts: [?request]
} {
emit: { failure: BUILD_FAILED, success: REQUEST_EMBEDDED }
})
FILL -> idle
PICK -> idle
CONVERSE -> idle
ASSISTANT_REPLIED -> idle
TOOLS_FAILED -> idle
}
state searching {
INIT -> searching
(set @entity.status searching)
REQUEST_EMBEDDED -> searching when (> (array/len ?embeddings) 0)
(set @entity.queryVector (array/first ?embeddings))
(emit STEP {})
REQUEST_EMBEDDED -> failed when (= (array/len ?embeddings) 0)
(set @entity.error "The model returned no embedding")
(set @entity.status failed)
(render-ui main <Typography content={"Build failed: the model returned no embedding."} variant={caption} />)
(emit BUILD_REJECTED {
error: "The model returned no embedding"
errors: []
})
STEP -> searching when (and (< @entity.step (array/len [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}])) (= (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) source) catalog))
(behavior/catalog {
paths: (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) scope [])
} {
emit: { failure: BUILD_FAILED, success: CATALOG_LISTED }
})
STEP -> searching when (and (< @entity.step (array/len [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}])) (= (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) source) pool))
(emit POOL_SEARCH {
take: (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) take 5)
vector: @entity.queryVector
})
STEP -> failed when (>= @entity.step (array/len [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}]))
(set @entity.error "No tier of the ladder could serve the request")
(set @entity.status failed)
(render-ui main <Typography content={"No tier could serve the request."} variant={caption} />)
(emit BUILD_REJECTED {
error: "No tier of the ladder could serve the request"
errors: []
})
CATALOG_LISTED -> searching
(set @entity.ranked (array/sort (array/map (array/filter ?result (fn e (> (array/len (object/get @e.vectors description [])) 0))) (fn e {
behavior: @e.behavior
description: (object/get @e description "")
fields: {}
score: (array/cosine (object/get @e.vectors description) @entity.queryVector)
trait: (array/first @e.traits)
value: @e.value
})) score desc))
(emit RANKED {})
POOL_FOUND -> searching
(set @entity.ranked (array/map ?hits (fn h {
behavior: @h.behavior
description: (object/get @h description "")
fields: (object/get @h fields {})
score: @h.score
value: @h.value
})))
(emit RANKED {})
RANKED -> searching when (or (= (array/len @entity.ranked) 0) (< (object/get (array/first @entity.ranked) score) (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) threshold)))
(set @entity.step (+ @entity.step 1))
(emit STEP {})
RANKED -> building when (and (> (array/len @entity.ranked) 0) (and (>= (object/get (array/first @entity.ranked) score) (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) threshold)) (= (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) action) mount)))
(set @entity.pick (object/get (array/first @entity.ranked) trait))
(set @entity.status building)
(emit BUILD_PROGRESS {
status: building
tier: (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) name)
})
(program/eval (quasiquote {
name: (unquote @entity.orbitalName)
orbitals: [{
entity: {
fields: [{ name: id, type: string }]
name: BuiltView
persistence: runtime
}
name: (unquote @entity.orbitalName)
pages: [{
name: Built
path: "/"
traits: [{ ref: BuiltFrame }]
}]
traits: [{
linkedEntity: BuiltView
name: BuiltFrame
scope: instance
stateMachine: {
events: [{ key: INIT, name: Init }]
states: [{ isInitial: true, name: idle }]
transitions: [{
effects: [(render-ui main {
children: [
[
unquote
@entity.pick
]
]
type: stack
})]
event: INIT
from: idle
to: idle
}]
}
}]
}]
}) {
emit: { failure: BUILD_FAILED, success: BUILT }
})
RANKED -> done when (and (> (array/len @entity.ranked) 0) (and (>= (object/get (array/first @entity.ranked) score) (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) threshold)) (= (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) action) adopt)))
(set @entity.behavior (object/get (array/first @entity.ranked) behavior))
(set @entity.status done)
(render-ui main <Typography content={(str/concat "Adopted " @entity.behavior)} variant={caption} />)
(emit BUILD_COMPLETE {
behavior: @entity.behavior
fields: (object/get (array/first @entity.ranked) fields {})
orbitalName: @entity.orbitalName
tier: (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) name)
value: (object/get (array/first @entity.ranked) value)
})
RANKED -> describing when (and (and (> (array/len @entity.ranked) 0) (and (>= (object/get (array/first @entity.ranked) score) (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) threshold)) (= (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) action) fill))) (or (<= (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) take 1) 1) (= (array/len @entity.ranked) 1)))
(set @entity.chosen (object/get (array/first @entity.ranked) behavior))
(set @entity.chosenDescription (object/get (array/first @entity.ranked) description ""))
(set @entity.pickedFields {})
(set @entity.status describing)
(emit BUILD_PROGRESS {
status: describing
tier: (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) name)
})
(behavior/describe { behavior: @entity.chosen } {
emit: { failure: BUILD_FAILED, success: DESCRIBED }
})
RANKED -> choosing when (and (and (> (array/len @entity.ranked) 0) (and (>= (object/get (array/first @entity.ranked) score) (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) threshold)) (= (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) action) fill))) (and (> (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) take 1) 1) (and (> (array/len @entity.ranked) 1) (= chat jev))))
(set @entity.chosen "")
(set @entity.pickedFields {})
(set @entity.status choosing)
(emit BUILD_PROGRESS {
status: choosing
tier: (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) name)
})
(call-service llm choose {
instructions: "Which building block's interaction does what the request asks (sorting into groups, putting in order, estimating, exploring), not just the one about the same subject?"
options: (array/map (array/take @entity.ranked (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) take 1)) (fn r {
description: (object/get @r description "")
value: @r.behavior
}))
state: (if (= @entity.context "") @entity.request (str/concat @entity.request "\n\n" @entity.context))
} {
emit: { failure: BUILD_FAILED, success: CHOSEN }
})
RANKED -> choosing when (and (and (> (array/len @entity.ranked) 0) (and (>= (object/get (array/first @entity.ranked) score) (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) threshold)) (= (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) action) fill))) (and (> (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) take 1) 1) (and (> (array/len @entity.ranked) 1) (= chat chat))))
(set @entity.chosen "")
(set @entity.pickedFields {})
(set @entity.status choosing)
(emit BUILD_PROGRESS {
status: choosing
tier: (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) name)
})
(emit CONVERSE {
ephemeral: true
instructions: (str/concat "Several building blocks could serve the request. Pick the one whose interaction does what the request asks (sorting into groups, putting in order, estimating, exploring…), not just the one about the same subject. Call the PICK tool once with the block and every requested field, then reply with one sentence." "\nThe building blocks:\n" (str/join (array/map (array/take @entity.ranked (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) take 1)) (fn r (str/concat "- " @r.behavior ": " (object/get @r description "")))) "\n"))
messages: [{
content: (if (= @entity.context "") @entity.request (str/concat @entity.request "\n\n" @entity.context))
role: user
}]
tools: [{
event: "BuilderPipeline.PICK"
payload: [{
description: "The building block that fits the request."
name: behavior
required: true
type: string
values: (array/map (array/take @entity.ranked (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) take 1)) (fn r @r.behavior))
}, {
name: fields
properties: []
required: (> (array/len @config.pickFields) 0)
type: object
}]
}]
})
BUILD_FAILED -> failed
(set @entity.error ?error)
(set @entity.status failed)
(render-ui main <Typography content={(str/concat "Build failed: " ?error)} variant={caption} />)
(emit BUILD_REJECTED {
error: ?error
errors: []
})
}
state choosing {
INIT -> choosing
(set @entity.status choosing)
CHOSEN -> describing when (array/some (array/take @entity.ranked (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) take 1)) (fn r (= @r.behavior ?choice)))
(set @entity.chosen ?choice)
(set @entity.chosenDescription (object/get (array/find @entity.ranked (fn r (= @r.behavior ?choice))) description ""))
(set @entity.status describing)
(emit BUILD_PROGRESS {
status: describing
tier: (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) name)
})
(behavior/describe { behavior: ?choice } {
emit: { failure: BUILD_FAILED, success: DESCRIBED }
})
CHOSEN -> failed when (not (array/some (array/take @entity.ranked (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) take 1)) (fn r (= @r.behavior ?choice))))
(set @entity.error "The decision model picked none of the building blocks offered")
(set @entity.status failed)
(render-ui main <Typography content={"Build failed: no building block was picked."} variant={caption} />)
(emit BUILD_REJECTED {
error: "The decision model picked none of the building blocks offered"
errors: []
})
BUILD_FAILED -> failed
(set @entity.error ?error)
(set @entity.status failed)
(render-ui main <Typography content={(str/concat "Build failed: " ?error)} variant={caption} />)
(emit BUILD_REJECTED {
error: ?error
errors: []
})
PICK -> choosing
(set @entity.chosen (str/default ?behavior ""))
(set @entity.pickedFields (if (== ?fields null) {} ?fields))
ASSISTANT_REPLIED -> describing when (array/some (array/take @entity.ranked (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) take 1)) (fn r (= @r.behavior @entity.chosen)))
(set @entity.chosenDescription (object/get (array/find @entity.ranked (fn r (= @r.behavior @entity.chosen))) description ""))
(set @entity.status describing)
(emit BUILD_PROGRESS {
status: describing
tier: (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) name)
})
(behavior/describe { behavior: @entity.chosen } {
emit: { failure: BUILD_FAILED, success: DESCRIBED }
})
ASSISTANT_REPLIED -> failed when (not (array/some (array/take @entity.ranked (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) take 1)) (fn r (= @r.behavior @entity.chosen))))
(set @entity.error "The model picked none of the building blocks offered")
(set @entity.status failed)
(render-ui main <Typography content={"Build failed: no building block was picked."} variant={caption} />)
(emit BUILD_REJECTED {
error: "The model picked none of the building blocks offered"
errors: []
})
TOOLS_FAILED -> failed
(set @entity.error ?error)
(set @entity.status failed)
(render-ui main <Typography content={(str/concat "Build failed: " ?error)} variant={caption} />)
(emit BUILD_REJECTED {
error: ?error
errors: []
})
}
state describing {
INIT -> describing
(set @entity.status describing)
DESCRIBED -> filling when (> (array/len (object/get ?result orbitals [])) 0)
(let ((o (array/first (object/get ?result orbitals [])))) (do (set @entity.target (object/get @o value)) (set @entity.tool [{
name: config
properties: (array/map (array/filter (object/get @o knobs []) (fn k (!= (object/get @k tier "") internal))) (fn k (object/pick @k (default description name properties required type values))))
type: object
}, {
name: traits
properties: (array/map (object/get @o traits []) (fn t {
name: (object/get @t trait)
properties: [{
name: config
properties: (array/map (array/filter (object/get @t knobs []) (fn k (!= (object/get @k tier "") internal))) (fn k (object/pick @k (default description name properties required type values))))
type: object
}]
type: object
}))
type: object
}, {
name: fields
properties: (array/concat @config.fillFields @config.pickFields)
required: (> (+ (array/len @config.fillFields) (array/len @config.pickFields)) 0)
type: object
}]) (set @entity.status filling) (emit BUILD_PROGRESS {
status: filling
tier: (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) name)
}) (emit CONVERSE {
ephemeral: true
instructions: (str/concat "You adapt an existing building block to a request. Call the FILL tool once: set only the knobs the request needs (in `config` and `traits` → trait → `config`), write every requested field in `fields`, then reply with one sentence." "\nThe building block: " @entity.chosen " — " @entity.chosenDescription)
messages: [{
content: (if (= @entity.context "") @entity.request (str/concat @entity.request "\n\n" @entity.context))
role: user
}]
tools: [{
event: "BuilderPipeline.FILL"
payload: @entity.tool
}]
})))
DESCRIBED -> failed when (= (array/len (object/get ?result orbitals [])) 0)
(set @entity.error "The best match has no orbital to fill")
(set @entity.status failed)
(render-ui main <Typography content={"Build failed: the best match has no orbital to fill."} variant={caption} />)
(emit BUILD_REJECTED {
error: "The best match has no orbital to fill"
errors: []
})
BUILD_FAILED -> failed
(set @entity.error ?error)
(set @entity.status failed)
(render-ui main <Typography content={(str/concat "Build failed: " ?error)} variant={caption} />)
(emit BUILD_REJECTED {
error: ?error
errors: []
})
}
state filling {
INIT -> filling
(set @entity.status filling)
FILL -> filling
(set @entity.filledConfig (if (== ?config null) {} ?config))
(set @entity.filledTraits (if (== ?traits null) {} ?traits))
(set @entity.filledFields (object/merge (if (== ?fields null) {} ?fields) @entity.pickedFields))
ASSISTANT_REPLIED -> filling when (and (not (array/every @config.fieldWordLimits (fn l (<= (array/len (str/split (str/trim (object/get @entity.filledFields @l.name "")) " ")) @l.words)))) (< @entity.repairs 2))
(set @entity.repairs (+ @entity.repairs 1))
(set @entity.pickedFields {})
(emit BUILD_PROGRESS {
status: repairing
tier: (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) name)
})
(emit CONVERSE {
ephemeral: true
instructions: (str/concat "You adapt an existing building block to a request. Call the FILL tool once: set only the knobs the request needs (in `config` and `traits` → trait → `config`), write every requested field in `fields`, then reply with one sentence." "\nThe building block: " @entity.chosen " — " @entity.chosenDescription)
messages: [{ content: @entity.request, role: user }, {
content: (str/concat "Some fields are too long. The most words each field may hold: " (str/join (array/map @config.fieldWordLimits (fn l (str/concat @l.name " " (str/concat @l.words) " words"))) ", ") ". What you wrote: " (json/stringify @entity.filledFields) ". Call FILL again with the same knobs and shorter fields.")
role: user
}]
tools: [{
event: "BuilderPipeline.FILL"
payload: @entity.tool
}]
})
ASSISTANT_REPLIED -> building when (or (array/every @config.fieldWordLimits (fn l (<= (array/len (str/split (str/trim (object/get @entity.filledFields @l.name "")) " ")) @l.words))) (>= @entity.repairs 2))
(set @entity.status building)
(emit BUILD_PROGRESS {
status: building
tier: (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) name)
})
(program/eval (quasiquote {
name: (unquote @entity.orbitalName)
orbitals: [(unquote (behavior/apply @entity.target { config: @entity.filledConfig, traits: @entity.filledTraits }))]
}) { final: true } {
emit: { failure: BUILD_FAILED, success: BUILT }
})
TOOLS_FAILED -> failed
(set @entity.error ?error)
(set @entity.status failed)
(render-ui main <Typography content={(str/concat "Build failed: " ?error)} variant={caption} />)
(emit BUILD_REJECTED {
error: ?error
errors: []
})
}
state building {
INIT -> building
(set @entity.status building)
BUILT -> done
(set @entity.behavior (object/get ?result behavior))
(set @entity.status done)
(render-ui main <Typography content={(str/concat "Built " (object/get ?result behavior))} variant={caption} />)
(emit BUILD_COMPLETE {
behavior: (object/get ?result behavior)
fields: @entity.filledFields
orbitalName: @entity.orbitalName
tier: (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) name)
value: (object/get ?result value)
})
BUILD_FAILED -> filling when (and (= (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) action) fill) (< @entity.repairs 2))
(set @entity.repairs (+ @entity.repairs 1))
(set @entity.status filling)
(emit BUILD_PROGRESS {
status: repairing
tier: (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) name)
})
(emit CONVERSE {
ephemeral: true
instructions: "You adapt an existing building block to a request. Call the FILL tool once: set only the knobs the request needs (in `config` and `traits` → trait → `config`), write every requested field in `fields`, then reply with one sentence."
messages: [{ content: @entity.request, role: user }, {
content: (str/concat "The result did not validate. The validator's issues: " (json/stringify (if (== ?errors null) [] ?errors)) " (" ?error "). Call FILL again with corrected values.")
role: user
}]
tools: [{
event: "BuilderPipeline.FILL"
payload: @entity.tool
}]
})
BUILD_FAILED -> failed when (or (!= (object/get (array/nth [{
action: mount
name: mount
scope: (list almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}] @entity.step) action) fill) (>= @entity.repairs 2))
(set @entity.error ?error)
(set @entity.status failed)
(render-ui main <Typography content={(str/concat "Build failed: " ?error)} variant={caption} />)
(emit BUILD_REJECTED {
error: ?error
errors: (if (== ?errors null) [] ?errors)
})
}
state done {
INIT -> done
(set @entity.status done)
RESET -> idle
(set @entity.status idle)
(set @entity.pick null)
(render-ui main <Typography content={"Ready to build."} variant={caption} />)
START -> searching
(set @entity.request ?request)
(set @entity.orbitalName ?orbitalName)
(set @entity.context (str/default ?context ""))
(set @entity.step 0)
(set @entity.repairs 0)
(set @entity.status searching)
(emit BUILD_PROGRESS {
status: searching
tier: ""
})
(call-service llm embed {
texts: [?request]
} {
emit: { failure: BUILD_FAILED, success: REQUEST_EMBEDDED }
})
}
state failed {
INIT -> failed
(set @entity.status failed)
RESET -> idle
(set @entity.status idle)
(set @entity.pick null)
(render-ui main <Typography content={"Ready to build."} variant={caption} />)
START -> searching
(set @entity.request ?request)
(set @entity.orbitalName ?orbitalName)
(set @entity.context (str/default ?context ""))
(set @entity.step 0)
(set @entity.repairs 0)
(set @entity.status searching)
(emit BUILD_PROGRESS {
status: searching
tier: ""
})
(call-service llm embed {
texts: [?request]
} {
emit: { failure: BUILD_FAILED, success: REQUEST_EMBEDDED }
})
}
emits {
BUILD_COMPLETE -> external {
orbitalName : string!
behavior : string!
value : behavior!
tier : string!
fields : Map string string
}
@description "A tier served the request: the behavior (its specifier and its value), the ladder step that served it, and the extra fields the fill turn wrote (or that the adopted pool entry carries)."
@tier "domain"
BUILD_REJECTED -> external {
error : string!
errors : [BuildIssue]
}
@description "No tier could serve the request, or the build failed; the validator's issues come back as data."
@tier "domain"
BUILD_PROGRESS -> external {
status : string!
tier : string
}
@description "The build moved on (searching, describing, filling, repairing, building) at a ladder step, for a page that shows the build as it streams."
@tier "domain"
POOL_SEARCH -> external {
vector : [number]!
take : number
}
@description "A pool step asks the pool for its best entries for the request's vector; std-agent-pool's SEARCH answers with POOL_FOUND."
@tier "domain"
CONVERSE -> external {
messages : [AgentChatMessage]!
instructions : string
tools : [AgentToolInput]
ephemeral : boolean
}
@tier "internal"
STEP
@tier "internal"
RANKED
@tier "internal"
REQUEST_EMBEDDED {
embeddings : [[number]]!
}
@tier "internal"
CATALOG_LISTED {
result : [CatalogHit]!
}
@tier "internal"
DESCRIBED {
result : { behavior : string!, knobs : [KnobField]!, orbitals : [{ value : orbital!, knobs : [KnobField]!, traits : [{ trait : string!, knobs : [KnobField]! }]! }]! }!
}
@tier "internal"
CHOSEN {
choice : string!
confidence : number!
}
@tier "internal"
BUILT {
result : { behavior : string!, value : behavior! }!
}
@tier "internal"
BUILD_FAILED {
error : string!
errors : [BuildIssue]
}
@tier "internal"
}
listens {
BuilderTools.ASSISTANT_REPLIED -> ASSISTANT_REPLIED
BuilderTools.ASSISTANT_REPLY_FAILED -> TOOLS_FAILED
START -> external {
request : string!
orbitalName : string!
context : string
}
@description "Build a behavior for the request; orbitalName names the program a mount or fill writes; context is any extra the fill turn should know."
FILL -> external {
config : Map string SExpr
traits : Map string FilledTrait
fields : Map string string
}
@description "The model's knob settings for the building block and the extra fields it was asked to write."
PICK -> external {
behavior : string!
fields : Map string string
}
@description "The model's pick among the building blocks a fill step offered."
ASSISTANT_REPLIED {
reply : string
}
TOOLS_FAILED {
error : string!
}
POOL_FOUND {
hits : [{ id : string!, behavior : string!, value : behavior!, name : string, kind : string, topic : string, fields : Map string string, description : string, score : number! }]!
}
@description "The pool's answer to POOL_SEARCH: its best entries, best first."
RESET
}
config {
fieldWordLimits : [FieldWordLimit] = []
@label "Most words per fill field"
@description "A fill field written longer than its limit goes back to the model as a repair turn; after the last repair turn the build goes ahead with what was written."
@tier "policy"
fillEvent : EventAddress = "BuilderPipeline.FILL"
@label "Fill tool event"
@description "The address the model's FILL tool fires; a consumer that renames this trait sets it to its own name."
@tier "internal"
fillFields : [AgentToolField] = []
@label "Extra fields the fill turn writes"
@description "Fields the model fills alongside the knobs (e.g. a one-line hint); they come back in BUILD_COMPLETE's `fields`."
@tier "domain"
fillInstructions : string = "You adapt an existing building block to a request. Call the FILL tool once: set only the knobs the request needs (in `config` and `traits` → trait → `config`), write every requested field in `fields`, then reply with one sentence."
@label "How the fill turn is briefed"
@tier "domain"
ladder : [BuilderStep] = [{
action: mount
name: mount
scope: (almadar-std/ui/core/molecules)
source: catalog
take: 1
threshold: 0
}]
@label "Caching tiers, cheapest first"
@description "Each step ranks its source (a registry catalog under `scope`, or the pool) against the request and, when the best match reaches `threshold`, runs `action` on it: `mount` (a page around its first trait), `adopt` (serve it as it is, no model call) or `fill` (one model turn setting its knobs). A step whose best match falls short hands over to the next one; when no step serves, the build is rejected."
@synonyms "tiers, cache levels, retrieval ladder"
@tier "domain"
maxRepairs : number = 2
@label "Repair turns"
@description "How many times validator issues go back to the model before the build fails."
@tier "policy"
pickDecider : "chat" | "jev" = chat
@label "Who picks the building block"
@description "`chat`: a model turn picks it (and writes `pickFields`). `jev`: the decision model picks it in one typed choice (`llm choose`), and the fill turn writes `pickFields`."
@tier "policy"
pickEvent : EventAddress = "BuilderPipeline.PICK"
@label "Pick tool event"
@description "The address the model's PICK tool fires; a consumer that renames this trait sets it to its own name."
@tier "internal"
pickFields : [AgentToolField] = []
@label "Fields the pick turn writes"
@description "Fields the model writes while it picks the building block, before it sees the block's knobs (e.g. a how-to-play hint that must not lean on the content). They win over the fill turn's; with no pick turn the fill turn writes them."
@tier "domain"
pickInstructions : string = "Several building blocks could serve the request. Pick the one whose interaction does what the request asks (sorting into groups, putting in order, estimating, exploring…), not just the one about the same subject. Call the PICK tool once with the block and every requested field, then reply with one sentence."
@label "How the pick turn is briefed"
@description "Used when a fill step takes more than one candidate: the model picks the building block before filling it."
@tier "domain"
pickQuestion : string = "Which building block's interaction does what the request asks (sorting into groups, putting in order, estimating, exploring), not just the one about the same subject?"
@label "The decision model's question"
@tier "domain"
statusSlot : slot = main
@label "Status slot"
@description "Where the builder shows its one-line status; a page running it in the background sends it to `system`."
@tier "presentation"
}
}The compiler produces each of the following from the same .lolo source.
A programming language of composable state machines.