Class: Riffer::Agent

Inherits:
Object
  • Object
show all
Defined in:
lib/riffer/agent.rb,
sig/generated/riffer/agent.rbs

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 =

Returns:

  • (Symbol)
:max_steps

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

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

Parameters:



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 = build_instruction_message
  @skills_message = build_skills_message

  @session = session || Riffer::Agent::Session.new(messages: [@instruction_message, @skills_message].compact)
  @session.set(Riffer::Agent::Session::Repair.prune_orphans(@session.messages))
end

Instance Attribute Details

#configRiffer::Agent::Config (readonly)

The per-instance Riffer::Agent::Config.



217
218
219
# File 'lib/riffer/agent.rb', line 217

def config
  @config
end

#contextRiffer::Agent::Context (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_messageRiffer::Messages::System? (readonly)

The system message built from the configured instructions, or nil when none are configured.

Returns:



221
222
223
# File 'lib/riffer/agent.rb', line 221

def instruction_message
  @instruction_message
end

#model_nameString (readonly)

The resolved model name (the part after "/" in the model string), used as the model argument on every LLM call.

Returns:

  • (String)


237
238
239
# File 'lib/riffer/agent.rb', line 237

def model_name
  @model_name
end

#providerRiffer::Providers::Base (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_nameString (readonly)

The resolved provider name (the part before "/" in the model string), e.g. "openai".

Returns:

  • (String)


233
234
235
# File 'lib/riffer/agent.rb', line 233

def provider_name
  @provider_name
end

#sessionRiffer::Agent::Session (readonly)

The conversation handle.



214
215
216
# File 'lib/riffer/agent.rb', line 214

def session
  @session
end

#skills_messageRiffer::Messages::System? (readonly)

The system message describing the configured skills catalog, or nil when skills are unconfigured or the catalog is empty.

Returns:



225
226
227
# File 'lib/riffer/agent.rb', line 225

def skills_message
  @skills_message
end

#structured_outputRiffer::Agent::StructuredOutput? (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_runtimeRiffer::Tools::Runtime (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

#toolsArray[singleton(Riffer::Tool)] (readonly)

The tool classes the LLM sees on every call this agent makes.

Returns:



248
249
250
# File 'lib/riffer/agent.rb', line 248

def tools
  @tools
end

Class Method Details

.allArray[singleton(Riffer::Agent)]

Returns all agent subclasses.

-- : () -> Array

Returns:



166
167
168
# File 'lib/riffer/agent.rb', line 166

def self.all
  subclasses #: Array[singleton(Riffer::Agent)]
end

.configRiffer::Agent::Config

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) ⇒ singleton(Riffer::Agent)?

Finds an agent class by identifier.

-- : (String) -> singleton(Riffer::Agent)?

Parameters:

  • (String)

Returns:



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) ⇒ Riffer::Agent

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

Parameters:

Returns:



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) ⇒ Riffer::Agent

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

Parameters:

Returns:



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, tags: {}) ⇒ Riffer::Agent::Response

Generates a response using a new agent instance.

: (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?, ?context: Hash[Symbol, untyped]?, ?tags: Hash[(String | Symbol), untyped]) -> Riffer::Agent::Response

Parameters:

  • (String, nil)
  • files: (Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart], nil) (defaults to: nil)
  • context: (Hash[Symbol, untyped], nil) (defaults to: nil)
  • tags: (Hash[String | Symbol, untyped]) (defaults to: {})

Returns:



173
174
175
# File 'lib/riffer/agent.rb', line 173

def self.generate(prompt = nil, files: nil, context: nil, tags: {})
  new(context: context).generate(prompt, files: files, tags: tags)
end

.guardrail(phase, with:, **options) ⇒ void

This method returns an undefined value.

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

Parameters:



202
203
204
# File 'lib/riffer/agent.rb', line 202

def self.guardrail(phase, with:, **options)
  config.add_guardrail(phase, klass: with, options: options)
end

.guardrails_for(phase) ⇒ Array[Hash[Symbol, untyped]]

Returns the registered guardrail configs for a given phase.

: (Symbol) -> Array[Hash[Symbol, untyped]]

Parameters:

  • (Symbol)

Returns:

  • (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) ⇒ String

Gets or sets the agent identifier.

-- : (?String?) -> String

Parameters:

  • (String, nil)

Returns:

  • (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) ⇒ String, ...

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)?

Parameters:

  • (?(String | Proc), nil)

Returns:

  • (String, Proc, nil)


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) ⇒ Numeric?

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?

Parameters:

  • (Numeric, nil)

Returns:

  • (Numeric, nil)


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_configsArray[Hash[Symbol, untyped]]

Returns the accumulated use_mcp configurations for this agent class.

: () -> Array[Hash[Symbol, untyped]]

