Class: Ask::Agent::Policies::ApprovalPolicy

Inherits:
Object
  • Object
show all
Defined in:
lib/ask/agent/policies/approval_policy.rb

Overview

Approval policy hook: classifies tool calls as approval-required and routes them into an ApprovalQueue.

Wire it as a before_tool hook on a Session (or enable it with Session.new(approval: true)), and any tool whose class declares approval_required true — or whose name matches the policy's rule-based lists — is queued for human approval instead of executed. The agent receives a pending result and continues; the tool runs only after a human approves it.

Examples:

queue = Ask::Agent::ApprovalQueue.new
policy = Ask::Agent::Policies::ApprovalPolicy.new(queue: queue)
session = Ask::Agent::Session.new(
  model: "gpt-4o",
  tools: [SendEmail],
  hooks: { before_tool: [policy.method(:before_tool_call)] }
)

# Later, when the user decides:
session.approval_queue.approve_all

Instance Method Summary collapse

Constructor Details

#initialize(queue:, require_approval: nil, rules: nil, tools: nil) ⇒ ApprovalPolicy

Returns a new instance of ApprovalPolicy.

Parameters:

  • queue (Ask::Agent::ApprovalQueue)

    the queue actions go into. The queue owns the user-enabled auto-approval rules; this policy only reports each tool's own declaration.

  • require_approval (Array<String, Regexp>, :all, nil) (defaults to: nil)

    extra rule-based classification on top of the tool's own declaration. Strings match tool names exactly, Regexps match against the name, and :all requires approval for every tool call.

  • rules (Ask::Agent::Policies::PermissionRules, nil) (defaults to: nil)

    persisted allow/ask/deny patterns. Rules classify first and take precedence over tool declarations: :deny blocks, :allow proceeds without the queue, :ask queues regardless of auto-approvable.

  • tools (Array<Object>, nil) (defaults to: nil)

    the session's resolved tool instances, used to read class-level declarations (approval_required, auto_approvable). When nil, only the rule-based lists classify calls.



43
44
45
46
47
48
# File 'lib/ask/agent/policies/approval_policy.rb', line 43

def initialize(queue:, require_approval: nil, rules: nil, tools: nil)
  @queue = queue
  @require_approval = require_approval
  @rules = rules
  @tools = Array(tools)
end

Instance Method Details

#before_tool_call(tool_call, _context) ⇒ Hash

Hook entry point — matches the before_tool hook signature.

Parameters:

Returns:

  • (Hash)

    :proceed to run, :pending, action_id:, reason: to queue for approval, or :block, reason: to refuse



57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/ask/agent/policies/approval_policy.rb', line 57

def before_tool_call(tool_call, _context)
  case @rules&.classify(tool_call.name, tool_call.arguments)
  when :deny
    return { action: :block, reason: "Denied by permission rules: '#{tool_call.name}'" }
  when :allow
    return { action: :proceed }
  when :ask
    return queue_for_approval(tool_call, auto_approvable: false)
  end

  return { action: :proceed } unless approval_required?(tool_call.name)

  queue_for_approval(tool_call, auto_approvable: tool_auto_approvable?(tool_call.name))
end