Class PromptFormat

java.lang.Object
com.tnsai.prompt.format.PromptFormat

public final class PromptFormat extends Object
Shared formatting helpers for prompt-building call sites.

Three places in the codebase render the same mustAlways / mustNever constraint blocks: RolePromptBuilder (the primary @RoleSpec renderer), RoleSpecReader (YAML / external role-spec ingestion), and the SystemPromptBuilder SCOP bridge in tnsai-integration. Pulling the format here keeps wording, ordering, and indentation in lockstep — improving one site no longer means hunting for the other two.

The format itself is the issue's chosen design: positive obligations first (set the tone), negatives last (draw the boundary), single header per block, bullets indented under the header.

Since:
0.9.3
  • Method Details

    • renderConstraints

      public static void renderConstraints(StringBuilder out, List<String> mustAlways, List<String> mustNever, String indent)
      Append a constraint block for an action — Must always: first, then Must never:, each as a header line followed by indented bullet rules. Empty inputs render nothing.

      Example output (with indent = " "):

      
         Must always:
           - Call this tool exactly once per turn
           - Include the returned question text VERBATIM in your reply
      
         Must never:
           - Paraphrase or summarise the question
       

      Each output line begins with a leading \n; callers stay responsible for any trailing newline they want after the block. Bullet rows are indented two extra spaces under the header so the section grouping stays visually clear.

      Parameters:
      out - buffer to append to
      mustAlways - positive obligations; null or empty skips the block
      mustNever - negative obligations; null or empty skips the block
      indent - base indent string applied to both the header and the bullet rows
    • renderConstraints

      public static void renderConstraints(StringBuilder out, String[] mustAlways, String[] mustNever, String indent)
      Convenience overload accepting String[] arrays — convenient for callers reading from ActionMetadata whose getters return raw arrays.
    • renderExamples

      public static void renderExamples(StringBuilder out, List<ToolExampleSpec> examples, String indent)
      Append a `@ToolExample` block for an action — positive examples under Examples:, then negatives under Avoid (anti-patterns):. Same indent + bullet conventions as renderConstraints(StringBuilder, List, List, String).

      Why render examples in the system-prompt prose at all: provider tool definitions (input_examples on Anthropic, description fold on OpenAI / Gemini / others) already deliver examples at the tool-call surface. The system-prompt surface is *additionally* useful: the model sees these when reasoning about the role overall, before deciding whether a tool is the right move. Anthropic's research reports a 72%→90% accuracy improvement on complex parameter handling when examples are present — concrete examples beat abstract rules. Token cost is paid once on the cached system prompt, not per call.

      Empty inputs render nothing. Examples whose input is blank are skipped (defensive — the only field every example must have meaningful content for).

      Bullet shape:

      
         Examples:
           - {description}: input={input} → output={output}
      
         Avoid (anti-patterns):
           - {description}: input={input} — Why bad: {whyBad}
       
      Parameters:
      out - buffer to append to
      examples - positive + negative examples; null or empty skips the entire block
      indent - base indent applied to headers and bullets