Class: DecisionAgent::Agent

Inherits:
Object
  • Object
show all
Defined in:
lib/decision_agent/agent.rb

Overview

Agent runs multiple evaluators over a context, scores their evaluations, and returns a single Decision with the chosen outcome and confidence.

Class Attribute Summary collapse

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(evaluators:, scoring_strategy: nil, audit_adapter: nil, validate_evaluations: nil) ⇒ Agent

Returns a new instance of Agent.

Parameters:

  • evaluators (Array<#evaluate>)

    Objects that respond to #evaluate(context, feedback:)

  • scoring_strategy (Scoring::Base, nil) (defaults to: nil)

    Strategy to score evaluations (default: WeightedAverage)

  • audit_adapter (Audit::Base, nil) (defaults to: nil)

    Adapter for recording decisions (default: NullAdapter)

  • validate_evaluations (Boolean, nil) (defaults to: nil)

    If true, validate evaluations; nil = validate unless production



28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/decision_agent/agent.rb', line 28

def initialize(evaluators:, scoring_strategy: nil, audit_adapter: nil, validate_evaluations: nil)
  @evaluators = Array(evaluators)
  @scoring_strategy = scoring_strategy || Scoring::WeightedAverage.new
  @audit_adapter = audit_adapter || Audit::NullAdapter.new
  # Default to validating in development, skip in production for performance
  @validate_evaluations = validate_evaluations.nil? ? (ENV["RAILS_ENV"] != "production") : validate_evaluations

  validate_configuration!

  # Freeze instance variables for thread-safety
  @evaluators.freeze
end

Class Attribute Details

.hash_cacheObject (readonly)

Returns the value of attribute hash_cache.



21
22
23
# File 'lib/decision_agent/agent.rb', line 21

def hash_cache
  @hash_cache
end

.hash_cache_max_sizeObject (readonly)

Returns the value of attribute hash_cache_max_size.



21
22
23
# File 'lib/decision_agent/agent.rb', line 21

def hash_cache_max_size
  @hash_cache_max_size
end

.hash_cache_mutexObject (readonly)

Returns the value of attribute hash_cache_mutex.



21
22
23
# File 'lib/decision_agent/agent.rb', line 21

def hash_cache_mutex
  @hash_cache_mutex
end

Instance Attribute Details

#audit_adapterObject (readonly)

Returns the value of attribute audit_adapter.



11
12
13
# File 'lib/decision_agent/agent.rb', line 11

def audit_adapter
  @audit_adapter
end

#evaluatorsObject (readonly)

Returns the value of attribute evaluators.



11
12
13
# File 'lib/decision_agent/agent.rb', line 11

def evaluators
  @evaluators
end

#scoring_strategyObject (readonly)

Returns the value of attribute scoring_strategy.



11
12
13
# File 'lib/decision_agent/agent.rb', line 11

def scoring_strategy
  @scoring_strategy
end

Instance Method Details

#decide(context:, feedback: {}) ⇒ Decision

Runs all evaluators on the context, scores results, and returns a single decision.

Parameters:

  • context (Context, Hash)

    Input data; converted to Context if a Hash

  • feedback (Hash) (defaults to: {})

    Optional feedback passed to each evaluator

Returns:

  • (Decision)

    The chosen decision with confidence, explanations, and audit payload

Raises:



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/decision_agent/agent.rb', line 47

def decide(context:, feedback: {})
  ctx = context.is_a?(Context) ? context : Context.new(context)

  evaluations = collect_evaluations(ctx, feedback)

  raise NoEvaluationsError if evaluations.empty?

  # Validate all evaluations for correctness and thread-safety (optional for performance)
  EvaluationValidator.validate_all!(evaluations) if @validate_evaluations

  scored_result = @scoring_strategy.score(evaluations)

  decision_value = scored_result[:decision]
  confidence_value = scored_result[:confidence]

  explanations = build_explanations(evaluations, decision_value, confidence_value)

  audit_payload = build_audit_payload(
    context: ctx,
    evaluations: evaluations,
    decision: decision_value,
    confidence: confidence_value,
    feedback: feedback
  )

  decision = Decision.new(
    decision: decision_value,
    confidence: confidence_value,
    explanations: explanations,
    evaluations: evaluations,
    audit_payload: audit_payload
  )

  @audit_adapter.record(decision, ctx)

  decision
end