Requirements and best practices for building ITS compilers
This guide defines the requirements for implementing a compliant ITS compiler. Requirements are categorized using RFC 2119 keywords:
Compilers MUST validate templates against the base schema before processing:
version, content)When loading schemas from the extends array:
template fieldCompilation MUST fail if:
The extends array can contain:
https://example.com/schema.json./local-schema.jsonFor better user experience, report which schemas are being loaded.
Compilers may cache remote schemas to improve performance.
Optional but recommended security features include:
Instruction types are resolved in this order (highest to lowest):
customInstructionTypes in the templateextends arrayextends arrayWhen a type is defined in multiple schemas, the entire definition is replaced. No property merging occurs.
Compilers should inform users when types are overridden:
INFO: Instruction type overrides detected:
- 'summary' overridden by marketing-types.json (from company-types.json)
- 'list' overridden by customInstructionTypes (from its-standard-types-v1.json)
Replace ${variableName} references with variable values in:
Handle all JSON-compatible types:
${name}${count}${enabled}${user.name}${items[0]}, including negative indices that select from the end (${items[-1]}).length pseudo-property on arrays and strings: ${items.length}
Array references accept a chain of collection functions after the path: concat(prop?),
sum(prop?), avg(prop?), min(prop?), max(prop?) and
top(n). They are chainable suffixes applied left to right (for example
${forecast.top(3).concat(day)}) and are valid in substitution only, never in conditional
expressions. Aggregations require numeric values, and whole-number results render without a decimal part.
If a variable reference is undefined, compilers MUST fail with a clear error message. Both reference compilers fail in this case, and the shared invalid-template suite requires an error.
| Operator Type | Operators | Example |
|---|---|---|
| Equality | ==, != |
tone == 'professional' |
| Comparison | >, <, >=, <= |
count > 5 |
| Chained comparison | a < b <= c |
1 < number <= 10 |
| Logical | &&, ||, ! (word forms and, or, not accepted) |
includeA && !includeB |
| Membership | in, not in |
type in ['A', 'B', 'C'] |
Conditionals can contain other conditionals in their content arrays.
Invalid expressions should produce helpful error messages.
For each placeholder:
If a template references {property} but it's not in config:
Type Definition:
{
"instructionTypes": {
"list": {
"template": "<<Replace this placeholder with a list using this user prompt: ([{<{description}>}]). Format requirements: Use {format} formatting with each item on a new line.>>",
"configSchema": {
"type": "object",
"properties": {
"format": {
"type": "string",
"enum": ["bullet_points", "numbered"],
"default": "bullet_points"
}
}
}
}
}
}
Placeholder in Template:
{
"type": "placeholder",
"instructionType": "list",
"config": {
"description": "List 5 fruits",
"format": "bullet_points"
}
}
Processing Steps:
{description} with "List 5 fruits"{format} with "bullet_points"([{<List 5 fruits>}])Generated Instruction:
<<Replace this placeholder with a list using this user prompt: ([{<List 5 fruits>}]). Format requirements: Use bullet_points formatting with each item on a new line.>>
The compiled output must have these sections:
INTRODUCTION
[System prompt from compilerConfig]
INSTRUCTIONS
[Processing instructions from compilerConfig]
REFERENCE DATA
[Rendered data sources - only when the template uses reference data]
TEMPLATE
[Processed template content with instructions]
The REFERENCE DATA section is emitted only when any placeholder names a
dataSource or any variable reference resolves to an object; templates using neither omit
that section entirely.
Maintain line breaks, spacing, and structure from the original template.
Compilers MUST support the reserved placeholder config keys dataSource (a variable name or
array of variable names) and dataLimit (a positive integer).
dataLimit; a reference without a limit beats any limitdataSource names an unknown variable${refs} and render the object as reference data automatically
Compilers MUST enforce processing limits - template size, content element count, nesting depth, total
variable count (nested values included), items per variable array, and text length - and MUST make them
operator-configurable. A template can never raise the limits of the compiler processing it. The reference
implementations expose these via configuration objects, CLI flags (JavaScript) and ITS_*
environment variables (Python and .NET).
| Error Type | Required Behavior | Example Message |
|---|---|---|
| Schema Validation | MUST fail compilation | "Template validation failed: Missing required property 'content'" |
| Schema Loading | MUST fail compilation | "Failed to load schema: https://example.com/types.json (404 Not Found)" |
| Version Mismatch | MUST fail compilation | "Schema version 2.0 incompatible with template version 1.0" |
| Undefined Variable | MUST fail compilation | "Undefined variable: ${productName}" |
| Invalid Expression | MUST fail compilation | "Invalid conditional expression: 'count >> 5'" |
| Missing Type | MUST fail compilation | "Unknown instruction type: 'custom_type'" |
Recompile templates when source files change.
Besides the standard prompt format, compilers may generate:
Language server protocol support for real-time validation.
The ITS Compiler Python provides the complete reference implementation of this specification. Use it to:
Installation:
# Core library (PyPI distribution: its-compiler)
pip install its-compiler
# Command-line tool providing its-compile
pip install its-compiler-cli
Usage:
# Compile a template
its-compile template.json --output prompt.txt
# Validate without compiling
its-compile template.json --validate-only
# Watch mode for development
its-compile template.json --watch
ITS Compiler JavaScript provides a node-js implementation.
Installation:
npm install its-compiler-js
Usage:
# Compile a template
npx its-compile template.json --output prompt.txt
# Use variables and watch mode
npx its-compile template.json --variables vars.json --watch
# Strict security mode
npx its-compile template.json --strict --verbose
ITS Compiler .NET provides a .NET 8 library with ASP.NET service and Azure Functions samples. NuGet publication is pending.
The its-example-templates repository is the shared conformance and security suite: every reference compiler runs its templates, and new implementations should too.
function compileTemplate(templatePath) {
// 1. Load and validate template
const template = loadJSON(templatePath)
validateSchema(template, BASE_SCHEMA)
// 2. Load extended schemas
const types = {}
for (const schemaUrl of template.extends || []) {
const schema = loadSchema(schemaUrl)
validateSchema(schema, TYPE_EXTENSION_SCHEMA)
// Apply overrides
Object.assign(types, schema.instructionTypes)
}
// 3. Apply custom types (highest precedence)
Object.assign(types, template.customInstructionTypes || {})
// 4. Process variables
const processedContent = processVariables(template.content, template.variables)
// 5. Evaluate conditionals
const finalContent = evaluateConditionals(processedContent, template.variables)
// 6. Generate instructions
const compiledTemplate = generateInstructions(finalContent, types)
// 7. Collect and render reference data from included placeholders
// and object-valued variable references
const referenceData = collectReferenceData(finalContent, template.variables)
// 8. Assemble final output (REFERENCE DATA section only when present)
return assembleOutput(template.compilerConfig, referenceData, compiledTemplate)
}