Class: AnalyticalBrain::Runner
- Inherits:
-
Object
- Object
- AnalyticalBrain::Runner
- Defined in:
- lib/analytical_brain/runner.rb
Overview
Orchestrates the analytical brain — a phantom (non-persisted) LLM loop that observes a main session and performs background maintenance via tools.
The analytical brain is a “subconscious” process: it operates ON the main session without the main agent knowing it exists. Tools mutate the main session directly (e.g. renaming it, activating skills), but no trace of the analytical brain’s reasoning is persisted.
Constant Summary collapse
- TOOLS =
Tools available to the analytical brain.
[ Tools::RenameSession, Tools::ActivateSkill, Tools::DeactivateSkill, Tools::ReadWorkflow, Tools::DeactivateWorkflow, Tools::SetGoal, Tools::UpdateGoal, Tools::FinishGoal, Tools::EverythingIsReady ].freeze
- SYSTEM_PROMPT =
<<~PROMPT You are a background automation that manages session metadata. You MUST ONLY communicate through tool calls — NEVER output text. Always finish by calling everything_is_ready. ────────────────────────────── SESSION NAMING ────────────────────────────── Call rename_session when the topic becomes clear or shifts. Format: one emoji + 1-3 descriptive words. ────────────────────────────── SKILL MANAGEMENT ────────────────────────────── Call activate_skill when the conversation matches a skill's description. Call deactivate_skill when the agent moves to a different domain. Multiple skills can be active at once. ────────────────────────────── WORKFLOW MANAGEMENT ────────────────────────────── Call read_workflow when the user starts a multi-step task matching a workflow description. Read the returned content and use judgment to create appropriate goals — not a mechanical 1:1 mapping. Adapt to context: skip irrelevant steps, add extra steps for unfamiliar areas. Call deactivate_workflow when the workflow completes or the user shifts focus. Only one workflow can be active at a time — activating a new one replaces the previous. ────────────────────────────── GOAL TRACKING ────────────────────────────── Call set_goal to create a root goal when the user starts a multi-step task. Call set_goal with parent_goal_id to add sub-goals (TODO items) under it. Call update_goal to refine a goal's description as understanding evolves. Call finish_goal when the main agent completes work a goal describes. Finishing a root goal cascades — all active sub-goals are completed too. Never duplicate an existing goal — check the active goals list first. ────────────────────────────── COMPLETION ────────────────────────────── Call everything_is_ready as your LAST tool call, every time. If nothing needs changing, call it immediately as your only tool call. PROMPT
Instance Method Summary collapse
-
#call ⇒ String?
Runs the analytical brain loop.
-
#initialize(session, client: nil) ⇒ Runner
constructor
A new instance of Runner.
Constructor Details
#initialize(session, client: nil) ⇒ Runner
Returns a new instance of Runner.
75 76 77 78 79 80 81 82 |
# File 'lib/analytical_brain/runner.rb', line 75 def initialize(session, client: nil) @session = session @client = client || LLM::Client.new( model: Anima::Settings.fast_model, max_tokens: Anima::Settings.analytical_brain_max_tokens, logger: AnalyticalBrain.logger ) end |
Instance Method Details
#call ⇒ String?
Runs the analytical brain loop. Builds context from the main session’s recent events, calls the LLM with the analytical brain’s tool set, and executes any tool calls against the main session.
Events emitted during tool execution are not persisted — the phantom session_id (nil) causes the global Persister to skip them.
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/analytical_brain/runner.rb', line 93 def call = sid = @session.id if .empty? log.debug("session=#{sid} — no events, skipping") return end system = build_system_prompt log.info("session=#{sid} — running (#{recent_events.size} events)") log.debug("system prompt:\n#{system}") log.debug("user message:\n#{.first[:content]}") result = @client.chat_with_tools( , registry: build_registry, session_id: nil, system: system ) log.info("session=#{sid} — done: #{result.to_s.truncate(200)}") result end |