A renga circle
A renga circle: three poet agents compose a linked-verse poem, each verse responding to the one before it. The dependency graph IS the poem's form - verse 2 cannot begin until verse 1 exists, and the orchestrator pipes each verse into the poet who answers it.
Plans & Graphs
Round 2
Matz
exit 0
bundle exec ruby examples/renga_circle.rb
a real captured run
~ a renga on "autumn wind" ~ first light, autumn wind - the pond remembers last night's moon answering first: autumn wind paints the hillside in a brush of geese yes, geese - and yet even this autumn wind is home to someone small (completed in 108ms)
source
# frozen_string_literal: true # A renga circle: three poet agents compose a linked-verse poem, each # verse responding to the one before it. The dependency graph IS the # poem's form - verse 2 cannot begin until verse 1 exists, and the # orchestrator pipes each verse into the poet who answers it. # # bundle exec ruby examples/renga_circle.rb # # Runs offline: each poet's craft is a lambda-backed capability. require class="s">"bundler/setup" require class="s">"agentic" STYLES = { class="s">"Basho" => ->(theme, previous) { previous ? class="s">"#{previous.split.last} lingers -\n#{theme} on the temple bell\na crow shakes off rain" : class="s">"first light, #{theme} -\nthe pond remembers\nlast night's moon" }, class="s">"Buson" => ->(theme, previous) { class="s">"answering #{previous.split.first}:\n#{theme} paints the hillside\nin a brush of geese" }, class="s">"Issa" => ->(theme, previous) { class="s">"yes, #{previous.split.last} - and yet\neven this #{theme}\nis home to someone small" } }.freeze # Each poet is an agent with a single "verse" capability poets = STYLES.to_h do |name, craft| spec = Agentic:class="y">:CapabilitySpecification.new( name: class="s">"verse_#{name.downcase}", description: class="s">"Compose a linked verse in #{name}'s voice", version: class="s">"1.0.0", inputs: { theme: {type: class="s">"string", required: true}, previous: {type: class="s">"string", description: class="s">"The verse being answered"} }, outputs: {verse: {type: class="s">"string", required: true}} ) provider = Agentic:class="y">:CapabilityProvider.new( capability: spec, implementation: ->(inputs) { {verse: craft.call(inputs[class="y">:theme], inputs[class="y">:previous])} } ) Agentic.register_capability(spec, provider) poet = Agentic:class="y">:Agent.build do |a| a.name = name a.role = class="s">"Renga poet" end poet.add_capability(class="s">"verse_#{name.downcase}") [name, poet] end theme = ARGV.first || class="s">"autumn wind" orchestrator = Agentic:class="y">:PlanOrchestrator.new # The circle: each poet's task depends on the previous poet's, and the # previous verse arrives through the dependency pipe - no shared state tasks = [] %w[Basho Buson Issa].each do |name| task = Agentic:class="y">:Task.new( description: name, agent_spec: Agentic:class="y">:AgentSpecification.new( name: name, description: class="s">"Renga poet", instructions: class="s">"Compose one linked verse" ), payload: theme ) orchestrator.add_task(task, tasks.empty? ? [] : [tasks.last], agent: ->(t) { previous = t.dependency_outputs.values.first poets[t.description].execute_capability( class="s">"verse_#{t.description.downcase}", {theme: t.payload, previous: previous}.compact )[class="y">:verse] }) tasks << task end result = orchestrator.execute_plan puts class="s">" ~ a renga on \"#{theme}\class="s">" ~" puts tasks.each do |task| puts result.results[task.id].output.split(class="s">"\n").map { |line| class="s">" #{line}" } puts end puts class="s">" (#{result.status} in #{(result.execution_time * 1000).round}ms)"