<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: PromptOT</title>
    <description>The latest articles on DEV Community by PromptOT (@promptot).</description>
    <link>https://dev.to/promptot</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4009001%2Fda212af2-413d-4e9a-8dd6-251b8f6bbb93.jpg</url>
      <title>DEV Community: PromptOT</title>
      <link>https://dev.to/promptot</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/promptot"/>
    <language>en</language>
    <item>
      <title>Hardcoding LLM prompts is fine until it isn't. Here's what we built instead.</title>
      <dc:creator>PromptOT</dc:creator>
      <pubDate>Tue, 30 Jun 2026 06:53:54 +0000</pubDate>
      <link>https://dev.to/promptot/hardcoding-llm-prompts-is-fine-until-it-isnt-heres-what-we-built-instead-3g7b</link>
      <guid>https://dev.to/promptot/hardcoding-llm-prompts-is-fine-until-it-isnt-heres-what-we-built-instead-3g7b</guid>
      <description>&lt;p&gt;I had a bug last month that took most of a Saturday to find. A support bot we shipped started promising refund timelines that didn't match policy. Customer complaints, frantic Slack messages, the usual.&lt;/p&gt;

&lt;p&gt;The prompt had changed three weeks earlier. Nobody could remember why. Git blame pointed to a one-line edit inside a 200-line &lt;code&gt;SYSTEM_PROMPT&lt;/code&gt; constant. No PR description, no diff worth reading.&lt;/p&gt;

&lt;p&gt;That's when I knew I'd been writing prompts wrong for the last two years.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://www.promptot.com/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.promptot.com%2Fopengraph-image.jpg%3Fopengraph-image.5503fc36.jpg" height="420" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://www.promptot.com/" rel="noopener noreferrer" class="c-link"&gt;
            PromptOT - Prompt Management Platform
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Compose prompts from typed blocks, version safely, and deliver to your apps via API. The prompt management platform built for AI engineering teams.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.promptot.com%2Ffavicon.ico%3Ffavicon.70c146bd.ico" width="48" height="48"&gt;
          promptot.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Prompts are code, but we treat them like Notion docs
&lt;/h2&gt;

&lt;p&gt;A typical system prompt for anything useful crams five things into one string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are a friendly support agent for Acme. Use this knowledge: {{kb}}.
Follow escalation rules. Never share internal ticket IDs. Reply in plain
text, two to four paragraphs.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's a role, context, instructions, guardrails, and an output format all jammed together. When the PM wants to soften the tone, they're editing the same string an engineer uses to update the knowledge base. When security adds a guardrail, it lands inches from the response format. One bad edit and every reply ships broken.&lt;/p&gt;

&lt;p&gt;We wouldn't write code this way. So why are prompts always a 200-line &lt;code&gt;const&lt;/code&gt; somewhere in &lt;code&gt;lib/&lt;/code&gt;?&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.promptot.com" rel="noopener noreferrer"&gt;PromptOT&lt;/a&gt; is a prompt management platform. The core idea is small: typed blocks instead of flat strings.&lt;/p&gt;

&lt;p&gt;You break a prompt into pieces. Each piece has a type — role, context, instructions, guardrails, output_format, custom. Each one is independently editable, can be toggled on or off, and has its own version history. The compiler joins them into a single prompt string at delivery time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Block 1 — role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;          &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;are&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;support&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;agent&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Acme..."&lt;/span&gt;
&lt;span class="na"&gt;Block 2 — context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;       &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Knowledge&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;base:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{kb}}..."&lt;/span&gt;
&lt;span class="na"&gt;Block 3 — instructions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1.&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Acknowledge&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;issue..."&lt;/span&gt;
&lt;span class="na"&gt;Block 4 — guardrails&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Never&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;share&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;internal&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;ticket&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;IDs..."&lt;/span&gt;
&lt;span class="na"&gt;Block 5 — output_format&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Plain&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;text,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;two&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;four&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;paragraphs..."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the PM edits one block. The security review adds a guardrail without touching anything else. Each save is a version. Publishing a version makes it immutable. If something breaks in prod, you roll back from the dashboard in two clicks.&lt;/p&gt;

&lt;h2&gt;
  
  
  The delivery layer
&lt;/h2&gt;

&lt;p&gt;Apps fetch the compiled prompt through a simple API. Production keys return the published version. Development keys return whatever draft is currently being iterated on. Variables resolve at fetch time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://api.promptot.com/api/v1/prompts/support-bot/compiled &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer pk_live_..."&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"customer_name": "Maya", "kb": "..."}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. No SDK to install. No prompt strings sitting in your codebase. Updating a prompt does not require a deploy.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part I'm proudest of
&lt;/h2&gt;

&lt;p&gt;PromptOT ships an MCP server with 23 tools, so your AI assistant can manage prompts for you. I can be in Claude Desktop or Cursor and say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Read my support-bot prompt and add a guardrail about not promising refund timelines.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Claude calls &lt;code&gt;get_prompt&lt;/code&gt;, drafts the change, and calls &lt;code&gt;save_draft_version&lt;/code&gt;. I review the diff and publish. The whole loop happens in chat. No tab-switching, no dashboard.&lt;/p&gt;

&lt;p&gt;claude.ai and ChatGPT connect via OAuth, so they never see a raw key. Other clients (Claude Desktop, Cursor, Codex CLI, Windsurf, Zed) get a scoped install snippet from the dashboard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Free tier covers most side projects — 3 projects, 5 prompts each, 1,000 API calls a month, MCP included. No credit card.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Site: &lt;a href="https://www.promptot.com" rel="noopener noreferrer"&gt;promptot.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Docs: &lt;a href="https://www.promptot.com/docs" rel="noopener noreferrer"&gt;promptot.com/docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;MCP install: &lt;a href="https://www.promptot.com/docs/mcp/install" rel="noopener noreferrer"&gt;promptot.com/docs/mcp/install&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your LLM prompts currently live as constants in a TypeScript file with a TODO from six months ago, you'll know what this fixes.&lt;/p&gt;

&lt;p&gt;What's the worst prompt bug you've shipped to production? Curious which patterns repeat.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>promptengineering</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
