Class: Insika::Safety::Config

Inherits:
Object
  • Object
show all
Defined in:
lib/insika/safety/config.rb

Overview

Per-agent guardrail configuration (RFC-0009 §3.3 / D6), read from profile.guardrails. OPT-IN like capabilities: an agent that says nothing gets the CONSERVATIVE default — deterministic detectors ON, LLM moderator OFF.

Tolerant of the JSON round-trip (string OR symbol keys / values), same discipline as ModelPolicy — the StoredProfileSource persists this as a plain Hash and it comes back stringified.

guardrails: {
input:      true|false,        # run the input guardrail middleware (default true)
output:     true|false,        # run the output filter + validator (default true)
moderator:  "provider/model"|nil,  # LLM moderator model; nil = deterministic only
strictness: "low"|"medium"|"high", # which input categories fire (default medium)
responses:  { <category> => "<safe reply>", ... }  # per-agent override, see below
}

responses is the CONFIGURATION-OVER-CONVENTION knob (RFC-0009 §7). The engine ships neutral built-in refusals (Safety::SafeResponses::DEFAULTS), but this is OSS across arbitrary businesses/languages, so we never hard-bake tone: an agent overrides the safe reply per category (injection/sexual/abuse/escalate/ …) or sets a single catch-all default. Resolution order (SafeResponses.for): agentagent → built-in → built-in.

Constant Summary collapse

STRICTNESS_CATEGORIES =

strictness -> input categories that the deterministic scan runs. low = only injection (+ output redaction) — highest confidence, fewest FPs medium = injection + sexual + abuse (the default) high = same families, reserved for future broader lists

{
  low: %i[injection],
  medium: %i[injection sexual abuse],
  high: %i[injection sexual abuse]
}.freeze
DEFAULT_STRICTNESS =
:medium

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(input:, output:, moderator:, strictness:, responses: {}) ⇒ Config

Returns a new instance of Config.



42
43
44
45
46
47
48
# File 'lib/insika/safety/config.rb', line 42

def initialize(input:, output:, moderator:, strictness:, responses: {})
  @input = input
  @output = output
  @moderator = moderator
  @strictness = strictness
  @responses = responses # { "category" => "safe reply" }, agent override map
end

Instance Attribute Details

#inputObject (readonly)

Returns the value of attribute input.



40
41
42
# File 'lib/insika/safety/config.rb', line 40

def input
  @input
end

#moderatorObject (readonly)

Returns the value of attribute moderator.



40
41
42
# File 'lib/insika/safety/config.rb', line 40

def moderator
  @moderator
end

#outputObject (readonly)

Returns the value of attribute output.



40
41
42
# File 'lib/insika/safety/config.rb', line 40

def output
  @output
end

#responsesObject (readonly)

Returns the value of attribute responses.



40
41
42
# File 'lib/insika/safety/config.rb', line 40

def responses
  @responses
end

#strictnessObject (readonly)

Returns the value of attribute strictness.



40
41
42
# File 'lib/insika/safety/config.rb', line 40

def strictness
  @strictness
end

Class Method Details

.from_hash(raw) ⇒ Object



54
55
56
57
58
59
60
61
62
63
# File 'lib/insika/safety/config.rb', line 54

def self.from_hash(raw)
  h = symbolize(raw)
  new(
    input: bool(h.fetch(:input, true)),
    output: bool(h.fetch(:output, true)),
    moderator: presence(h[:moderator]),
    strictness: normalize_strictness(h[:strictness]),
    responses: normalize_responses(h[:responses])
  )
end

.from_profile(profile) ⇒ Object

Builds a Config from a profile. A nil/empty guardrails -> the conservative default (see from_hash).



52
# File 'lib/insika/safety/config.rb', line 52

def self.from_profile(profile) = from_hash(profile.guardrails)

Instance Method Details

#enabled?Boolean

A guardrail is fully off only when BOTH sides are disabled — cheap early-out.

Returns:

  • (Boolean)


69
# File 'lib/insika/safety/config.rb', line 69

def enabled? = @input || @output

#input_categoriesObject

Input categories the deterministic scan should run, per strictness.



66
# File 'lib/insika/safety/config.rb', line 66

def input_categories = STRICTNESS_CATEGORIES.fetch(@strictness, STRICTNESS_CATEGORIES[DEFAULT_STRICTNESS])

#moderator?Boolean

Returns:

  • (Boolean)


71
# File 'lib/insika/safety/config.rb', line 71

def moderator? = !@moderator.nil?