agentic examples

The Plan Forest

The Plan Forest: your graph drawn as a forest - roots at the soil, leaves in the canopy, every task planted at its depth. stats[:roots] and stats[:leaves] (new this round) do the gardening.

Plans & Graphs Round 8 Matz exit 0

source on github

bundle exec ruby examples/plan_forest.rb

a real captured run

THE PLAN FOREST

                  (@) preserve jars    <- canopy
                  (@) feast            <- canopy
               |  harvest
           |  water daily
           |  pull weeds
       |  plant rows
  \_/ gather seeds     <- root
  \_/ till the soil    <- root
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ soil

  8 trees from 2 roots to 2 leaves, canopy 5 high

  the shape at a glance: two roots feed one trunk (plant rows),
  the trunk splits to water and weeds, rejoins at harvest, and
  the canopy bears two fruits. stats[:roots] and stats[:leaves]
  told the gardener where the soil and sunlight are.

source

# frozen_string_literal: true

# The Plan Forest: your graph drawn as a forest - roots at the soil,
# leaves in the canopy, every task planted at its depth. stats[:roots]
# and stats[:leaves] (new this round) do the gardening.
#
#   bundle exec ruby examples/plan_forest.rb
#
# Runs offline; no photosynthesis required.

require class="s">"bundler/setup"
require class="s">"agentic"

def step(name)
  Agentic:class="y">:Task.new(description: name, agent_spec: {class="s">"name" => name, class="s">"instructions" => class="s">"grow"})
end

orchestrator = Agentic:class="y">:PlanOrchestrator.new
seeds = step(class="s">"gather seeds")
till = step(class="s">"till the soil")
plant = step(class="s">"plant rows")
water = step(class="s">"water daily")
weed = step(class="s">"pull weeds")
harvest = step(class="s">"harvest")
preserve = step(class="s">"preserve jars")
feast = step(class="s">"feast")

orchestrator.add_task(seeds)
orchestrator.add_task(till)
orchestrator.add_task(plant, needs: {seed_stock: seeds, bed: till})
orchestrator.add_task(water, [plant])
orchestrator.add_task(weed, [plant])
orchestrator.add_task(harvest, needs: {growth: water, clear_rows: weed})
orchestrator.add_task(preserve, [harvest])
orchestrator.add_task(feast, [harvest])

graph = orchestrator.graph
stats = graph[class="y">:stats]
names = graph[class="y">:tasks].transform_values(&class="y">:description)

# --- the forest: depth becomes altitude ---------------------------------------
canopy = stats[class="y">:depth].values.max
rows = (2..canopy).map { |level| stats[class="y">:depth].select { |_, d| d == level }.keys }

puts class="s">"THE PLAN FOREST"
puts
rows.reverse_each.with_index do |ids, i|
  level = canopy - i
  ids.each do |id|
    leaf = stats[class="y">:leaves].include?(id)
    indent = class="s">"    " * (level - 1)
    puts format(class="s">"  %s%s %-16s %s", indent, leaf ? class="s">"(@)" : class="s">" | ", names[id],
      leaf ? class="s">"<- canopy" : class="s">"")
  end
end
stats[class="y">:roots].each do |id|
  puts format(class="s">"  \\_/ %-16s <- root", names[id])
end
puts class="s">"  #{"~class="s">" * 40} soil"
puts
puts format(class="s">"  %d trees from %d roots to %d leaves, canopy %d high",
  graph[class="y">:tasks].size, stats[class="y">:roots].size, stats[class="y">:leaves].size, canopy)
puts
puts class="s">"  the shape at a glance: two roots feed one trunk (plant rows),"
puts class="s">"  the trunk splits to water and weeds, rejoins at harvest, and"
puts class="s">"  the canopy bears two fruits. stats[class="y">:roots] and stats[class="y">:leaves]"
puts class="s">"  told the gardener where the soil and sunlight are."