Class: Brute::Hooks

Inherits:
Object
  • Object
show all
Defined in:
lib/brute/hooks.rb

Overview

Pub/sub registry for agent lifecycle hooks, subscribed on the builder:

Brute.agent
.use(Brute::Middleware::MaxIterations)
.run(->(env) { env[:messages].assistant("done") })
.on(:before_llm) { |env| ... }
.on(:approve_tool) { |call| call[:name] != "exec" }

Emission points and payloads:

:turn_start, :turn_end  → the turn env (AgentPipeline#start; turn_end
                        fires from an ensure, so it also fires on error)
:before_llm, :after_llm → the turn env, around every LLM call
:before_tool            → call env {name:, arguments:, result:, events:,
                        metadata:, turn_env:} — mutate :arguments to
                        rewrite the call, or set :result (or return a
                        value) to skip execution entirely ("respond")
:approve_tool           → call env — a false return denies the call; a
                        String return denies it with that message
:after_tool             → call env — mutate :result

Subscribers run inline (tool events may fire from parallel threads). Exceptions propagate to the caller — layers that want fail-open semantics rescue in their own subscriber.

Constant Summary collapse

EVENTS =
%i[turn_start turn_end before_llm after_llm before_tool approve_tool after_tool].freeze

Instance Method Summary collapse

Constructor Details

#initializeHooks

Returns a new instance of Hooks.



34
35
36
# File 'lib/brute/hooks.rb', line 34

def initialize
  @subscribers = Hash.new { |hash, key| hash[key] = [] }
end

Instance Method Details

#any?(event) ⇒ Boolean

Returns:

  • (Boolean)


49
# File 'lib/brute/hooks.rb', line 49

def any?(event) = @subscribers[event.to_sym].any?

#emit(event, payload) ⇒ Object

Fire an event; returns every subscriber's raw result (nils and false included — the deny contract distinguishes them).



45
46
47
# File 'lib/brute/hooks.rb', line 45

def emit(event, payload)
  @subscribers[event.to_sym].map { |subscriber| subscriber.call(payload) }
end

#on(event, &block) ⇒ Object



38
39
40
41
# File 'lib/brute/hooks.rb', line 38

def on(event, &block)
  @subscribers[event.to_sym] << block
  self
end