Module: Silas::NestedRunner

Defined in:
lib/silas/nested_runner.rb

Overview

Drives a nested subagent Session's turn to terminal INLINE (no AgentLoopJob), inside the parent's delegate #call. Swaps the subagent's scope in as the active globals for the duration, then restores — so the existing loop machinery (StepRunner/Instructions/Budget/Ledger) runs unchanged against the subagent's tools/instructions. Synchronous, depth-1 (v1).

Durability of the nested run = its persisted rows; its exactly-once BOUNDARY is the parent's at_most_once delegate invocation (a crash parks it in-doubt).

Class Method Summary collapse

Class Method Details

.run(session, input:) ⇒ Object



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/silas/nested_runner.rb', line 13

def run(session, input:)
  scope = Silas.subagent_scope(session.agent_name)
  turn = session.turns.create!(index: 0, input: input)

  Silas.with_agent_scope(scope) do
    agent = scope.agent
    turn.update!(status: "running", started_at: Time.current)
    Instructions.snapshot!(turn) # renders the SUBAGENT's instructions + snapshots ITS digest

    index = 0
    loop do
      case StepRunner.call(turn, index)
      when :parked   then return turn.finish!(:failed, reason: "subagent_parked") && turn.reload
      when :terminal then return turn.finish!(:completed) && turn.reload
      end
      if (reason = Budget.exceeded_reason(turn, agent: agent))
        return turn.finish!(:failed, reason: reason) && turn.reload
      end

      index += 1
      if index >= agent.max_steps
        turn.finish!(:failed, reason: "max_steps")
        return turn.reload
      end
    end
  end
end