Class: AgUi::RunLoop
- Inherits:
-
Object
- Object
- AgUi::RunLoop
- Defined in:
- lib/ag_ui/run_loop.rb
Overview
The run loop: drives one AG-UI run through a brute turn pipeline.
The terminal block is the LLM call (ruby_llm or anything else) — it receives brute's env (events:, ...), streams deltas into env (translated live to SSE by EventBridge) and appends the assistant message to env. The gem stays LLM-agnostic.
run_loop = AgUi::RunLoop.new(system_prompt: PROMPT) do |env|
env[:events] << { type: :text_message_start, data: { message_id: id } }
... stream provider chunks ...
env[:events] << { type: :text_message_end, data: { message_id: id } }
env[:messages].assistant(full_text)
end
app = AgUi.agent(agent_id: "default", &run_loop)
Lifecycle per run (the AG-UI contract): RUN_STARTED first; then the pipeline streams; then RUN_FINISHED — or RUN_ERROR if the pipeline raised. Schema-validation failures are wire-contract bugs and re-raise after RUN_ERROR so they fail loudly in dev.
Instance Method Summary collapse
- #a2ui_enabled? ⇒ Boolean
- #handle(rack_env) ⇒ Object
-
#initialize(system_prompt: nil, validate: true, middleware: [], a2ui: nil, server_tools: [], max_iterations: 10, &terminal) ⇒ RunLoop
constructor
a2ui: nil/false = off; an AgUi::A2ui::Catalog = on with that catalog; true = on degraded (tool injected, no component schema).
-
#to_proc ⇒ Object
AgUi.agent takes a block; RunLoop quacks like one.
Constructor Details
#initialize(system_prompt: nil, validate: true, middleware: [], a2ui: nil, server_tools: [], max_iterations: 10, &terminal) ⇒ RunLoop
a2ui: nil/false = off; an AgUi::A2ui::Catalog = on with that catalog; true = on degraded (tool injected, no component schema). server_tools: [description:, parameters:, handler:] execute inline and the turn loops (Loop::ToolResult) until the model answers in text, a client tool defers to the browser, or max_iterations hits.
34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/ag_ui/run_loop.rb', line 34 def initialize(system_prompt: nil, validate: true, middleware: [], a2ui: nil, server_tools: [], max_iterations: 10, &terminal) unless terminal raise ArgumentError, "RunLoop requires a terminal block (the LLM call)" end @system_prompt = system_prompt @validate = validate @middleware = middleware @a2ui = a2ui @server_tools = server_tools @max_iterations = max_iterations @terminal = terminal end |
Instance Method Details
#a2ui_enabled? ⇒ Boolean
49 50 51 |
# File 'lib/ag_ui/run_loop.rb', line 49 def a2ui_enabled? !(@a2ui.nil? || @a2ui == false) end |
#handle(rack_env) ⇒ Object
59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/ag_ui/run_loop.rb', line 59 def handle(rack_env) input = rack_env["ag_ui.input"] rack_env["ag_ui.stream"].open( thread_id: input.thread_id, run_id: input.run_id, validate: @validate, ) do |stream| stream.run_started run(stream, input) end end |
#to_proc ⇒ Object
AgUi.agent takes a block; RunLoop quacks like one.
54 55 56 57 |
# File 'lib/ag_ui/run_loop.rb', line 54 def to_proc run_loop = self proc { |rack_env| run_loop.handle(rack_env) } end |