Class: Omnibot::Agent
- Inherits:
-
Object
- Object
- Omnibot::Agent
- Defined in:
- lib/omnibot/agent.rb
Defined Under Namespace
Classes: TurnLimit
Constant Summary collapse
- FAST_REPLY =
:__omnibot_fast_reply
Instance Attribute Summary collapse
-
#context ⇒ Object
readonly
Returns the value of attribute context.
Class Method Summary collapse
-
.chat_factory(callable = nil, &block) ⇒ Object
Per-agent chat factory (e.g. to set temperature/params for THIS agent only).
- .extract(input, schema:, context: {}) ⇒ Object
- .fast_path(&block) ⇒ Object
- .fast_paths ⇒ Object
- .inherited(subclass) ⇒ Object
- .instructions(value = nil) ⇒ Object
-
.max_turns(value = nil) ⇒ Object
Bounds the number of tool executions in a run, not conversation rounds — the before_tool_call hook counts each call, so parallel tool calls in a single round each count separately.
- .model(value = nil) ⇒ Object
- .resolved_chat_factory ⇒ Object
- .run(message, history: [], context: {}, stream: nil) ⇒ Object
- .tool(name_or_class, description = nil, &block) ⇒ Object
- .tools ⇒ Object
Instance Method Summary collapse
- #extract(input, schema:) ⇒ Object
-
#initialize(context = {}) ⇒ Agent
constructor
A new instance of Agent.
-
#reply(text) ⇒ Object
Called from within a fast_path block to short-circuit the run loop.
- #run(message, history: [], stream: nil) ⇒ Object
-
#tools_for(_context) ⇒ Object
Override in subclasses to gate tools per run (context-aware).
Constructor Details
#initialize(context = {}) ⇒ Agent
Returns a new instance of Agent.
64 65 66 |
# File 'lib/omnibot/agent.rb', line 64 def initialize(context = {}) @context = context end |
Instance Attribute Details
#context ⇒ Object (readonly)
Returns the value of attribute context.
62 63 64 |
# File 'lib/omnibot/agent.rb', line 62 def context @context end |
Class Method Details
.chat_factory(callable = nil, &block) ⇒ Object
Per-agent chat factory (e.g. to set temperature/params for THIS agent only). Precedence: Omnibot::Testing.fake! override > class factory > Omnibot.chat_factory. Accepts a callable or a block.
34 35 36 37 |
# File 'lib/omnibot/agent.rb', line 34 def chat_factory(callable = nil, &block) factory = callable || block factory ? @chat_factory = factory : @chat_factory end |
.extract(input, schema:, context: {}) ⇒ Object
57 58 59 |
# File 'lib/omnibot/agent.rb', line 57 def extract(input, schema:, context: {}) new(context).extract(input, schema: schema) end |
.fast_path(&block) ⇒ Object
29 |
# File 'lib/omnibot/agent.rb', line 29 def fast_path(&block) = fast_paths << block |
.fast_paths ⇒ Object
28 |
# File 'lib/omnibot/agent.rb', line 28 def fast_paths = @fast_paths ||= [] |
.inherited(subclass) ⇒ Object
43 44 45 46 47 48 49 50 51 |
# File 'lib/omnibot/agent.rb', line 43 def inherited(subclass) super subclass.instance_variable_set(:@model, @model) subclass.instance_variable_set(:@instructions, @instructions) subclass.instance_variable_set(:@max_turns, @max_turns) subclass.instance_variable_set(:@tools, tools.dup) subclass.instance_variable_set(:@fast_paths, fast_paths.dup) subclass.instance_variable_set(:@chat_factory, @chat_factory) end |
.instructions(value = nil) ⇒ Object
12 13 14 |
# File 'lib/omnibot/agent.rb', line 12 def instructions(value = nil) value ? @instructions = value : @instructions end |
.max_turns(value = nil) ⇒ Object
Bounds the number of tool executions in a run, not conversation rounds — the before_tool_call hook counts each call, so parallel tool calls in a single round each count separately.
19 20 21 |
# File 'lib/omnibot/agent.rb', line 19 def max_turns(value = nil) value ? @max_turns = value : (@max_turns || 5) end |
.model(value = nil) ⇒ Object
8 9 10 |
# File 'lib/omnibot/agent.rb', line 8 def model(value = nil) value ? @model = value : (@model || Omnibot.config.default_model) end |
.resolved_chat_factory ⇒ Object
39 40 41 |
# File 'lib/omnibot/agent.rb', line 39 def resolved_chat_factory Omnibot.chat_factory_override || chat_factory || Omnibot.chat_factory end |
.run(message, history: [], context: {}, stream: nil) ⇒ Object
53 54 55 |
# File 'lib/omnibot/agent.rb', line 53 def run(, history: [], context: {}, stream: nil) new(context).run(, history: history, stream: stream) end |
.tool(name_or_class, description = nil, &block) ⇒ Object
23 24 25 |
# File 'lib/omnibot/agent.rb', line 23 def tool(name_or_class, description = nil, &block) tools << (block ? Tool.from_block(name_or_class, description, &block) : name_or_class) end |
.tools ⇒ Object
27 |
# File 'lib/omnibot/agent.rb', line 27 def tools = @tools ||= [] |
Instance Method Details
#extract(input, schema:) ⇒ Object
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/omnibot/agent.rb', line 84 def extract(input, schema:) chat = self.class.resolved_chat_factory.call(model: self.class.model, agent_class: self.class) chat.with_instructions(interpolated_instructions) if self.class.instructions chat.with_schema(schema) response = instrument_llm { chat.ask(input.to_s) } parse_extraction(response.content) do |error| repair = instrument_llm do chat.ask("Your previous output was not valid JSON (#{error.}). " \ "Respond again with ONLY valid JSON matching the schema.") end parse_extraction(repair.content) do |_error| raise ExtractionError, "extraction failed after repair: #{repair.content.to_s.truncate(200)}" end end end |
#reply(text) ⇒ Object
Called from within a fast_path block to short-circuit the run loop.
82 |
# File 'lib/omnibot/agent.rb', line 82 def reply(text) = throw(FAST_REPLY, text) |
#run(message, history: [], stream: nil) ⇒ Object
68 69 70 71 72 73 74 75 76 |
# File 'lib/omnibot/agent.rb', line 68 def run(, history: [], stream: nil) ActiveSupport::Notifications.instrument("omnibot.agent.run", agent: self.class) do |payload| payload[:fast_path] = false result = run_loop(, history, stream) payload[:fast_path] = result.fast_path? payload[:usage] = result.usage result end end |
#tools_for(_context) ⇒ Object
Override in subclasses to gate tools per run (context-aware).
79 |
# File 'lib/omnibot/agent.rb', line 79 def tools_for(_context) = self.class.tools |