LLM artifact types implementation guide
Apicurio Registry includes built-in AI/ML artifact types (MODEL_SCHEMA and PROMPT_TEMPLATE). You can learn about the architecture, JSON Schema backing, MCP integration, and implementation details for these types.
Architecture overview
The LLM artifact types are first-class Java artifact types in Apicurio Registry. They follow the same pattern as other built-in types such as Avro, JSON Schema, and Agent Card.
The LLM artifact types consist of the following components:
| Component | Description |
|---|---|
Java implementation |
Source files in |
Provider wiring |
|
Prompt rendering service |
Java service ( |
Each artifact type includes the following handler functions (as Java classes in schema-util/common/):
| Function | Purpose |
|---|---|
|
Checks whether content matches this artifact type based on structure and content type. |
|
Validates content structure, required fields, and constraint violations. |
|
Checks backward compatibility between existing and proposed versions. |
|
Normalizes content for consistent hashing and comparison. |
|
Identifies |
|
Resolves |
|
Rewrites |
|
Verifies that all references are properly mapped. |
JSON Schema backing and industry standards
The PROMPT_TEMPLATE and MODEL_SCHEMA artifact types in Apicurio Registry have formal JSON Schemas, aligned with industry standards for interoperability.
You can find the JSON Schemas in app/src/main/resources/schemas/:
| File | Description |
|---|---|
|
Schema for PROMPT_TEMPLATE artifacts, aligned with Microsoft Prompty |
|
Schema for MODEL_SCHEMA artifacts, aligned with Google Model Card Toolkit |
The PROMPT_TEMPLATE schema is aligned with the Microsoft Prompty specification for interoperability with the Azure AI ecosystem.
| Apicurio field | Prompty field | Notes |
|---|---|---|
|
|
Primary identifier |
|
|
Both names supported |
|
|
Both names supported |
|
Body content |
{{variable}} syntax |
|
|
Model configuration |
|
|
Contributors list |
|
|
Categorization |
templateId: sentiment-analysis
name: Sentiment Analysis Prompt
version: "1.0.0"
description: Analyzes customer sentiment
# Prompty-aligned fields
authors:
- Apicurio Team
tags:
- sentiment
- nlp
templateFormat: mustache # or jinja2, handlebars
# Model configuration (Prompty-aligned)
model:
api: chat
parameters:
temperature: 0.3
max_tokens: 500
template: |
Analyze the sentiment of: {{customerMessage}}
variables:
customerMessage:
type: string
required: true
The MODEL_SCHEMA is aligned with the Google Model Card Toolkit for governance and compliance use cases.
| Apicurio field | Model Card field | Notes |
|---|---|---|
|
|
Model identifier |
|
|
Model provider |
|
|
Version info |
|
|
I/O schema |
|
|
I/O schema |
|
|
Full metadata |
|
|
Metrics |
|
|
Ethics, limitations |
{
"modelId": "claude-3-opus",
"provider": "anthropic",
"version": "2024-02",
"input": { "type": "object" },
"output": { "type": "object" },
"modelDetails": {
"name": "Claude 3 Opus",
"overview": "Advanced multimodal AI assistant",
"owners": [{"name": "Anthropic"}],
"licenses": [{"identifier": "Proprietary"}]
},
"considerations": {
"users": ["Developers", "Enterprises"],
"limitations": ["May produce inaccurate information"],
"ethicalConsiderations": [
{"name": "Bias", "mitigationStrategy": "Regular auditing"}
]
}
}
MCP (Model Context Protocol) integration
Apicurio Registry supports the Model Context Protocol (MCP) and makes PROMPT_TEMPLATE artifacts available as MCP prompts. AI agents can discover and use prompt templates through MCP.
Prompt templates can include an mcp section to enable MCP protocol integration:
templateId: support-chat
name: Support Chat Prompt
template: |
Answer the question: {{question}}
variables:
question:
type: string
required: true
# MCP integration
mcp:
enabled: true
name: support-chat
description: Answer customer support questions
arguments:
- name: question
description: The customer question
required: true
| Field | Required | Description |
|---|---|---|
|
No |
Set to |
|
No |
MCP prompt name (defaults to |
|
No |
MCP prompt description (defaults to template description) |
|
No |
MCP arguments (auto-derived from |
The mcp/ module contains an MCP Server for registry prompts:
| Component | Description |
|---|---|
|
MCP Server that makes prompt templates available as MCP prompts |
|
Parses and renders prompt templates |
The MCP Server includes the following tools and prompts:
| Tool | Description |
|---|---|
|
List all MCP-enabled prompt templates in the registry |
|
Get and render an MCP-enabled prompt with arguments |
|
Render any prompt template (MCP-enabled or not) |
| Prompt | Description |
|---|---|
|
Interactive prompt for rendering templates from the registry |
To run the MCP Server:
cd mcp
../mvnw quarkus:dev
The MCP Server communicates with the registry and makes prompts available through the MCP protocol. AI agents such as Claude and ChatGPT can discover and use registry-stored prompts.
| Layer | Description |
|---|---|
Apicurio Registry (PROMPT_TEMPLATE artifacts) |
Stores prompt templates with |
MCP server module |
Connects Apicurio Registry to AI agents by using the MCP protocol. Provides the following tools:
|
AI agent or LLM (such as Claude or ChatGPT) |
Communicates with the MCP server by using the MCP protocol:
|
PROMPT_TEMPLATE implementation details
The PROMPT_TEMPLATE artifact type implementation resides in schema-util/util-provider/src/main/java/io/apicurio/registry/types/provider/PromptTemplateArtifactTypeUtilProvider.java, with validators, extractors, and compatibility checkers in schema-util/common/.
interface PromptTemplate {
$schema?: string; // Schema URL for identification
templateId: string; // Required: unique identifier
name?: string; // Human-readable name
description?: string; // Template description
version?: string; // Semantic version
template: string; // Required: template text with {{variable}} placeholders
// Prompty-aligned fields
authors?: string[]; // Contributors list
tags?: string[]; // Categorization tags
templateFormat?: string; // 'mustache' | 'jinja2' | 'handlebars'
model?: ModelConfiguration; // Model configuration
// Input/output definitions (Prompty: inputs/outputs)
variables?: Record<string, VariableSchema>; // Variable definitions
inputs?: Record<string, VariableSchema>; // Alias for variables (Prompty)
outputSchema?: Record<string, unknown>; // Expected output structure
outputs?: Record<string, unknown>; // Alias for outputSchema (Prompty)
// Extensions
metadata?: Record<string, unknown>; // Custom metadata
mcp?: MCPConfiguration; // MCP integration
}
interface VariableSchema {
type?: string; // string, integer, number, boolean, array, object
required?: boolean; // Whether variable is required
default?: unknown; // Default value
description?: string; // Variable description
enum?: unknown[]; // Allowed values
minimum?: number; // Minimum value for numeric types
maximum?: number; // Maximum value for numeric types
$ref?: string; // Reference to external schema
}
interface ModelConfiguration {
api?: string; // 'chat' | 'completion'
configuration?: {
type?: string; // Provider type
azure_deployment?: string;
azure_endpoint?: string;
};
parameters?: {
temperature?: number;
max_tokens?: number;
top_p?: number;
};
response?: string; // 'first' | 'all'
}
interface MCPConfiguration {
enabled?: boolean; // Expose via MCP protocol
name?: string; // MCP prompt name
description?: string; // MCP prompt description
arguments?: MCPArgument[]; // MCP arguments
}
The acceptsContent() function detects PROMPT_TEMPLATE content by checking the following criteria:
-
Content type is
application/json,application/x-yaml, ortext/x-prompt-template. -
Schema identifier: the
$schemafield containsprompt-template. -
Required fields: both
templateIdandtemplatefields are present.
The validate() function checks the following rules:
-
templateIdmust be a non-empty string. -
templatemust be a non-empty string. -
All
{{variable}}placeholders in the template must have corresponding definitions invariables. -
Variable types must be valid:
string,integer,number,boolean,array,object. -
Numeric constraints (
minimum,maximum) must be numbers. -
Enum values must be arrays.
| Change type | Allowed | Reason |
|---|---|---|
Add new optional variable |
Yes |
Existing consumers can ignore new variables |
Remove unused variable (not in template) |
Yes |
No impact on template rendering |
Remove used variable (in template) |
No |
Breaks template rendering |
Change variable type |
No |
Existing variable values might become invalid |
Make optional variable required |
No |
Existing consumers might not provide the value |
Narrow enum values (remove options) |
No |
Existing valid values might become invalid |
Change template text (same variables) |
Yes |
Variable contract remains intact |
Remove output schema property |
No |
Consumers might depend on removed properties |
The system extracts variables from template text by using the regex pattern \{\{(\w+)\}\}:
function extractTemplateVariables(template: string): string[] {
const regex = /\{\{(\w+)\}\}/g;
const variables: string[] = [];
let match;
while ((match = regex.exec(template)) !== null) {
if (!variables.includes(match[1])) {
variables.push(match[1]);
}
}
return variables;
}
The canonicalization process converts PROMPT_TEMPLATE content to YAML format with the following characteristics:
-
Recursively sorted object keys
-
Preserved multiline template strings
-
Consistent quoting style
MODEL_SCHEMA implementation details
The MODEL_SCHEMA artifact type implementation resides in schema-util/util-provider/src/main/java/io/apicurio/registry/types/provider/ModelSchemaArtifactTypeUtilProvider.java, with validators, extractors, and compatibility checkers in schema-util/common/.
interface ModelSchema {
$schema?: string; // Schema URL for identification
modelId: string; // Required: unique model identifier
provider?: string; // Provider name (OpenAI, Anthropic, etc.)
version?: string; // Model version
input?: Record<string, unknown>; // Input schema (JSON Schema format)
output?: Record<string, unknown>; // Output schema (JSON Schema format)
metadata?: Record<string, unknown>; // Custom metadata (capabilities, etc.)
definitions?: Record<string, unknown>; // Reusable schema definitions
// Model Card Toolkit-aligned sections
modelDetails?: ModelDetails; // Comprehensive model metadata
modelParameters?: ModelParameters; // Architecture and data info
quantitativeAnalysis?: QuantitativeAnalysis; // Performance metrics
considerations?: Considerations; // Ethics, limitations, users
// MLflow compatibility
signature?: MLflowSignature; // MLflow model signature
}
interface ModelDetails {
name?: string;
overview?: string;
owners?: Array<{name: string; contact?: string}>;
version?: {name: string; date?: string};
licenses?: Array<{identifier?: string; custom_text?: string}>;
references?: Array<{reference: string}>;
citations?: Array<{style?: string; citation: string}>;
regulatoryRequirements?: string[];
}
interface Considerations {
users?: string[];
useCases?: string[];
limitations?: string[];
tradeoffs?: string[];
ethicalConsiderations?: Array<{name: string; mitigationStrategy?: string}>;
fairnessConsiderations?: Array<{name: string; mitigationStrategy?: string}>;
}
The acceptsContent() function detects MODEL_SCHEMA content by checking the following criteria:
-
Content type is
application/jsonorapplication/x-yaml. -
Schema identifier: the
$schemafield containsmodel-schema. -
Required fields:
modelIdand at least one ofinputoroutputare present.
The validate() function checks the following rules:
-
modelIdmust be a non-empty string. -
At least one of
inputoroutputmust be defined. -
inputandoutputmust be objects (JSON Schema format). -
metadatamust be an object if provided.
| Change type | Allowed | Reason |
|---|---|---|
Add optional input property |
Yes |
Existing consumers can ignore new fields |
Add required input property |
No |
Existing consumers do not provide new required fields |
Remove input property |
No |
Consumers might still send removed properties |
Change input property type |
No |
Existing data might become invalid |
Add output property |
Yes |
Consumers can ignore new fields in response |
Remove output property |
No |
Consumers might depend on removed properties |
Change output property type |
No |
Consumer parsing might break |
Remove input schema entirely |
No |
Contract changes fundamentally |
Remove output schema entirely |
No |
Contract changes fundamentally |
The canonicalization process converts MODEL_SCHEMA content to JSON format with the following characteristics:
-
Recursively sorted object keys
-
Consistent indentation (2 spaces)
-
No trailing whitespace
Prompt rendering service
Apicurio Registry includes a server-side prompt rendering service for PROMPT_TEMPLATE artifacts.
POST /apis/registry/v3/groups/{groupId}/artifacts/{artifactId}/versions/{versionExpression}/render
{
"variables": {
"variableName": "value",
"anotherVariable": 123
}
}
{
"rendered": "The fully rendered template with substituted values",
"groupId": "default",
"artifactId": "my-prompt",
"version": "1.0",
"validationErrors": []
}
The PromptRenderingService class (app/src/main/java/io/apicurio/registry/services/PromptRenderingService.java) includes the following features:
| Feature | Description |
|---|---|
Content parsing |
Parses YAML or JSON prompt templates |
Variable substitution |
Replaces |
Type validation |
Validates that variable values match their defined types |
Required field checking |
Reports missing required variables as validation errors |
Enum validation |
Checks that values are within allowed enum options |
Range validation |
Validates numeric values against minimum/maximum constraints |
When validation fails, the response includes validation errors:
{
"rendered": "Template with {{missing}} placeholder intact",
"groupId": "default",
"artifactId": "my-prompt",
"version": "1.0",
"validationErrors": [
{
"variableName": "missing",
"message": "Required variable is missing"
},
{
"variableName": "count",
"message": "Value 200 is greater than maximum 100"
}
]
}
LLM artifact type customization
You can modify the built-in LLM artifact types or use them as templates for custom types.
| File | Purpose |
|---|---|
|
MODEL_SCHEMA content type detection |
|
MODEL_SCHEMA validation |
|
MODEL_SCHEMA backward compatibility checking |
|
PROMPT_TEMPLATE content type detection |
|
PROMPT_TEMPLATE validation (including template variable cross-checking) |
|
PROMPT_TEMPLATE backward compatibility checking |
|
MODEL_SCHEMA provider wiring |
|
PROMPT_TEMPLATE provider wiring |