Returns:

  • (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) ⇒ String, ...

Gets or sets the model string (e.g., "openai/gpt-4o").

-- : (?(String | Proc)?) -> (String | Proc)?

Parameters:

  • (?(String | Proc), nil)

Returns:

  • (String, Proc, nil)


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) ⇒ Hash[Symbol, untyped]

Gets or sets model options passed to generate_text/stream_text.

-- : (?Hash[Symbol, untyped]?) -> Hash[Symbol, untyped]

Parameters:

  • (Hash[Symbol, untyped], nil)

Returns:

  • (Hash[Symbol, untyped])


72
73
74
# File 'lib/riffer/agent.rb', line 72

def self.model_options(options = nil)
  options.nil? ? config.model_options : (config.model_options = options)
end

.provider_options(options = nil) ⇒ Hash[Symbol, untyped]

Gets or sets provider options passed to the provider client.

-- : (?Hash[Symbol, untyped]?) -> Hash[Symbol, untyped]

Parameters:

  • (Hash[Symbol, untyped], nil)

Returns:

  • (Hash[Symbol, untyped])


64
65
66
# File 'lib/riffer/agent.rb', line 64

def self.provider_options(options = nil)
  options.nil? ? config.provider_options : (config.provider_options = options)
end

.skills(&block) ⇒ void

This method returns an undefined value.

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, tags: {}) ⇒ Enumerator[Riffer::StreamEvents::Base, void]

Streams a response using a new agent instance.

: (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?, ?context: Hash[Symbol, untyped]?, ?tags: Hash[(String | Symbol), untyped]) -> Enumerator[Riffer::StreamEvents::Base, void]

Parameters:

  • (String, nil)
  • files: (Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart], nil) (defaults to: nil)
  • context: (Hash[Symbol, untyped], nil) (defaults to: nil)
  • tags: (Hash[String | Symbol, untyped]) (defaults to: {})

Returns:



180
181
182
# File 'lib/riffer/agent.rb', line 180

def self.stream(prompt = nil, files: nil, context: nil, tags: {})
  new(context: context).stream(prompt, files: files, tags: tags)
end

.structured_output(params = nil, &block) ⇒ void

This method returns an undefined value.

Gets or sets the structured output schema for this agent.

: (?Riffer::Params?) ?{ (Riffer::Params) [self: Riffer::Params] -> void } -> Riffer::Params?

Parameters:



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) ⇒ singleton(Riffer::Tools::Runtime), ...

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)

Parameters:

Returns:



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) ⇒ void

This method returns an undefined value.

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

Parameters:

  • (String, Symbol)
  • progressive: (Boolean) (defaults to: true)


115
116
117
# File 'lib/riffer/agent.rb', line 115

def self.use_mcp(tag, progressive: true)
  config.add_mcp(tag, progressive: progressive)
end

.uses_tools(value = nil) ⇒ Array[singleton(Riffer::Tool)], ...

Gets or sets the tools used by this agent.

-- : (?(Array | Proc)?) -> (Array | Proc)?

Parameters:

Returns:



107
108
109
# File 'lib/riffer/agent.rb', line 107

def self.uses_tools(value = nil)
  value.nil? ? config.tools_config : (config.tools_config = value)
end

Instance Method Details

#assert_distinct_tool_names!(tool_classes) ⇒ void

This method returns an undefined value.

-- : (Array) -> void

Parameters:



494
495
496
497
498
499
500
501
# File 'lib/riffer/agent.rb', line 494

def assert_distinct_tool_names!(tool_classes)
  tally = Hash.new(0) #: Hash[String, Integer]
  tool_classes.each { |tc| tally[tc.name] += 1 }
  dupes = tally.filter_map { |name, n| name if n > 1 }
  return if dupes.empty?

  raise Riffer::ArgumentError, "Duplicate tool names: #{dupes.sort.join(", ")}"
end

#build_instruction_messageRiffer::Messages::System?

-- : () -> Riffer::Messages::System?

Returns:



344
345
346
347
348
# File 'lib/riffer/agent.rb', line 344

def build_instruction_message
  content = Riffer::Helpers::CallOrValue.resolve(@config.instructions, context: @context)
  return nil if content.nil? || content.empty?
  Riffer::Messages::System.new(content)
end

#build_providerRiffer::Providers::Base

-- : () -> Riffer::Providers::Base



375
376
377
378
379
# File 'lib/riffer/agent.rb', line 375

def build_provider
  provider_class = Riffer::Providers::Repository.find(@provider_name)
  raise Riffer::ArgumentError, "Provider not found: #{@provider_name}" unless provider_class
  provider_class.new(**@config.provider_options)
end

#build_skills_messageRiffer::Messages::System?

-- : () -> Riffer::Messages::System?

Returns:



