diff --git a/enterprise/app/models/captain/assistant.rb b/enterprise/app/models/captain/assistant.rb index e37d2e9db..89078d3eb 100644 --- a/enterprise/app/models/captain/assistant.rb +++ b/enterprise/app/models/captain/assistant.rb @@ -19,6 +19,7 @@ class Captain::Assistant < ApplicationRecord include Avatarable include CaptainToolsHelpers + include Agentable self.table_name = 'captain_assistants' @@ -69,18 +70,10 @@ class Captain::Assistant < ApplicationRecord } end - def agent(_user) - Agents::Agent.new( - name: name, - instructions: agent_instructions, - model: 'gpt-4.1-mini' - ) - end - private - def agent_instructions - Captain::PromptRenderer.render('assistant', prompt_context) + def agent_name + name end def prompt_context diff --git a/enterprise/app/models/captain/scenario.rb b/enterprise/app/models/captain/scenario.rb index 6a77452ea..ea2729a1c 100644 --- a/enterprise/app/models/captain/scenario.rb +++ b/enterprise/app/models/captain/scenario.rb @@ -22,6 +22,7 @@ # class Captain::Scenario < ApplicationRecord include CaptainToolsHelpers + include Agentable self.table_name = 'captain_scenarios' @@ -39,10 +40,6 @@ class Captain::Scenario < ApplicationRecord before_save :resolve_tool_references - def agent_instructions - Captain::PromptRenderer.render('scenario', prompt_context) - end - def prompt_context { title: title, @@ -51,22 +48,16 @@ class Captain::Scenario < ApplicationRecord } end - def agent_tools - resolved_tools.map { |tool| self.class.resolve_tool_class(tool[:id]) } - end - - def agent(user) - tool_instances = agent_tools.map { |tool| tool.new(assistant, user: user) } - Agents::Agent.new( - name: "#{title} Agent".titleize, - instructions: agent_instructions, - tools: tool_instances, - model: 'gpt-4.1-mini' - ) - end - private + def agent_name + "#{title} Agent".titleize + end + + def agent_tools(user) + resolved_tools.map { |tool| self.class.resolve_tool_class(tool[:id]) }.map { |tool| tool.new(assistant, user: user) } + end + def resolved_instructions instruction.gsub(%r{\(tool://(\w+)\)}) do |match| "#{match} tool " diff --git a/enterprise/app/models/concerns/agentable.rb b/enterprise/app/models/concerns/agentable.rb new file mode 100644 index 000000000..91f0a2c46 --- /dev/null +++ b/enterprise/app/models/concerns/agentable.rb @@ -0,0 +1,51 @@ +module Agentable + extend ActiveSupport::Concern + + included do + def agent(user) + Agents::Agent.new( + name: agent_name, + instructions: ->(context) { agent_instructions(context) }, + tools: agent_tools(user), + model: agent_model + ) + end + + def agent_instructions(context = nil) + enhanced_context = prompt_context + + if context + state = context.context[:state] || {} + conversation_data = state[:conversation] || {} + enhanced_context = enhanced_context.merge( + conversation: conversation_data, + has_conversation: conversation_data.present? + ) + end + + Captain::PromptRenderer.render(template_name, enhanced_context) + end + + private + + def agent_name + raise NotImplementedError, "#{self.class} must implement agent_name" + end + + def template_name + self.class.name.demodulize.underscore + end + + def agent_tools(_user) + [] # Default implementation, override if needed + end + + def agent_model + 'gpt-4.1-mini' + end + + def prompt_context + raise NotImplementedError, "#{self.class} must implement prompt_context" + end + end +end