From 279dd1876c780c4dc2a4bcb735d5cd8ce3ec5762 Mon Sep 17 00:00:00 2001 From: Aakash Bakhle <48802744+aakashb95@users.noreply.github.com> Date: Mon, 27 Apr 2026 15:51:49 +0530 Subject: [PATCH] fix: make captain datetime aware (#14069) # Pull Request Template ## Description Captain currently cannot discern today, tomorrow etc. This PR adds datetime awareness to the system prompt Fixes: https://linear.app/chatwoot/issue/AI-148/captain-should-be-aware-of-datetime ## Type of change - [x] Bug fix (non-breaking change which fixes an issue) ## How Has This Been Tested? Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration. Locally CleanShot 2026-04-27 at 14 47 47 ## Checklist: - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my code - [x] I have commented on my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [x] Any dependent changes have been merged and published in downstream modules --- .../services/captain/llm/assistant_chat_service.rb | 6 +++++- .../services/captain/llm/system_prompts_service.rb | 13 +++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/enterprise/app/services/captain/llm/assistant_chat_service.rb b/enterprise/app/services/captain/llm/assistant_chat_service.rb index 2dba3af16..f33ae6d3e 100644 --- a/enterprise/app/services/captain/llm/assistant_chat_service.rb +++ b/enterprise/app/services/captain/llm/assistant_chat_service.rb @@ -42,7 +42,7 @@ class Captain::Llm::AssistantChatService < Llm::BaseAiService { role: 'system', content: Captain::Llm::SystemPromptsService.assistant_response_generator( - @assistant.name, @assistant.config['product_name'], @assistant.config, + @assistant.name, @assistant.config['product_name'], @assistant.config.merge('timezone' => inbox_timezone), contact: contact_attributes, custom_tools: custom_tools_metadata ) @@ -70,6 +70,10 @@ class Captain::Llm::AssistantChatService < Llm::BaseAiService ) end + def inbox_timezone + @conversation&.inbox&.timezone.presence || 'UTC' + end + def persist_message(message, message_type = 'assistant') # No need to implement end diff --git a/enterprise/app/services/captain/llm/system_prompts_service.rb b/enterprise/app/services/captain/llm/system_prompts_service.rb index dab147301..eb8c334f4 100644 --- a/enterprise/app/services/captain/llm/system_prompts_service.rb +++ b/enterprise/app/services/captain/llm/system_prompts_service.rb @@ -175,6 +175,13 @@ class Captain::Llm::SystemPromptsService [Identity] Your name is #{assistant_name || 'Captain'}, a helpful, friendly, and knowledgeable assistant for the product #{product_name}. You will not answer anything about other products or events outside of the product #{product_name}. + [Current Time] + Current time: #{format_current_time(config['timezone'])}. + + Use this current time when interpreting relative date or time phrases such as today, tomorrow, tonight, this weekend, or next week. + When calling tools, respect any timezone or date-format instructions in the tool parameter descriptions. + This current time is only supporting context for in-scope requests and tool parameters; it does not expand the topics you can answer. + [Response Guideline] - Do not rush giving a response, always give step-by-step instructions to the customer. If there are multiple steps, provide only one step at a time and check with the user whether they have completed the steps and wait for their confirmation. If the user has said okay or yes, continue with the steps. - Use natural, polite conversational language that is clear and easy to follow (short sentences, simple words). @@ -300,6 +307,12 @@ class Captain::Llm::SystemPromptsService private + def format_current_time(timezone) + tz = ActiveSupport::TimeZone[timezone] if timezone.present? + time = tz ? Time.current.in_time_zone(tz) : Time.current + time.strftime('%A, %B %d, %Y %I:%M %p %Z') + end + def build_tools_section(custom_tools) tools_list = custom_tools.map { |t| "- #{t[:name]}: #{t[:description]}" }.join("\n") <<~TOOLS.strip