352
353
354
355
356
# File 'lib/riffer/agent.rb', line 352

def build_skills_message
  content = @context.skills&.system_prompt
  return nil if content.nil? || content.empty?
  Riffer::Messages::System.new(content)
end

#gather_mcp_registrations_with_tags(configs) ⇒ [ Hash[Riffer::Mcp::Registration, Array[Symbol]], Hash[Riffer::Mcp::Registration, Array[Symbol]] ]

-- : (Array[Hash[Symbol, untyped]]) -> [Hash[Riffer::Mcp::Registration, Array[Symbol]], Hash[Riffer::Mcp::Registration, Array[Symbol]]]

Parameters:

  • (Array[Hash[Symbol, untyped]])

Returns:



472
473
474
475
476
477
478
479
480
481
482
# File 'lib/riffer/agent.rb', line 472

def gather_mcp_registrations_with_tags(configs)
  regular = {} #: Hash[Riffer::Mcp::Registration, Array[Symbol]]
  progressive = {} #: Hash[Riffer::Mcp::Registration, Array[Symbol]]
  configs.each do |cfg|
    target = cfg[:progressive] ? progressive : regular
    Riffer::Mcp::Registry.find_by_tags(cfg[:tags]).each do |reg|
      (target[reg] ||= []).concat(cfg[:tags] & reg.manifest.tags)
    end
  end
  [regular, progressive]
end

#generate(prompt = nil, files: nil, tags: {}) ⇒ Riffer::Agent::Response

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.

tags: is an optional flat hash of attribution tags applied to this single call: they propagate to the provider's native request-metadata field, and are stamped as riffer.tag.* on every span the call emits. See docs/03_AGENTS.md for the per-provider mapping. The reserved key user_id also maps to the provider's native user identifier where one exists.

-- : (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?, ?tags: Hash[(String | Symbol), untyped]) -> Riffer::Agent::Response

Parameters:

  • (String, nil)
  • files: (Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart], nil) (defaults to: nil)
  • tags: (Hash[String | Symbol, untyped]) (defaults to: {})

Returns:



300
301
302
# File 'lib/riffer/agent.rb', line 300

def generate(prompt = nil, files: nil, tags: {})
  Riffer::Agent::Run.generate(agent: self, prompt: prompt, files: files, tags: tags)
end

#interrupt!(reason = nil) ⇒ void

This method returns an undefined value.

Interrupts the agent loop from an on_message callback. Equivalent to throw :riffer_interrupt, reason.

: (?(String | Symbol)?) -> void

Parameters:

  • (?(String | Symbol), nil)


320
321
322
# File 'lib/riffer/agent.rb', line 320

def interrupt!(reason = nil)
  throw :riffer_interrupt, reason
end

#mcp_tools_for_registration(reg, matched_tags, cred, ctx) ⇒ Array[singleton(Riffer::Tool)]

-- : (Riffer::Mcp::Registration, Array, (^(manifest: Riffer::Mcp::Manifest, matched_tags: Array, context: Riffer::Agent::Context) -> Hash[Symbol, untyped]?)?, Riffer::Agent::Context) -> Array

Parameters:

Returns:



486
487
488
489
490
# File 'lib/riffer/agent.rb', line 486

def mcp_tools_for_registration(reg, matched_tags, cred, ctx)
  return reg.tools unless cred
  return [] if cred.call(manifest: reg.manifest, matched_tags: matched_tags, context: ctx).nil?
  Riffer::Mcp::AuthenticatedTool.wrap_all(reg.tools, reg.manifest, matched_tags)
end

#resolve_mcp_tool_classesArray[singleton(Riffer::Tool)]

-- : () -> Array

Returns:



450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
# File 'lib/riffer/agent.rb', line 450

def resolve_mcp_tool_classes
  configs = @config.mcp_configs
  return [] if configs.empty?

  cred = Riffer.config.mcp.credentials
  ctx = @context

  regular_reg_tags, progressive_reg_tags = gather_mcp_registrations_with_tags(configs)

  regular_tools = regular_reg_tags.flat_map { |reg, tag_accum| mcp_tools_for_registration(reg, tag_accum.uniq, cred, ctx) }
  progressive_tools = progressive_reg_tags.flat_map { |reg, tag_accum| mcp_tools_for_registration(reg, tag_accum.uniq, cred, ctx) }

  if progressive_tools.any?
    @context.mcp_progressive_tools = progressive_tools.freeze
    regular_tools + [Riffer::Mcp::SearchTool]
  else
    regular_tools
  end
end

#resolve_provider_and_model[ String, String ]

-- : () -> [String, String]

Returns:

  • ([ String, String ])


360
361
362
363
364
365
366
367
368
369
370
371
# File 'lib/riffer/agent.rb', line 360

