diff --git a/config/agents/tools.yml b/config/agents/tools.yml index c2faf75e7..14092728a 100644 --- a/config/agents/tools.yml +++ b/config/agents/tools.yml @@ -34,3 +34,8 @@ title: 'Handoff to Human' description: 'Hand off the conversation to a human agent' icon: 'user-switch' + +- id: resolve + title: 'Resolve Conversation' + description: 'Mark the conversation as resolved' + icon: 'checkmark-circle' diff --git a/enterprise/lib/captain/tools/resolve_tool.rb b/enterprise/lib/captain/tools/resolve_tool.rb new file mode 100644 index 000000000..00ca96e5c --- /dev/null +++ b/enterprise/lib/captain/tools/resolve_tool.rb @@ -0,0 +1,46 @@ +class Captain::Tools::ResolveTool < Captain::Tools::BasePublicTool + description 'Mark the conversation as resolved when the issue has been addressed' + param :reason, type: 'string', desc: 'The reason why the conversation is being resolved (optional)', required: false + + def perform(tool_context, reason: nil) + conversation = find_conversation(tool_context.state) + return 'Conversation not found' unless conversation + + return 'Conversation is already resolved' if conversation.resolved? + + log_tool_usage('tool_resolve', { + conversation_id: conversation.id, + reason: reason || 'Agent resolved conversation' + }) + + resolve_conversation(conversation, reason) + + "Conversation marked as resolved#{" (Reason: #{reason})" if reason.present?}" + rescue StandardError => e + ChatwootExceptionTracker.new(e).capture_exception + 'Failed to resolve conversation' + end + + private + + def resolve_conversation(conversation, reason) + # Add a private note with the reason if provided + if reason.present? + conversation.messages.create!( + message_type: :outgoing, + private: true, + sender: @assistant, + account: conversation.account, + inbox: conversation.inbox, + content: "Resolved: #{reason}" + ) + end + + # Mark conversation as resolved + conversation.resolved! + end + + def permissions + %w[conversation_manage conversation_unassigned_manage conversation_participating_manage] + end +end