Class: Riffer::Agent
- Inherits:
-
Object
- Object
- Riffer::Agent
- Defined in:
- lib/riffer/agent.rb
Overview
Base class for all agents in the Riffer framework. Subclass it to define an agent’s model, instructions, tools, and guardrails.
class MyAgent < Riffer::Agent
model 'openai/gpt-4o'
instructions 'You are a helpful assistant.'
end
agent = MyAgent.new
agent.generate('Hello!')
Defined Under Namespace
Modules: Run, Serializer Classes: Config, Context, Response, Session, StructuredOutput
Constant Summary collapse
- INTERRUPT_MAX_STEPS =
:max_steps
Instance Attribute Summary collapse
-
#config ⇒ Object
readonly
The per-instance Riffer::Agent::Config.
-
#context ⇒ Object
readonly
The mutable runtime context shared with every
Riffer::Agent::Runthis agent executes and threaded through all Proc-based settings. -
#instruction_message ⇒ Object
readonly
The system message built from the configured
instructions, ornilwhen none are configured. -
#model_name ⇒ Object
readonly
The resolved model name (the part after “/” in the model string), used as the model argument on every LLM call.
-
#provider ⇒ Object
readonly
The provider client.
-
#provider_name ⇒ Object
readonly
The resolved provider name (the part before “/” in the model string), e.g.
-
#session ⇒ Object
readonly
The conversation handle.
-
#skills_message ⇒ Object
readonly
The system message describing the configured skills catalog, or
nilwhen skills are unconfigured or the catalog is empty. -
#structured_output ⇒ Object
readonly
The
Riffer::Agent::StructuredOutputwrapping the configured schema, ornilwhen not configured. -
#tool_runtime ⇒ Object
readonly
The tool runtime instance used to execute tool calls.
-
#tools ⇒ Object
readonly
The tool classes the LLM sees on every call this agent makes.
Class Method Summary collapse
-
.all ⇒ Object
Returns all agent subclasses.
-
.config ⇒ Object
Returns the per-class Riffer::Agent::Config holding every DSL setting.
-
.find(identifier) ⇒ Object
Finds an agent class by identifier.
-
.from_h(hash, context: nil, session: nil, tool_resolver: Riffer::Agent::Serializer::DEFAULT_TOOL_RESOLVER, tool_runtime: nil) ⇒ Object
Reconstructs a runnable agent from a wire hash produced by
#to_h. -
.from_json(json, context: nil, session: nil, tool_resolver: Riffer::Agent::Serializer::DEFAULT_TOOL_RESOLVER, tool_runtime: nil) ⇒ Object
Reconstructs a runnable agent from a JSON string produced by
#to_json. -
.generate(prompt = nil, files: nil, context: nil) ⇒ Object
Generates a response using a new agent instance.
-
.guardrail(phase, with:, **options) ⇒ Object
Registers a guardrail for input, output, or both phases.
-
.guardrails_for(phase) ⇒ Object
Returns the registered guardrail configs for a given phase.
-
.identifier(value = nil) ⇒ Object
Gets or sets the agent identifier.
-
.instructions(value = nil) ⇒ Object
Gets or sets the agent instructions.
-
.max_steps(*value) ⇒ Object
Gets or sets the maximum number of LLM call steps in the tool-use loop.
-
.mcp_configs ⇒ Object
Returns the accumulated
use_mcpconfigurations for this agent class. -
.model(value = nil) ⇒ Object
Gets or sets the model string (e.g., “openai/gpt-4o”).
-
.model_options(options = nil) ⇒ Object
Gets or sets model options passed to generate_text/stream_text.
-
.provider_options(options = nil) ⇒ Object
Gets or sets provider options passed to the provider client.
-
.skills(&block) ⇒ Object
Configures skills for this agent via a block DSL, or returns the current Riffer::Skills::Config when called without a block.
-
.stream(prompt = nil, files: nil, context: nil) ⇒ Object
Streams a response using a new agent instance.
-
.structured_output(params = nil, &block) ⇒ Object
Gets or sets the structured output schema for this agent.
-
.tool_runtime(value = nil) ⇒ Object
Gets or sets the tool runtime for this agent; defaults to
Riffer.config.tool_runtimewhen unset. -
.use_mcp(tag, progressive: true) ⇒ Object
Opts this agent into MCP tools from registrations matching the given tag.
-
.uses_tools(value = nil) ⇒ Object
Gets or sets the tools used by this agent.
Instance Method Summary collapse
-
#generate(prompt = nil, files: nil) ⇒ Object
Generates a response from the agent.
-
#initialize(session: nil, context: nil, config: nil) ⇒ Agent
constructor
Initializes a new agent.
-
#interrupt!(reason = nil) ⇒ Object
Interrupts the agent loop from an
on_messagecallback. -
#stream(prompt = nil, files: nil) ⇒ Object
Streams a response from the agent, returning an
EnumeratorofRiffer::StreamEvents. -
#to_h ⇒ Object
Snapshots this resolved agent into a self-contained, provider-neutral wire hash.
-
#to_json ⇒ Object
Snapshots this resolved agent into a wire JSON string.
Constructor Details
#initialize(session: nil, context: nil, config: nil) ⇒ Agent
Initializes a new agent.
A provided session: is used as-is — the caller owns its contents (e.g. cross-process resume from persisted history); an omitted one is seeded with the instruction and skills messages.
Raises Riffer::ArgumentError unless the configured model string is “provider/model” format.
– : (?session: Riffer::Agent::Session?, ?context: Hash[Symbol, untyped]?, ?config: Riffer::Agent::Config?) -> void
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 |
# File 'lib/riffer/agent.rb', line 264 def initialize(session: nil, context: nil, config: nil) @config = config || self.class.config @context = Riffer::Agent::Context.new(context || {}) @provider_name, @model_name = resolve_provider_and_model @provider = build_provider @context.skills = resolve_skills @structured_output = resolve_structured_output @tools = resolve_tools @tool_runtime = resolve_tool_runtime @instruction_message = @skills_message = @session = session || Riffer::Agent::Session.new(messages: [@instruction_message, @skills_message].compact) @session.set(Riffer::Agent::Session::Repair.prune_orphans(@session.)) end |
Instance Attribute Details
#config ⇒ Object (readonly)
The per-instance Riffer::Agent::Config.
217 218 219 |
# File 'lib/riffer/agent.rb', line 217 def config @config end |
#context ⇒ Object (readonly)
The mutable runtime context shared with every Riffer::Agent::Run this agent executes and threaded through all Proc-based settings.
229 230 231 |
# File 'lib/riffer/agent.rb', line 229 def context @context end |
#instruction_message ⇒ Object (readonly)
The system message built from the configured instructions, or nil when none are configured.
221 222 223 |
# File 'lib/riffer/agent.rb', line 221 def @instruction_message end |
#model_name ⇒ Object (readonly)
The resolved model name (the part after “/” in the model string), used as the model argument on every LLM call.
237 238 239 |
# File 'lib/riffer/agent.rb', line 237 def model_name @model_name end |
#provider ⇒ Object (readonly)
The provider client. Public so tests can pre-queue responses on Riffer::Providers::Mock before calling #generate.
241 242 243 |
# File 'lib/riffer/agent.rb', line 241 def provider @provider end |
#provider_name ⇒ Object (readonly)
The resolved provider name (the part before “/” in the model string), e.g. “openai”.
233 234 235 |
# File 'lib/riffer/agent.rb', line 233 def provider_name @provider_name end |
#session ⇒ Object (readonly)
The conversation handle.
214 215 216 |
# File 'lib/riffer/agent.rb', line 214 def session @session end |
#skills_message ⇒ Object (readonly)
The system message describing the configured skills catalog, or nil when skills are unconfigured or the catalog is empty.
225 226 227 |
# File 'lib/riffer/agent.rb', line 225 def @skills_message end |
#structured_output ⇒ Object (readonly)
The Riffer::Agent::StructuredOutput wrapping the configured schema, or nil when not configured.
245 246 247 |
# File 'lib/riffer/agent.rb', line 245 def structured_output @structured_output end |
#tool_runtime ⇒ Object (readonly)
The tool runtime instance used to execute tool calls.
251 252 253 |
# File 'lib/riffer/agent.rb', line 251 def tool_runtime @tool_runtime end |
#tools ⇒ Object (readonly)
The tool classes the LLM sees on every call this agent makes.
248 249 250 |
# File 'lib/riffer/agent.rb', line 248 def tools @tools end |
Class Method Details
.all ⇒ Object
Returns all agent subclasses.
– : () -> Array
166 167 168 |
# File 'lib/riffer/agent.rb', line 166 def self.all subclasses #: Array[singleton(Riffer::Agent)] end |
.config ⇒ Object
Returns the per-class Riffer::Agent::Config holding every DSL setting. – : () -> Riffer::Agent::Config
25 26 27 |
# File 'lib/riffer/agent.rb', line 25 def self.config @config ||= Riffer::Agent::Config.new end |
.find(identifier) ⇒ Object
Finds an agent class by identifier.
– : (String) -> singleton(Riffer::Agent)?
158 159 160 |
# File 'lib/riffer/agent.rb', line 158 def self.find(identifier) all.find { |agent_class| agent_class.identifier == identifier.to_s } end |
.from_h(hash, context: nil, session: nil, tool_resolver: Riffer::Agent::Serializer::DEFAULT_TOOL_RESOLVER, tool_runtime: nil) ⇒ Object
Reconstructs a runnable agent from a wire hash produced by #to_h. – : (Hash[Symbol, untyped], ?context: Hash[Symbol, untyped]?, ?session: Riffer::Agent::Session?, ?tool_resolver: ^(Hash[Symbol, untyped]) -> singleton(Riffer::Tool), ?tool_runtime: (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)?) -> Riffer::Agent
187 188 189 |
# File 'lib/riffer/agent.rb', line 187 def self.from_h(hash, context: nil, session: nil, tool_resolver: Riffer::Agent::Serializer::DEFAULT_TOOL_RESOLVER, tool_runtime: nil) Riffer::Agent::Serializer.from_h(hash, context: context, session: session, tool_resolver: tool_resolver, tool_runtime: tool_runtime) end |
.from_json(json, context: nil, session: nil, tool_resolver: Riffer::Agent::Serializer::DEFAULT_TOOL_RESOLVER, tool_runtime: nil) ⇒ Object
Reconstructs a runnable agent from a JSON string produced by #to_json. – : (String, ?context: Hash[Symbol, untyped]?, ?session: Riffer::Agent::Session?, ?tool_resolver: ^(Hash[Symbol, untyped]) -> singleton(Riffer::Tool), ?tool_runtime: (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)?) -> Riffer::Agent
194 195 196 |
# File 'lib/riffer/agent.rb', line 194 def self.from_json(json, context: nil, session: nil, tool_resolver: Riffer::Agent::Serializer::DEFAULT_TOOL_RESOLVER, tool_runtime: nil) Riffer::Agent::Serializer.from_json(json, context: context, session: session, tool_resolver: tool_resolver, tool_runtime: tool_runtime) end |
.generate(prompt = nil, files: nil, context: nil) ⇒ Object
Generates a response using a new agent instance. – : (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?, ?context: Hash[Symbol, untyped]?) -> Riffer::Agent::Response
173 174 175 |
# File 'lib/riffer/agent.rb', line 173 def self.generate(prompt = nil, files: nil, context: nil) new(context: context).generate(prompt, files: files) end |
.guardrail(phase, with:, **options) ⇒ Object
Registers a guardrail for input, output, or both phases. Raises Riffer::ArgumentError unless phase is :before, :after, or :around. – : (Symbol, with: singleton(Riffer::Guardrail), **untyped) -> void
202 203 204 |
# File 'lib/riffer/agent.rb', line 202 def self.guardrail(phase, with:, **) config.add_guardrail(phase, klass: with, options: ) end |
.guardrails_for(phase) ⇒ Object
Returns the registered guardrail configs for a given phase. – : (Symbol) -> Array[Hash[Symbol, untyped]]
209 210 211 |
# File 'lib/riffer/agent.rb', line 209 def self.guardrails_for(phase) config.guardrails_for(phase) end |
.identifier(value = nil) ⇒ Object
Gets or sets the agent identifier.
– : (?String?) -> String
33 34 35 |
# File 'lib/riffer/agent.rb', line 33 def self.identifier(value = nil) value.nil? ? (config.identifier || Riffer::Helpers::ClassNameConverter.convert(name)) : (config.identifier = value) end |
.instructions(value = nil) ⇒ Object
Gets or sets the agent instructions. A Proc is called at generate time with the context hash (which may be nil).
instructions "You are a helpful assistant."
instructions -> (context) {
"You are assisting #{context[:name]}"
}
– : (?(String | Proc)?) -> (String | Proc)?
56 57 58 |
# File 'lib/riffer/agent.rb', line 56 def self.instructions(value = nil) value.nil? ? config.instructions : (config.instructions = value) end |
.max_steps(*value) ⇒ Object
Gets or sets the maximum number of LLM call steps in the tool-use loop. The splat distinguishes a getter (no argument) from setting the limit to nil (unlimited); it defaults to Riffer::Agent::Config::DEFAULT_MAX_STEPS.
max_steps # reads the current limit
max_steps 8 # cap the loop at 8 steps
max_steps nil # unlimited
– : (*Numeric?) -> Numeric?
98 99 100 101 |
# File 'lib/riffer/agent.rb', line 98 def self.max_steps(*value) return config.max_steps if value.empty? config.max_steps = value.first end |
.mcp_configs ⇒ Object
Returns the accumulated use_mcp configurations for this agent class.
: () -> Array[Hash[Symbol, untyped]]
122 123 124 |
# File 'lib/riffer/agent.rb', line 122 def self.mcp_configs config.mcp_configs end |
.model(value = nil) ⇒ Object
Gets or sets the model string (e.g., “openai/gpt-4o”).
– : (?(String | Proc)?) -> (String | Proc)?
41 42 43 |
# File 'lib/riffer/agent.rb', line 41 def self.model(value = nil) value.nil? ? config.model : (config.model = value) end |
.model_options(options = nil) ⇒ Object
Gets or sets model options passed to generate_text/stream_text.
– : (?Hash[Symbol, untyped]?) -> Hash[Symbol, untyped]
72 73 74 |
# File 'lib/riffer/agent.rb', line 72 def self.( = nil) .nil? ? config. : (config. = ) end |
.provider_options(options = nil) ⇒ Object
Gets or sets provider options passed to the provider client.
– : (?Hash[Symbol, untyped]?) -> Hash[Symbol, untyped]
64 65 66 |
# File 'lib/riffer/agent.rb', line 64 def self.( = nil) .nil? ? config. : (config. = ) end |
.skills(&block) ⇒ Object
Configures skills for this agent via a block DSL, or returns the current Riffer::Skills::Config when called without a block.
skills do
backend Riffer::Skills::FilesystemBackend.new(".skills")
adapter Riffer::Skills::XmlAdapter
activate ["code-review"]
end
– : () ?{ (Riffer::Skills::Config) [self: Riffer::Skills::Config] -> void } -> Riffer::Skills::Config?
145 146 147 148 149 150 151 152 |
# File 'lib/riffer/agent.rb', line 145 def self.skills(&block) if block skills_config = Riffer::Skills::Config.new skills_config.instance_eval(&block) config.skills_config = skills_config end config.skills_config end |
.stream(prompt = nil, files: nil, context: nil) ⇒ Object
Streams a response using a new agent instance. – : (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?, ?context: Hash[Symbol, untyped]?) -> Enumerator[Riffer::StreamEvents::Base, void]
180 181 182 |
# File 'lib/riffer/agent.rb', line 180 def self.stream(prompt = nil, files: nil, context: nil) new(context: context).stream(prompt, files: files) end |
.structured_output(params = nil, &block) ⇒ Object
Gets or sets the structured output schema for this agent. – : (?Riffer::Params?) ?{ (Riffer::Params) [self: Riffer::Params] -> void } -> Riffer::Params?
79 80 81 82 83 84 85 86 |
# File 'lib/riffer/agent.rb', line 79 def self.structured_output(params = nil, &block) if block params = Riffer::Params.new params.instance_eval(&block) end config.structured_output = params if params config.structured_output end |
.tool_runtime(value = nil) ⇒ Object
Gets or sets the tool runtime for this agent; defaults to Riffer.config.tool_runtime when unset. – : (?(singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)?) -> (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)
130 131 132 |
# File 'lib/riffer/agent.rb', line 130 def self.tool_runtime(value = nil) value.nil? ? config.tool_runtime : (config.tool_runtime = value) end |
.use_mcp(tag, progressive: true) ⇒ Object
Opts this agent into MCP tools from registrations matching the given tag. Progressive registrations expose mcp_search instead of every schema up front.
: (String | Symbol, ?progressive: bool) -> void
115 116 117 |
# File 'lib/riffer/agent.rb', line 115 def self.use_mcp(tag, progressive: true) config.add_mcp(tag, progressive: progressive) end |
Instance Method Details
#generate(prompt = nil, files: nil) ⇒ Object
Generates a response from the agent.
With prompt, a new user message is appended (silently — on_message does not fire for user inputs) before the loop runs. Without it, the loop runs against the current session, resuming a persisted conversation or pending tool calls. files: requires prompt.
– : (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?) -> Riffer::Agent::Response
293 294 295 |
# File 'lib/riffer/agent.rb', line 293 def generate(prompt = nil, files: nil) Riffer::Agent::Run.generate(agent: self, prompt: prompt, files: files) end |
#interrupt!(reason = nil) ⇒ Object
Interrupts the agent loop from an on_message callback. Equivalent to throw :riffer_interrupt, reason. – : (?(String | Symbol)?) -> void
313 314 315 |
# File 'lib/riffer/agent.rb', line 313 def interrupt!(reason = nil) throw :riffer_interrupt, reason end |
#stream(prompt = nil, files: nil) ⇒ Object
Streams a response from the agent, returning an Enumerator of Riffer::StreamEvents. See #generate for prompt/files semantics.
Raises Riffer::ArgumentError if structured output is configured.
– : (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?) -> Enumerator[Riffer::StreamEvents::Base, void]
304 305 306 307 |
# File 'lib/riffer/agent.rb', line 304 def stream(prompt = nil, files: nil) raise Riffer::ArgumentError, "Structured output is not supported with streaming. Use #generate instead." if @structured_output Riffer::Agent::Run.stream(agent: self, prompt: prompt, files: files) end |
#to_h ⇒ Object
Snapshots this resolved agent into a self-contained, provider-neutral wire hash. – : () -> Hash[Symbol, untyped]
321 322 323 |
# File 'lib/riffer/agent.rb', line 321 def to_h Riffer::Agent::Serializer.to_h(agent: self) end |
#to_json ⇒ Object
Snapshots this resolved agent into a wire JSON string. The * absorbs the JSON generator state argument so JSON.generate(agent) works too. – : (*untyped) -> String
329 330 331 |
# File 'lib/riffer/agent.rb', line 329 def to_json(*) Riffer::Agent::Serializer.to_json(agent: self) end |