Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fc86f93879 | ||
|
|
baf860016f | ||
|
|
ecc4f1403d | ||
|
|
6ea17e700f | ||
|
|
da58cbd24a | ||
|
|
a31f95cf45 | ||
|
|
d932156dec | ||
|
|
2cbc14e366 | ||
|
|
548360583e |
@@ -78,7 +78,7 @@ class Captain::Conversation::ResponseBuilderJob < ApplicationJob
|
|||||||
end
|
end
|
||||||
|
|
||||||
def handoff_requested?
|
def handoff_requested?
|
||||||
@response['response'] == 'conversation_handoff'
|
@response['action'] == 'handoff'
|
||||||
end
|
end
|
||||||
|
|
||||||
def process_action(action)
|
def process_action(action)
|
||||||
@@ -97,9 +97,10 @@ class Captain::Conversation::ResponseBuilderJob < ApplicationJob
|
|||||||
end
|
end
|
||||||
|
|
||||||
def create_handoff_message
|
def create_handoff_message
|
||||||
create_outgoing_message(
|
handoff_message = @response&.dig('response').presence ||
|
||||||
@assistant.config['handoff_message'].presence || I18n.t('conversations.captain.handoff')
|
@assistant.config['handoff_message'].presence ||
|
||||||
)
|
I18n.t('conversations.captain.handoff')
|
||||||
|
create_outgoing_message(handoff_message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_messages
|
def create_messages
|
||||||
|
|||||||
@@ -94,8 +94,9 @@ class Captain::Assistant::AgentRunnerService
|
|||||||
|
|
||||||
def error_response(error_message)
|
def error_response(error_message)
|
||||||
{
|
{
|
||||||
'response' => 'conversation_handoff',
|
'response' => 'Transferring to another agent for further assistance.',
|
||||||
'reasoning' => "Error occurred: #{error_message}"
|
'reasoning' => "Error occurred: #{error_message}",
|
||||||
|
'action' => 'handoff'
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -194,14 +194,25 @@ class Captain::Llm::SystemPromptsService
|
|||||||
- Do not share anything outside of the context provided.
|
- Do not share anything outside of the context provided.
|
||||||
- Add the reasoning why you arrived at the answer
|
- Add the reasoning why you arrived at the answer
|
||||||
- Your answers will always be formatted in a valid JSON hash, as shown below. Never respond in non-JSON format.
|
- Your answers will always be formatted in a valid JSON hash, as shown below. Never respond in non-JSON format.
|
||||||
#{config['instructions'] || ''}
|
#{config['instructions'].present? ? "\n [Custom Instructions]\n #{config['instructions']}\n" : ''}
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
reasoning: '',
|
"reasoning": "",
|
||||||
response: '',
|
"response": "",
|
||||||
|
"action": "continue" | "offer_handoff" | "handoff"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
- If the answer is not provided in context sections, Respond to the customer and ask whether they want to talk to another support agent . If they ask to Chat with another agent, return `conversation_handoff' as the response in JSON response
|
The action field MUST be one of:
|
||||||
|
- "continue": Default. Use for normal conversation flow.
|
||||||
|
- "offer_handoff": Use when a handoff scenario is triggered (by custom instructions, inability to help, user frustration, or complex situations). Your response MUST ask the user if they would like to be connected to a support agent. Do NOT transfer yet - wait for their confirmation.
|
||||||
|
- "handoff": Use ONLY when:
|
||||||
|
• User has confirmed after you offered a handoff, OR
|
||||||
|
• User explicitly requests human support unprompted (in any language)
|
||||||
|
Never use handoff for scenarios where the bot decides a handoff is needed - use offer_handoff instead.
|
||||||
|
|
||||||
|
When action is "handoff", your response field MUST contain a message letting the user know they'll be connected to support.
|
||||||
|
This message MUST be in the same language as the user's message.
|
||||||
#{'- You MUST provide numbered citations at the appropriate places in the text.' if config['feature_citation']}
|
#{'- You MUST provide numbered citations at the appropriate places in the text.' if config['feature_citation']}
|
||||||
SYSTEM_PROMPT_MESSAGE
|
SYSTEM_PROMPT_MESSAGE
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -57,11 +57,13 @@ module Enterprise::MessageTemplates::HookExecutionService
|
|||||||
return unless conversation.pending?
|
return unless conversation.pending?
|
||||||
|
|
||||||
Rails.logger.info("Captain limit exceeded, performing handoff mid-conversation for conversation: #{conversation.id}")
|
Rails.logger.info("Captain limit exceeded, performing handoff mid-conversation for conversation: #{conversation.id}")
|
||||||
|
handoff_message = inbox.captain_assistant&.config&.dig('handoff_message').presence ||
|
||||||
|
'Transferring to another agent for further assistance.'
|
||||||
conversation.messages.create!(
|
conversation.messages.create!(
|
||||||
message_type: :outgoing,
|
message_type: :outgoing,
|
||||||
account_id: conversation.account.id,
|
account_id: conversation.account.id,
|
||||||
inbox_id: conversation.inbox.id,
|
inbox_id: conversation.inbox.id,
|
||||||
content: 'Transferring to another agent for further assistance.'
|
content: handoff_message
|
||||||
)
|
)
|
||||||
conversation.bot_handoff!
|
conversation.bot_handoff!
|
||||||
send_out_of_office_message_after_handoff
|
send_out_of_office_message_after_handoff
|
||||||
|
|||||||
@@ -251,7 +251,7 @@ RSpec.describe Captain::Conversation::ResponseBuilderJob, type: :job do
|
|||||||
closed_all_day: true,
|
closed_all_day: true,
|
||||||
open_all_day: false
|
open_all_day: false
|
||||||
)
|
)
|
||||||
allow(mock_llm_chat_service).to receive(:generate_response).and_return({ 'response' => 'conversation_handoff' })
|
allow(mock_llm_chat_service).to receive(:generate_response).and_return({ 'action' => 'handoff' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'sends out of office message after handoff' do
|
it 'sends out of office message after handoff' do
|
||||||
@@ -275,7 +275,7 @@ RSpec.describe Captain::Conversation::ResponseBuilderJob, type: :job do
|
|||||||
open_all_day: true,
|
open_all_day: true,
|
||||||
closed_all_day: false
|
closed_all_day: false
|
||||||
)
|
)
|
||||||
allow(mock_llm_chat_service).to receive(:generate_response).and_return({ 'response' => 'conversation_handoff' })
|
allow(mock_llm_chat_service).to receive(:generate_response).and_return({ 'action' => 'handoff' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does not send out of office message after handoff' do
|
it 'does not send out of office message after handoff' do
|
||||||
@@ -321,7 +321,7 @@ RSpec.describe Captain::Conversation::ResponseBuilderJob, type: :job do
|
|||||||
closed_all_day: true,
|
closed_all_day: true,
|
||||||
open_all_day: false
|
open_all_day: false
|
||||||
)
|
)
|
||||||
allow(mock_llm_chat_service).to receive(:generate_response).and_return({ 'response' => 'conversation_handoff' })
|
allow(mock_llm_chat_service).to receive(:generate_response).and_return({ 'action' => 'handoff' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does not send out of office message' do
|
it 'does not send out of office message' do
|
||||||
|
|||||||
@@ -148,8 +148,9 @@ RSpec.describe Captain::Assistant::AgentRunnerService do
|
|||||||
result = service.generate_response(message_history: message_history)
|
result = service.generate_response(message_history: message_history)
|
||||||
|
|
||||||
expect(result).to eq({
|
expect(result).to eq({
|
||||||
'response' => 'conversation_handoff',
|
'response' => 'Transferring to another agent for further assistance.',
|
||||||
'reasoning' => 'Error occurred: Test error'
|
'reasoning' => 'Error occurred: Test error',
|
||||||
|
'action' => 'handoff'
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -169,7 +170,8 @@ RSpec.describe Captain::Assistant::AgentRunnerService do
|
|||||||
result = service.generate_response(message_history: message_history)
|
result = service.generate_response(message_history: message_history)
|
||||||
|
|
||||||
expect(result).to eq({
|
expect(result).to eq({
|
||||||
'response' => 'conversation_handoff',
|
'response' => 'Transferring to another agent for further assistance.',
|
||||||
|
'action' => 'handoff',
|
||||||
'reasoning' => 'Error occurred: Test error'
|
'reasoning' => 'Error occurred: Test error'
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user