Class: TurnKit::SystemPrompt
- Inherits:
-
Object
- Object
- TurnKit::SystemPrompt
- Defined in:
- lib/turnkit/system_prompt.rb
Constant Summary collapse
- DEFAULT_SECTIONS =
%i[agent instructions behavior loaded_skills available_skills tools subject environment].freeze
- SECTION_METHODS =
{ agent: :agent_section, instructions: :instructions_section, behavior: :behavior_section, loaded_skills: :loaded_skills_section, available_skills: :available_skills_section, tools: :tools_section, subject: :subject_section, environment: :environment_section }.freeze
- DEFAULT_BEHAVIOR =
<<~TEXT.strip Treat each user message as a constraint on the current task. Follow the agent instructions and loaded skills first, then use tools when they are available and needed. Use the provided environment as the source of truth for the current date and time. Do not guess relative dates like "today", "tomorrow", or "yesterday" when the environment gives an exact calendar anchor. Only use tools listed in <tools_available>. If a tool you want is not listed, it is unavailable for this turn; adjust your answer instead of pretending to call it. If a tool returns an error, read the error and fix your inputs before trying again. Do not retry the identical failing call blindly. Report outcomes honestly. If you cannot verify something, say so or omit the claim instead of inventing details. TEXT
Instance Attribute Summary collapse
-
#agent ⇒ Object
readonly
Returns the value of attribute agent.
-
#conversation ⇒ Object
readonly
Returns the value of attribute conversation.
-
#sections ⇒ Object
readonly
Returns the value of attribute sections.
-
#turn ⇒ Object
readonly
Returns the value of attribute turn.
Class Method Summary collapse
Instance Method Summary collapse
- #agent_section ⇒ Object
- #available_skills_section ⇒ Object
- #behavior_section ⇒ Object
- #environment_section ⇒ Object
-
#initialize(agent:, turn:, conversation:, sections: nil) ⇒ SystemPrompt
constructor
A new instance of SystemPrompt.
- #instructions_section ⇒ Object
- #loaded_skills_section ⇒ Object
- #render(section) ⇒ Object
- #subject_section ⇒ Object
- #to_s ⇒ Object
- #tools_section ⇒ Object
Constructor Details
#initialize(agent:, turn:, conversation:, sections: nil) ⇒ SystemPrompt
Returns a new instance of SystemPrompt.
39 40 41 42 43 44 |
# File 'lib/turnkit/system_prompt.rb', line 39 def initialize(agent:, turn:, conversation:, sections: nil) @agent = agent @turn = turn @conversation = conversation @sections = Array(sections || agent.effective_prompt_sections) end |
Instance Attribute Details
#agent ⇒ Object (readonly)
Returns the value of attribute agent.
37 38 39 |
# File 'lib/turnkit/system_prompt.rb', line 37 def agent @agent end |
#conversation ⇒ Object (readonly)
Returns the value of attribute conversation.
37 38 39 |
# File 'lib/turnkit/system_prompt.rb', line 37 def conversation @conversation end |
#sections ⇒ Object (readonly)
Returns the value of attribute sections.
37 38 39 |
# File 'lib/turnkit/system_prompt.rb', line 37 def sections @sections end |
#turn ⇒ Object (readonly)
Returns the value of attribute turn.
37 38 39 |
# File 'lib/turnkit/system_prompt.rb', line 37 def turn @turn end |
Class Method Details
.loaded_skills_text(skills) ⇒ Object
86 87 88 |
# File 'lib/turnkit/system_prompt.rb', line 86 def self.loaded_skills_text(skills) skills.map { |skill| "## Skill: #{skill.key}\n\n#{skill.content}" }.join("\n\n") end |
Instance Method Details
#agent_section ⇒ Object
57 58 59 60 61 62 63 64 65 |
# File 'lib/turnkit/system_prompt.rb', line 57 def agent_section lines = [ "- Name: #{agent.name}", agent.description.empty? ? nil : "- Description: #{agent.description}", "- Model: #{turn.model || agent.effective_model}" ].compact tagged("agent", lines.join("\n")) end |
#available_skills_section ⇒ Object
90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/turnkit/system_prompt.rb', line 90 def available_skills_section skills = agent.effective_available_skills return nil if skills.empty? entries = skills.map do |skill| description = skill.description.empty? ? nil : " — #{skill.description}" "- #{skill.key}: #{skill.name}#{description}" end tagged( "skills_available", "Load or follow a skill when the task matches its description.\n\n#{entries.join("\n")}" ) end |
#behavior_section ⇒ Object
73 74 75 |
# File 'lib/turnkit/system_prompt.rb', line 73 def behavior_section tagged("behavior", TurnKit.prompt_behavior || DEFAULT_BEHAVIOR) end |
#environment_section ⇒ Object
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/turnkit/system_prompt.rb', line 124 def environment_section anchor = turn.started_at || Clock.now today = anchor.to_date yesterday = today - 1 tomorrow = today + 1 tagged( "environment", [ "- Today: #{today.strftime('%A, %B %-d, %Y')} (#{today.iso8601})", "- Current time: #{anchor.strftime('%-I:%M %Z')}", "- Yesterday: #{yesterday.strftime('%A, %B %-d, %Y')} (#{yesterday.iso8601})", "- Tomorrow: #{tomorrow.strftime('%A, %B %-d, %Y')} (#{tomorrow.iso8601})" ].join("\n") ) end |
#instructions_section ⇒ Object
67 68 69 70 71 |
# File 'lib/turnkit/system_prompt.rb', line 67 def instructions_section return nil if agent.instructions.empty? tagged("instructions", agent.instructions) end |
#loaded_skills_section ⇒ Object
77 78 79 80 81 82 83 84 |
# File 'lib/turnkit/system_prompt.rb', line 77 def loaded_skills_section return nil if agent.skills.empty? tagged( "skills_loaded", self.class.loaded_skills_text(agent.skills) ) end |
#render(section) ⇒ Object
50 51 52 53 54 55 |
# File 'lib/turnkit/system_prompt.rb', line 50 def render(section) method = SECTION_METHODS[section.to_sym] raise ArgumentError, "unknown prompt section: #{section}" unless method public_send(method) end |
#subject_section ⇒ Object
115 116 117 118 119 120 121 122 |
# File 'lib/turnkit/system_prompt.rb', line 115 def subject_section return nil unless conversation.subject&.respond_to?(:to_prompt) value = conversation.subject.to_prompt.to_s.strip return nil if value.empty? tagged("subject_context", value) end |
#to_s ⇒ Object
46 47 48 |
# File 'lib/turnkit/system_prompt.rb', line 46 def to_s sections.map { |section| render(section) }.compact.reject { |value| value.strip.empty? }.join("\n\n") end |
#tools_section ⇒ Object
105 106 107 108 109 110 111 112 113 |
# File 'lib/turnkit/system_prompt.rb', line 105 def tools_section tools = agent.effective_tools if tools.empty? tagged("tools_available", "(none)\n\nNo tools are available for this turn.") else tagged("tools_available", tools.map { |tool| tool_line(tool) }.join("\n")) end end |