64 lines
2.5 KiB
Ruby
64 lines
2.5 KiB
Ruby
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!
|
|
|
|
# Send out of office message if applicable (since template messages were suppressed while Captain was handling)
|
|
send_out_of_office_message_if_applicable(conversation)
|
|
end
|
|
|
|
def send_out_of_office_message_if_applicable(conversation)
|
|
# Campaign conversations should never receive OOO templates — the campaign itself
|
|
# serves as the initial outreach, and OOO would be confusing in that context.
|
|
return if conversation.campaign.present?
|
|
|
|
::MessageTemplates::Template::OutOfOffice.perform_if_applicable(conversation)
|
|
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
|