def resolve_provider_and_model
  model_string = Riffer::Helpers::CallOrValue.resolve(@config.model, context: @context)
  raise Riffer::ArgumentError, "Invalid model string: #{model_string}" unless model_string.is_a?(String)

  provider_name, model_name = model_string.split("/", 2)

  unless provider_name.is_a?(String) && !provider_name.strip.empty? && model_name.is_a?(String) && !model_name.strip.empty?
    raise Riffer::ArgumentError, "Invalid model string: #{model_string}"
  end

  [provider_name, model_name]
end

#resolve_skillsRiffer::Skills::Context?

-- : () -> Riffer::Skills::Context?

Returns:



383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
# File 'lib/riffer/agent.rb', line 383

def resolve_skills
  skills_config = @config.skills_config
  return nil unless skills_config

  backend = skills_config.backend || Riffer.config.skills.default_backend
  return nil unless backend

  backend = Riffer::Helpers::CallOrValue.resolve(backend, context: @context)
  return nil if backend.list_skills.empty?

  skills = backend.list_skills.to_h { |s| [s.name, s] }
  adapter_class = skills_config.adapter || @provider.class.skills_adapter(@model_name)
  skill_activate_tool_class = skills_config.activate_tool || Riffer.config.skills.default_activate_tool

  skills_context = Riffer::Skills::Context.new(
    backend: backend,
    skills: skills,
    adapter: adapter_class.new(skill_activate_tool: skill_activate_tool_class)
  )

  if skills_config.activate
    names = Array(Riffer::Helpers::CallOrValue.resolve(skills_config.activate, context: @context))
    names.each { |name| skills_context.preactivate(name) }
  end

  skills_context
end

#resolve_structured_outputRiffer::Agent::StructuredOutput?

-- : () -> Riffer::Agent::StructuredOutput?



413
414
415
416
# File 'lib/riffer/agent.rb', line 413

def resolve_structured_output
  params = @config.structured_output
  params ? Riffer::Agent::StructuredOutput.new(params) : nil
end

#resolve_tool_runtimeRiffer::Tools::Runtime

-- : () -> Riffer::Tools::Runtime



443
444
445
446
# File 'lib/riffer/agent.rb', line 443

def resolve_tool_runtime
  runtime = Riffer::Helpers::CallOrValue.resolve(@config.tool_runtime, context: @context)
  runtime.is_a?(Class) ? runtime.new : runtime
end

#resolve_toolsArray[singleton(Riffer::Tool)]

-- : () -> Array

Returns:



420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
# File 'lib/riffer/agent.rb', line 420

def resolve_tools
  tools = Riffer::Helpers::CallOrValue.resolve(@config.tools_config, context: @context, default: [])

  skills_config = @config.skills_config

  if skills_config && @context.skills&.activatable?
    skill_activate_tool_class = skills_config.activate_tool || Riffer.config.skills.default_activate_tool

    if tools.any? { |t| t.name == skill_activate_tool_class.name }
      raise Riffer::ArgumentError, "Tool name conflict with skill tools: #{skill_activate_tool_class.name}"
    end

    tools += [skill_activate_tool_class]
  end

  tools += resolve_mcp_tool_classes
  assert_distinct_tool_names!(tools)
  tools.each(&:validate_as_tool!)
  tools
end

#stream(prompt = nil, files: nil, tags: {}) ⇒ Enumerator[Riffer::StreamEvents::Base, void]

Streams a response from the agent, returning an Enumerator of Riffer::StreamEvents. See #generate for prompt/files/tags semantics.

Raises Riffer::ArgumentError if structured output is configured.

-- : (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?, ?tags: Hash[(String | Symbol), untyped]) -> Enumerator[Riffer::StreamEvents::Base, void]

Parameters:

  • (String, nil)
  • files: (Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart], nil) (defaults to: nil)
  • tags: (Hash[String | Symbol, untyped]) (defaults to: {})

Returns:



311
312
313
314
# File 'lib/riffer/agent.rb', line 311

def stream(prompt = nil, files: nil, tags: {})
  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, tags: tags)
end

#to_hHash[Symbol, untyped]

Snapshots this resolved agent into a self-contained, provider-neutral wire hash.

: () -> Hash[Symbol, untyped]

Returns:

  • (Hash[Symbol, untyped])


328
329
330
# File 'lib/riffer/agent.rb', line 328

def to_h
  Riffer::Agent::Serializer.to_h(agent: self)
end

#to_jsonString

Snapshots this resolved agent into a wire JSON string. The * absorbs the JSON generator state argument so JSON.generate(agent) works too.

: (*untyped) -> String

Parameters:

  • (Object)

Returns:

  • (String)


336
337
338
# File 'lib/riffer/agent.rb', line 336

def to_json(*)
  Riffer::Agent::Serializer.to_json(agent: self)
end