A Developer's Guide to Prompt Orchestration Markup Language


A Developer's Guide to Prompt Orchestration Markup Language

microsoft/poml

2025-08-15

As software engineers, we're all about creating systems that are robust, easy to maintain, and scalable. Plain text prompts, while simple to start with, can quickly become messy and hard to manage, especially for complex applications. POML solves these problems by providing a structured, declarative way to define prompts.

Structure and Readability
POML uses an HTML/XML-like syntax with semantic tags such as <role>, <task>, and <example>. This makes your prompts much more readable and easier to understand, not just for you but for your entire team. It clearly separates the different parts of a prompt.

Maintainability
By using a structured format, you can easily update, refactor, and version control your prompts. Changes to one part of the prompt don't have to ripple through the entire text block, making maintenance a breeze.

Data Integration
POML makes it simple to integrate different types of data—like text files, tables, or even images—directly into your prompts using tags like <document> or <table>. This is super helpful for building applications that require rich context.

Separation of Concerns
Just like in web development where we separate HTML (structure) from CSS (style), POML lets you separate the content of your prompt from its presentation. You can use a <stylesheet> to define how your prompt should be formatted (e.g., using bullet points or specific headings) without changing the core content. This is great for A/B testing different prompt formats without altering the logic.

Tooling
The Visual Studio Code extension is a game-changer. It provides features like syntax highlighting, live previews, and the ability to test your prompts directly within the editor. This turns prompt engineering into a more professional, "coding-like" experience.

Reusability
You can create modular, reusable components. For example, if you have a specific role or set of instructions you use across multiple prompts, you can define it once and reuse it, just like a function or a class in traditional programming.

Getting started with POML is pretty straightforward, especially if you're already a Visual Studio Code user.

Install the Extension
The first step is to install the official POML extension for Visual Studio Code from the marketplace. This gives you all the cool features like syntax highlighting and the preview panel.

Create a .poml File
Create a new file in your project with the .poml extension. This tells VS Code to use the POML language server and extension features.

Write Your Prompt
Start writing your prompt using the semantic tags. A basic prompt will have a <poml> root element. You can then add elements like <role>, <task>, and <instructions>.

Use the Preview
The VS Code extension has a built-in preview pane. Open it up and you can see how your structured POML file is rendered into a final, plain-text prompt that can be sent to an LLM. This lets you iterate quickly and see your changes in real-time.

Let's look at a few examples to see POML in action.

This example shows a simple, well-structured prompt for a sentiment analysis task.

<poml>
  <role>You are a helpful assistant for analyzing text sentiment.</role>
  <task>
    Your task is to classify the sentiment of the provided review as either 'positive', 'negative', or 'neutral'.
    Provide only the sentiment label as the output.
  </task>
  <input>
    <document title="Product Review">
      The quality of the product was fantastic, but the shipping was incredibly slow.
    </document>
  </input>
  <output>
    neutral
  </output>
</poml>

What's Happening Here?

<role> defines the persona of the assistant.

<task> specifies the instructions for the LLM.

<input> contains the data the LLM needs to process, in this case, a product review.

<output> provides an example of the desired response format.

This structured approach is much cleaner than a single text block. You can easily swap out the content inside <input> for different reviews without touching the core instructions.

This example demonstrates how to integrate a table directly into a prompt, which is perfect for tasks that involve structured data.

<poml>
  <role>You are a data analyst.</role>
  <task>
    Analyze the provided sales data and summarize the total sales for each region.
    Present the summary in a simple list format.
  </task>
  <input>
    <document title="Quarterly Sales Report">
      <table>
        <thead>
          <tr><th>Region</th><th>Sales</th></tr>
        </thead>
        <tbody>
          <tr><td>North</td><td>$15,000</td></tr>
          <tr><td>South</td><td>$22,000</td></tr>
          <tr><td>East</td><td>$18,000</td></tr>
          <tr><td>West</td><td>$25,000</td></tr>
        </tbody>
      </table>
    </document>
  </input>
</poml>

What's Happening Here?

The <table> tag lets you embed structured data directly.

The LLM gets a clear, labeled table to work with, which can lead to more accurate and predictable results compared to just pasting a CSV or a bunch of numbers.

POML isn't just for writing; you can also programmatically interact with it using an SDK. Here's a quick Python example.

First, you'd have your .poml file (sales_analyst.poml)

<poml>
  <role>You are a data analyst.</role>
  <task>
    Analyze the provided sales data and summarize the total sales for each region.
    Present the summary in a simple list format.
  </task>
  <input>
    <document title="Quarterly Sales Report">
      <template name="sales_data" />
    </document>
  </input>
</poml>

And then your Python code to load it and render it with dynamic data

from poml import load_poml, render_poml

# Load the POML file
prompt_template = load_poml("sales_analyst.poml")

# Your dynamic data
sales_data = """
<table>
  <thead>
    <tr><th>Region</th><th>Sales</th></tr>
  </thead>
  <tbody>
    <tr><td>North</td><td>$15,000</td></tr>
    <tr><td>South</td><td>$22,000</td></tr>
    <tr><td>East</td><td>$18,000</td></tr>
    <tr><td>West</td><td>$25,000</td></tr>
  </tbody>
</table>
"""

# Render the prompt with the data
final_prompt = render_poml(prompt_template, {"sales_data": sales_data})

print(final_prompt)

What's Happening Here?

We're using a <template> tag as a placeholder. This allows us to inject data programmatically at runtime.

The render_poml function takes the template and a dictionary of data to fill in the blanks.

This approach cleanly separates the prompt's logic from the data, which is a fundamental principle of good software design. It makes your code more modular and testable.


microsoft/poml




linshenkx/prompt-optimizer: A Software Engineer's Toolkit for High-Quality Prompts

At its core, prompt-optimizer is a prompt engineering toolkit. Think of it as a set of tools that help you systematically improve the prompts you feed to AI models


Boosting Productivity with KiloCode in VS Code

KiloCode, built by Kilo-Org, is an open-source AI coding assistant designed to help software engineers with the entire development lifecycle planning