Skip to main content

POM technical reference

Learn how to use the Prompt Object Model

Introduction​

This technical reference provides comprehensive documentation for developers working with the Prompt Object Model (POM) library. To learn more about what the Prompt Object Model is, see the POM overview.

POM format specification​

The POM is a JSON array of section objects with specific requirements based on position and nesting:

FieldRequiredDescription
titleNoHeading text
bodyOne of body or bullets requiredParagraph or long-form instruction text
bulletsOne of body or bullets requiredNon-empty array of short statements/rules
subsectionsNoNested list of sections
numberedNoBoolean indicating if section should be numbered
numberedBulletsNoBoolean indicating if bullets should be numbered

JSON schema for POM​

Users can refer to the following JSON schema and basic example below for the POM structure:

{
"$schema": "https://json-schema.org/draft-07/schema",
"$id": "https://example.com/pom.schema.json",
"title": "Prompt Object Model",
"type": "array",
"items": { "$ref": "#/$defs/section" },
"$defs": {
"section": {
"type": "object",
"properties": {
"title": { "type": "string" },
"body": { "type": "string" },
"bullets": {
"type": "array",
"items": { "type": "string" }
},
"subsections": {
"type": "array",
"items": { "$ref": "#/$defs/section" }
},
"numbered": { "type": "boolean" },
"numberedBullets": { "type": "boolean" }
},
"anyOf": [
{ "required": ["body"] },
{ "required": ["bullets"] }
],
"additionalProperties": false
}
}
}

Core classes​

The library consists of two main classes:

ClassDescription
PromptObjectModelThe main container that holds all sections and provides top-level functionality
SectionRepresents a single section in the prompt hierarchy with content and structure

PromptObjectModel class​

The PromptObjectModel class is the main entry point for creating and managing prompt objects.

Constructing a new POM​

from signalwire_pom import PromptObjectModel

# Create a new POM
pom = PromptObjectModel()

Methods​

MethodDescription
add_sectionAdds a top-level section to the prompt POM.
find_sectionFinds a section by its title, searching recursively through all sections and subsections.
to_jsonConverts the entire POM to a JSON string.
to_yamlConverts the entire POM to a YAML string.
to_dictConverts the entire POM to a list of dictionaries.
render_markdownRenders the entire POM as markdown.
render_xmlRenders the entire POM as XML.
from_jsonCreates a PromptObjectModel instance from JSON data.
from_yamlCreates a PromptObjectModel instance from YAML data.
add_pom_as_subsectionAdds another POM as a subsection to a specified section.

add_section​

Adds a top-level section to the prompt POM.

Parameters:

ParameterTypeDefault ValueDescription
titleOptionalOptional[str]-The title of the section
bodyOptionalstr''Body text for the section
bulletsOptionalUnion[List[str], str]-List of bullet points or a single string (which will be converted to a single-item list)
numberedOptionalOptional[bool]NoneWhether this section should be numbered
numberedBulletsOptionalboolFalseWhether bullets should be numbered instead of using bullet points

Returns:

TypeDescription
SectionThe newly created section object

Example:

# Create a section with a title and body
rules = pom.add_section(
"Rules",
body="Follow these important guidelines:"
)

# Add bullet points
rules.add_bullets([
"Never send emails on behalf of the user",
"Maintain user privacy and confidentiality"
])

find_section​

Finds a section by its title, searching recursively through all sections and subsections.

Parameters:

ParameterTypeDefault ValueDescription
titleRequiredstr-The title to search for

Returns:

TypeDescription
Optional[Section]The found section or None if not found

Example:

# Find a section by its title
rules_section = pom.find_section("Rules")
if rules_section:
# Modify the found section
rules_section.add_bullets(["Always suggest proofreading before sending"])

to_json​

Converts the entire POM to a JSON string.

Parameters: None

Returns:

TypeDescription
strJSON string representation of the POM

Example:

# Generate JSON representation
json_data = pom.to_json()
print(json_data)

to_yaml​

Converts the entire POM to a YAML string.

Parameters: None

Returns:

TypeDescription
strYAML string representation of the POM

Example:

# Generate YAML representation
yaml_data = pom.to_yaml()
print(yaml_data)

to_dict​

Converts the entire POM to a list of dictionaries.

Parameters: None

Returns:

TypeDescription
List[dict]List of dictionaries representing each section in the POM

Example:

# Convert POM to dictionary representation
dict_data = pom.to_dict()
print(dict_data)

render_markdown​

Renders the entire POM as markdown. The method will follow the below logic when rendering the POM as markdown:

Rendering Logic:

  • Top-level sections with titles are rendered as ## (h2 headings)
  • Each level of nesting increases the heading level (h3, h4, etc.)
  • Body text appears after the heading
  • Bullet points are rendered as markdown list items with - prefix
  • Proper line spacing is maintained between elements

Parameters: None

Returns:

