Class: Silas::Tool
- Inherits:
-
Object
show all
- Defined in:
- lib/silas/tool.rb
Overview
Base class for agent tools. The keyword signature of #call IS the schema:
class Agent::Tools::IssueRefund < Silas::Tool
description "Refund an order."
param :amount, :integer, desc: "Pence" # optional type refinement
approval :always # :never | :once | :always | lambda
transactional! # or at_most_once! (default) / idempotent!
def call(order_id:, amount:, note: nil)
...
end
end
Tool identity is the FILENAME (app/agent/tools/issue_refund.rb -> "issue_refund"),
eve's convention, enforced by the Registry.
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
Instance Attribute Details
#session ⇒ Object
Execution context, set by the Ledger before #call.
87
88
89
|
# File 'lib/silas/tool.rb', line 87
def session
@session
end
|
Class Method Details
.approval(policy = nil, &block) ⇒ Object
Also known as:
approval_policy
28
29
30
31
|
# File 'lib/silas/tool.rb', line 28
def approval(policy = nil, &block)
@approval_policy = block || policy unless policy.nil? && block.nil?
@approval_policy || :never
end
|
.at_most_once! ⇒ Object
36
|
# File 'lib/silas/tool.rb', line 36
def at_most_once! = @effect_mode = :at_most_once
|
.description(text = nil) ⇒ Object
19
20
21
22
|
# File 'lib/silas/tool.rb', line 19
def description(text = nil)
@description = text if text
@description || ""
end
|
.effect_mode ⇒ Object
38
|
# File 'lib/silas/tool.rb', line 38
def effect_mode = @effect_mode || :at_most_once
|
.idempotent! ⇒ Object
35
|
# File 'lib/silas/tool.rb', line 35
def idempotent! = @effect_mode = :idempotent
|
.param(name, type = :string, desc: nil) ⇒ Object
24
25
26
|
# File 'lib/silas/tool.rb', line 24
def param(name, type = :string, desc: nil)
param_refinements[name.to_sym] = { type: type.to_s, desc: desc }
end
|
.schema ⇒ Object
description:, input_schema: — provider-agnostic JSON schema.
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
# File 'lib/silas/tool.rb', line 45
def schema
validate_signature!
properties = {}
required = []
instance_method(:call).parameters.each do |kind, pname|
refinement = param_refinements[pname] || {}
properties[pname.to_s] = { "type" => refinement[:type] || "string" }
properties[pname.to_s]["description"] = refinement[:desc] if refinement[:desc]
required << pname.to_s if kind == :keyreq
end
{
"name" => tool_name,
"description" => description,
"input_schema" => {
"type" => "object",
"properties" => properties,
"required" => required
}
}
end
|
40
41
42
|
# File 'lib/silas/tool.rb', line 40
def tool_name
name.demodulize.underscore
end
|
.transactional! ⇒ Object
34
|
# File 'lib/silas/tool.rb', line 34
def transactional! = @effect_mode = :transactional
|
.validate_signature! ⇒ Object
66
67
68
69
70
71
72
73
|
# File 'lib/silas/tool.rb', line 66
def validate_signature!
raise Error, "#{name} must define #call" unless method_defined?(:call)
kinds = instance_method(:call).parameters.map(&:first)
if kinds.any? { |k| %i[req opt rest].include?(k) }
raise Error, "#{name}#call must accept keyword arguments only — the signature is the schema"
end
end
|
Instance Method Details
#approval_policy ⇒ Object
Instance-side delegation so a resolved instance answers the Ledger.
83
|
# File 'lib/silas/tool.rb', line 83
def approval_policy = self.class.approval_policy
|
#call ⇒ Object
89
90
91
|
# File 'lib/silas/tool.rb', line 89
def call(**)
raise NotImplementedError, "#{self.class}#call"
end
|
#effect_mode ⇒ Object
84
|
# File 'lib/silas/tool.rb', line 84
def effect_mode = self.class.effect_mode
|