class LittleGhost::AssemblyBuilder
Builds an Assembly when its participants or routes are discovered at runtime.
Class definitions are the usual, easier-to-find way to declare behavior. Builders expose the underlying dynamic form while preserving the same ask, stream_ask, call, and stream interface:
graph = LittleGhost::GraphBuilder.new(id: "support_flow") graph.node :triage, TriageAgent graph.node :respond, CustomerSupportAgent graph.start :triage graph.edge :triage, :respond graph.finish :respond graph.validate! run = graph.ask("Can I get a refund?")
A builder remains mutable. Each build or invocation copies its declarations and referenced Assembly definitions. Later builder changes affect future executions without changing an Assembly already built. Ruby closures and the objects they reference remain live application code.
Attributes
Optional Runtime reused by standalone executions from this builder.
Public Class Methods
# File lib/little_ghost/assembly_builder.rb, line 63 def initialize(id: nil, description: nil, runtime: nil, base: nil) @mutex = Mutex.new @assembly_id = id&.to_s&.dup&.freeze @description = description&.to_s&.dup&.freeze @runtime = runtime @base = base end
Creates a mutable builder with optional identity, runtime, and base class.
Public Instance Methods
Source
# File lib/little_ghost/assembly_builder.rb, line 147 def as_tool(**options) = build.as_tool(**options)
Exposes the current declarations as a Tool.
Source
# File lib/little_ghost/assembly_builder.rb, line 130 def ask(message, **options) = build.ask(message, **options)
Executes the current declarations and returns their Run.
Source
# File lib/little_ghost/assembly_builder.rb, line 72 def assembly_id(value = nil) return @mutex.synchronize { @assembly_id || default_assembly_id } if value.nil? @mutex.synchronize { @assembly_id = String(value).dup.freeze } self end
Reads or assigns the stable Assembly identifier.
Source
# File lib/little_ghost/assembly_builder.rb, line 88 def assembly_kind = self.class.assembly_kind
Returns :agent, :workflow, :swarm, or :graph.
# File lib/little_ghost/assembly_builder.rb, line 122 def build(runtime: self.runtime, run: nil) snapshot = definition return (runtime || run.runtime).build_assembly(snapshot, run:) if run snapshot.implementation.new(runtime:) end
Builds one execution instance from the current declarations.
# File lib/little_ghost/assembly_builder.rb, line 141 def call(input = nil, **options) = build.call(input, **options)
Executes the current declarations to completion.
Source
# File lib/little_ghost/assembly_builder.rb, line 97 def definition stack = Thread.current[:little_ghost_assembly_definition_stack] ||= [] identity = base || self if stack.include?(identity) raise ConfigurationError, "assembly definitions cannot contain themselves recursively" end stack << identity state = @mutex.synchronize { snapshot_state } implementation = build_implementation(state) prepare_implementation!(implementation) validate_implementation!(implementation) seal_implementation!(implementation) implementation.freeze AssemblyDefinition.new( kind: assembly_kind, assembly_id: implementation.assembly_id, description: implementation.description, implementation: ) ensure stack&.pop if stack&.last.equal?(identity) Thread.current[:little_ghost_assembly_definition_stack] = nil if stack && stack.empty? end
Returns a complete definition for the builder’s current declarations.
Source
# File lib/little_ghost/assembly_builder.rb, line 80 def description(value = nil) return @mutex.synchronize { @description || base_description } if value.nil? @mutex.synchronize { @description = String(value).dup.freeze } self end
Reads or assigns the human-readable description.
# File lib/little_ghost/assembly_builder.rb, line 145 def start_execution(payload, &block) = build.start_execution(payload, &block)
Starts a supervised execution from the current declarations.
# File lib/little_ghost/assembly_builder.rb, line 143 def stream(input = nil, **options) = build.stream(input, **options)
Streams the current declarations as StreamEvent objects.
# File lib/little_ghost/assembly_builder.rb, line 133 def stream_ask(message, **options) snapshot = definition Enumerator.new do |events| snapshot.implementation.new(runtime:).stream_ask(message, **options).each { |event| events << event } end end
Lazily streams an execution built from the current declarations.
Source
# File lib/little_ghost/assembly_builder.rb, line 91 def validate! definition self end
Validates the builder’s current declarations and returns this builder.