TypeDescription
strMarkdown representation of the POM

Example:

from signalwire_pom import PromptObjectModel

# Create a new POM
pom = PromptObjectModel()

# Add a section with title and body
section = pom.add_section(
"System instructions",
body="You are a helpful AI assistant."
)

# Add bullet points
section.add_bullets([
"Answer user questions accurately",
"Be concise and clear"
])

sub_section = section.add_subsection(
"Subsection 1",
body="This is the body of the subsection."
)

sub_section.add_bullets([
"Answer user questions accurately",
"Be concise and clear"
])

# Render as markdown
markdown = pom.render_markdown()
print(markdown)

Output:

## System instructions

You are a helpful AI assistant.

- Answer user questions accurately
- Be concise and clear

### Subsection 1

This is the body of the subsection.

- Answer user questions accurately
- Be concise and clear

render_xml​

Renders the entire POM as XML. The method will follow the below logic when rendering the POM as XML:

Rendering Logic:

  • The POM is wrapped in a root <prompt> element
  • Each section is represented as a <section> element
  • Section properties are rendered as child elements:
    • <title> for the section title
    • <body> for the section body text
    • <bullets> containing individual <bullet> elements
    • <subsections> containing nested <section> elements

Parameters:

ParameterTypeDefault ValueDescription
indentOptionalint0The indentation level to start with (default: 0)

Returns:

TypeDescription
strXML representation of the POM

Example:

# Using the same POM from the previous example
xml = pom.render_xml()
print(xml)

Output:

<?xml version="1.0" encoding="UTF-8"?>
<prompt>
<section>
<title>System instructions</title>
<body>You are a helpful AI assistant.</body>
<bullets>
<bullet>Answer user questions accurately</bullet>
<bullet>Be concise and clear</bullet>
</bullets>
<subsections>
<section>
<title>Subsection 1</title>
<body>This is the body of the subsection.</body>
<bullets>
<bullet>Answer user questions accurately</bullet>
<bullet>Be concise and clear</bullet>
</bullets>
</section>
</subsections>
</section>
</prompt>

from_json​

Creates a PromptObjectModel instance from JSON data.

Parameters:

ParameterTypeDefault ValueDescription
json_dataRequiredUnion[str, dict]-Either a JSON string or a parsed dictionary

Returns:

TypeDescription
PromptObjectModelA new instance populated with data from the JSON

Example:

# Create a POM from JSON
json_string = '''
[
{
"title": "Knowledge",
"body": "You have the following specific knowledge:",
"bullets": ["Email etiquette", "Business terminology"],
"subsections": []
}
]
'''
knowledge_pom = PromptObjectModel.from_json(json_string)

from_yaml​

Creates a PromptObjectModel instance from YAML data.

Parameters:

ParameterTypeDefault ValueDescription
yaml_dataRequiredUnion[str, dict]-Either a YAML string or a parsed dictionary

Returns:

TypeDescription
PromptObjectModelA new instance populated with data from the YAML

Example:

# Create a POM from YAML
yaml_string = '''
- title: Knowledge
body: You have the following specific knowledge
bullets:
- Email etiquette
- Business terminology
subsections: []
'''
knowledge_pom = PromptObjectModel.from_yaml(yaml_string)

add_pom_as_subsection​

Adds another PromptObjectModel as a subsection to a section with the given title or section object.

Parameters:

ParameterTypeDefault ValueDescription
targetRequiredUnion[str, Section]-The title of the section or the Section object to add to
pom_to_addRequiredPromptObjectModel-The PromptObjectModel to add as a subsection

Returns:

TypeDescription
NoneThis method doesn't return a value

Raises:

  • ValueError: If no section with the target title is found (when target is a string)
  • TypeError: If target is neither a string nor a Section object

Example:

# Create two POMs
base_pom = PromptObjectModel()
base_section = base_pom.add_section("Base Section", body="Main content")

additional_pom = PromptObjectModel()
additional_pom.add_section("Additional Content", body="Extra information")

# Add the additional POM as a subsection
base_pom.add_pom_as_subsection("Base Section", additional_pom)

Section class​

The Section class represents a single section in the POM hierarchy and provides methods for managing content and structure. A section can be accessed through a instance of the PromptObjectModel class.

Constructing a new Section​

from signalwire_pom import PromptObjectModel

# Create a new POM
pom = PromptObjectModel()

# Add a section to the POM
section = pom.add_section("Section title", body="This is the main content of my section.")

Methods​

MethodDescription
add_bodyAdds or replaces the body text for this section.
add_bulletsAdds bullet points to this section.
add_subsectionAdds a subsection to this section.
to_dictConverts the section to a dictionary representation.
render_markdownRenders this section and all its subsections as markdown.
render_xmlRenders this section and all its subsections as XML.

add_body​

Adds or replaces the body text for this section.

Parameters:

ParameterTypeDefault ValueDescription
bodyRequiredstr-The text to set as the section body

