feat: add more tools (#12116)
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
This commit is contained in:
39
enterprise/lib/captain/tools/faq_lookup_tool.rb
Normal file
39
enterprise/lib/captain/tools/faq_lookup_tool.rb
Normal file
@@ -0,0 +1,39 @@
|
||||
class Captain::Tools::FaqLookupTool < Captain::Tools::BasePublicTool
|
||||
description 'Search FAQ responses using semantic similarity to find relevant answers'
|
||||
param :query, type: 'string', desc: 'The question or topic to search for in the FAQ database'
|
||||
|
||||
def perform(_tool_context, query:)
|
||||
log_tool_usage('searching', { query: query })
|
||||
|
||||
# Use existing vector search on approved responses
|
||||
responses = @assistant.responses.approved.search(query).to_a
|
||||
|
||||
if responses.empty?
|
||||
log_tool_usage('no_results', { query: query })
|
||||
"No relevant FAQs found for: #{query}"
|
||||
else
|
||||
log_tool_usage('found_results', { query: query, count: responses.size })
|
||||
format_responses(responses)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def format_responses(responses)
|
||||
responses.map { |response| format_response(response) }.join
|
||||
end
|
||||
|
||||
def format_response(response)
|
||||
formatted_response = "
|
||||
Question: #{response.question}
|
||||
Answer: #{response.answer}
|
||||
"
|
||||
if response.documentable.present? && response.documentable.try(:external_link)
|
||||
formatted_response += "
|
||||
Source: #{response.documentable.external_link}
|
||||
"
|
||||
end
|
||||
|
||||
formatted_response
|
||||
end
|
||||
end
|
||||
52
enterprise/lib/captain/tools/handoff_tool.rb
Normal file
52
enterprise/lib/captain/tools/handoff_tool.rb
Normal file
@@ -0,0 +1,52 @@
|
||||
class Captain::Tools::HandoffTool < Captain::Tools::BasePublicTool
|
||||
description 'Hand off the conversation to a human agent when unable to assist further'
|
||||
param :reason, type: 'string', desc: 'The reason why handoff is needed (optional)', required: false
|
||||
|
||||
def perform(tool_context, reason: nil)
|
||||
conversation = find_conversation(tool_context.state)
|
||||
return 'Conversation not found' unless conversation
|
||||
|
||||
# Log the handoff with reason
|
||||
log_tool_usage('tool_handoff', {
|
||||
conversation_id: conversation.id,
|
||||
reason: reason || 'Agent requested handoff'
|
||||
})
|
||||
|
||||
# Use existing handoff mechanism from ResponseBuilderJob
|
||||
trigger_handoff(conversation, reason)
|
||||
|
||||
"Conversation handed off to human support team#{" (Reason: #{reason})" if reason}"
|
||||
rescue StandardError => e
|
||||
ChatwootExceptionTracker.new(e).capture_exception
|
||||
'Failed to handoff conversation'
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def trigger_handoff(conversation, reason)
|
||||
# post the reason as a private note
|
||||
conversation.messages.create!(
|
||||
message_type: :outgoing,
|
||||
private: true,
|
||||
sender: @assistant,
|
||||
account: conversation.account,
|
||||
inbox: conversation.inbox,
|
||||
content: reason
|
||||
)
|
||||
|
||||
# Trigger the bot handoff (sets status to open + dispatches events)
|
||||
conversation.bot_handoff!
|
||||
end
|
||||
|
||||
# TODO: Future enhancement - Add team assignment capability
|
||||
# This tool could be enhanced to:
|
||||
# 1. Accept team_id parameter for routing to specific teams
|
||||
# 2. Set conversation priority based on handoff reason
|
||||
# 3. Add metadata for intelligent agent assignment
|
||||
# 4. Support escalation levels (L1 -> L2 -> L3)
|
||||
#
|
||||
# Example future signature:
|
||||
# param :team_id, type: 'string', desc: 'ID of team to assign conversation to', required: false
|
||||
# param :priority, type: 'string', desc: 'Priority level (low/medium/high/urgent)', required: false
|
||||
# param :escalation_level, type: 'string', desc: 'Support level (L1/L2/L3)', required: false
|
||||
end
|
||||
@@ -23,7 +23,9 @@ class Captain::Tools::UpdatePriorityTool < Captain::Tools::BasePublicTool
|
||||
end
|
||||
|
||||
def normalize_priority(priority)
|
||||
priority == 'nil' || priority.blank? ? nil : priority
|
||||
return nil if priority == 'nil' || priority.blank?
|
||||
|
||||
priority.downcase
|
||||
end
|
||||
|
||||
def valid_priority?(priority)
|
||||
|
||||
Reference in New Issue
Block a user