Returns:

TypeDescription
NoneThis method doesn't return a value

Example:

section = pom.add_section("Section title")
section.add_body("This is the main content of my section.")

add_bullets​

Adds bullet points to this section.

Parameters:

ParameterTypeDefault ValueDescription
bulletsRequiredList[str]-List of bullet points to add

Returns:

TypeDescription
NoneThis method doesn't return a value

Example:

section = pom.add_section("Guidelines")
section.add_bullets([
"First important point",
"Second important point",
"Third important point"
])

add_subsection​

Adds a subsection to this section.

Parameters:

ParameterTypeDefault ValueDescription
titleOptionalstr-The title of the subsection
bodyOptionalstr-Optional body text for the subsection
bulletsOptionalOptional[List[str]]-Optional list of bullet points

Returns:

TypeDescription
SectionThe newly created subsection

Example:

capabilities = pom.add_section("Capabilities")
drafting = capabilities.add_subsection(
"Email drafting",
body="Create email drafts based on user specifications."
)
drafting.add_bullets([
"Format emails properly with greeting, body, and signature",
"Adjust tone based on recipient and purpose"
])

to_dict​

Converts the section to a dictionary representation.

Parameters: None

Returns:

TypeDescription
dictDictionary representation of the section

Example:

section = pom.add_section("Test section")
section_dict = section.to_dict()

render_markdown​

Renders this section and all its subsections as markdown. The method will follow the below logic when rendering the section as markdown:

Rendering Logic:

  • The section title is rendered as a heading, with heading level based on nesting depth
  • The heading level starts at the provided level parameter (default: 2, which is ##)
  • Body text appears after the heading with a blank line
  • Bullet points are rendered as markdown list items with - prefix
  • Subsections are rendered with incremented heading levels to show hierarchy
  • If a section has no title (only valid at root level), its content is rendered directly

Parameters:

ParameterTypeDefault ValueDescription
levelOptionalint2The heading level to start with (default: 2, which corresponds to ##)

Returns:

TypeDescription
strMarkdown representation of the section

Example:

# Using a section from the previous example
section_markdown = section.render_markdown()
print(section_markdown)

Output:

## System instructions

You are a helpful AI assistant.

- Answer user questions accurately
- Be concise and clear

### Subsection 1

This is the body of the subsection.

- Answer user questions accurately
- Be concise and clear

render_xml​

Renders this section and all its subsections as XML. The method will follow the below logic when rendering the section as XML:

Rendering Logic:

  • The section is represented as a <section> element
  • Section properties are rendered as child elements:
    • <title> for the section title (if present)
    • <body> for the section body text (if present)
    • <bullets> containing individual <bullet> elements (if present)
    • <subsections> containing nested <section> elements (if present)

Parameters:

ParameterTypeDefault ValueDescription
indentOptionalint0The indentation level to start with (default: 0)

Returns:

TypeDescription
strXML representation of the section

Example:

# Using a section from the previous example
section_xml = section.render_xml()
print(section_xml)

Output:

<section>
<title>System instructions</title>
<body>You are a helpful AI assistant.</body>
<bullets>
<bullet>Answer user questions accurately</bullet>
<bullet>Be concise and clear</bullet>
</bullets>
<subsections>
<section>
<title>Subsection 1</title>
<body>This is the body of the subsection.</body>
<bullets>
<bullet>Answer user questions accurately</bullet>
<bullet>Be concise and clear</bullet>
</bullets>
</section>
</subsections>
</section>

Command line interface​

The POM library includes a command-line interface (CLI) tool for working with POM files. The CLI allows you to convert between different formats and merge POM files.

Usage​

pom_tool <input_file> [--output=<format>] [--outfile=<file>] [--merge_pom="<section name>:<filename>"]

Arguments​

ArgumentDescription
input_fileRequiredPath to the input POM file (JSON or YAML format)

Options​

OptionDefaultDescription
-h, --helpOptional-Show help message
--output=<format>OptionalmdOutput format: md, xml, json, yaml
--outfile=<file>Optional-Output file path (if not specified, prints to stdout)
--merge_pom=<arg>Optional-Merge another POM file into a section: "<section name>:<filename>"

Error handling​

The tool handles several error conditions:

  1. Invalid output format: Returns an error if the specified output format is not one of: md, xml, json, yaml
  2. File parsing errors: Reports JSON/YAML parsing errors with descriptive messages
  3. Section not found: When using --merge_pom, reports if the target section is not found
  4. Invalid merge syntax: Validates the section:filename format for the merge option

Examples​

  1. Convert a JSON POM file to Markdown:
pom_tool input.json --output=md
  1. Convert a YAML POM file to XML and save to file:
pom_tool input.yaml --output=xml --outfile=output.xml
  1. Merge two POM files:
pom_tool base.json --merge_pom="System Instructions:additional.json" --output=json
  1. Show help message:
pom_tool --help