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.

Native Java artifact type system

The LLM artifact types consist of the following components:

Table 1. Architecture components
Component Description

Java implementation

Source files in schema-util/common/src/main/java/io/apicurio/registry/, including accepters, validators, compatibility checkers, reference finders, dereferencers, content extractors, and canonicalizers for each type.

Provider wiring

ModelSchemaArtifactTypeUtilProvider and PromptTemplateArtifactTypeUtilProvider in schema-util/util-provider/ wire each type’s implementations together and register them as standard artifact types.

Prompt rendering service

Java service (PromptRenderingService) for server-side template rendering of PROMPT_TEMPLATE artifacts.

Handler functions

Each artifact type includes the following handler functions (as Java classes in schema-util/common/):

Table 2. Artifact type handler functions
Function Purpose

acceptsContent()

Checks whether content matches this artifact type based on structure and content type.

validate()

Validates content structure, required fields, and constraint violations.

testCompatibility()

Checks backward compatibility between existing and proposed versions.

canonicalize()

Normalizes content for consistent hashing and comparison.

findExternalReferences()

Identifies $ref references to external schemas.

dereference()

Resolves $ref references by substituting actual content.

rewriteReferences()

Rewrites $ref paths to use registry URLs.

validateReferences()

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.

Schema locations

You can find the JSON Schemas in app/src/main/resources/schemas/:

Table 3. JSON Schema files
File Description

prompt-template-v1.schema.json

Schema for PROMPT_TEMPLATE artifacts, aligned with Microsoft Prompty

model-schema-v1.schema.json

Schema for MODEL_SCHEMA artifacts, aligned with Google Model Card Toolkit

PROMPT_TEMPLATE schema - Prompty alignment

The PROMPT_TEMPLATE schema is aligned with the Microsoft Prompty specification for interoperability with the Azure AI ecosystem.

Table 4. Prompty field mappings
Apicurio field Prompty field Notes

templateId

name

Primary identifier

variables

inputs

Both names supported

outputSchema

outputs

Both names supported

template

Body content

{{variable}} syntax

model

model

Model configuration

authors

authors

Contributors list

tags

tags

Categorization

PROMPT_TEMPLATE with Prompty-aligned fields
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
MODEL_SCHEMA schema - Model Card Toolkit alignment

The MODEL_SCHEMA is aligned with the Google Model Card Toolkit for governance and compliance use cases.

Table 5. Model Card field mappings
Apicurio field Model Card field Notes

modelId

model_details.name

Model identifier

provider

model_details.owners

Model provider

version

model_details.version

Version info

input

model_parameters.input_format

I/O schema

output

model_parameters.output_format

I/O schema

modelDetails

model_details

Full metadata

quantitativeAnalysis

quantitative_analysis

Metrics

considerations

considerations

Ethics, limitations

MODEL_SCHEMA with Model Card-aligned sections
{
  "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.

MCP extension in PROMPT_TEMPLATE

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
Table 6. MCP configuration fields
Field Required Description

enabled

No

Set to true to make this prompt available through MCP (default: false)

name

No

MCP prompt name (defaults to templateId)

description

No

MCP prompt description (defaults to template description)

arguments

No

MCP arguments (auto-derived from variables if not specified)

MCP server module

The mcp/ module contains an MCP Server for registry prompts:

Table 7. MCP server components
Component Description

PromptTemplateMCPServer.java

MCP Server that makes prompt templates available as MCP prompts

PromptTemplateConverter.java

Parses and renders prompt templates

MCP tools and prompts

The MCP Server includes the following tools and prompts:

Table 8. MCP tools
Tool Description

list_mcp_prompts

List all MCP-enabled prompt templates in the registry

get_mcp_prompt

Get and render an MCP-enabled prompt with arguments

render_prompt_template

Render any prompt template (MCP-enabled or not)

Table 9. MCP prompts
Prompt Description

render_registry_prompt

Interactive prompt for rendering templates from the registry

MCP server usage

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.

Table 10. MCP architecture data flow
Layer Description

Apicurio Registry (PROMPT_TEMPLATE artifacts)

Stores prompt templates with mcp.enabled: true in the MCP configuration section.

MCP server module

Connects Apicurio Registry to AI agents by using the MCP protocol. Provides the following tools:

  • list_mcp_prompts(): lists MCP-enabled templates

  • get_mcp_prompt(): renders a template with arguments

  • render_prompt_template(): renders any template

AI agent or LLM (such as Claude or ChatGPT)

Communicates with the MCP server by using the MCP protocol:

  • prompts/list: discovers available prompts

  • prompts/get: retrieves prompt content with arguments

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/.

PROMPT_TEMPLATE schema interface (Prompty-aligned)
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
}
Content detection

The acceptsContent() function detects PROMPT_TEMPLATE content by checking the following criteria:

  • Content type is application/json, application/x-yaml, or text/x-prompt-template.

  • Schema identifier: the $schema field contains prompt-template.

  • Required fields: both templateId and template fields are present.

Validation rules

The validate() function checks the following rules:

  • templateId must be a non-empty string.

  • template must be a non-empty string.

  • All {{variable}} placeholders in the template must have corresponding definitions in variables.

  • Variable types must be valid: string, integer, number, boolean, array, object.

  • Numeric constraints (minimum, maximum) must be numbers.

  • Enum values must be arrays.

Table 11. PROMPT_TEMPLATE backward compatibility
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

Template variable extraction

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;
}
Canonicalization

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/.

MODEL_SCHEMA schema interface (Model Card Toolkit-aligned)
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}>;
}
Content detection

The acceptsContent() function detects MODEL_SCHEMA content by checking the following criteria:

  • Content type is application/json or application/x-yaml.

  • Schema identifier: the $schema field contains model-schema.

  • Required fields: modelId and at least one of input or output are present.

Validation rules

The validate() function checks the following rules:

  • modelId must be a non-empty string.

  • At least one of input or output must be defined.

  • input and output must be objects (JSON Schema format).

  • metadata must be an object if provided.

Table 12. MODEL_SCHEMA backward compatibility
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

Canonicalization

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.

REST API endpoint
POST /apis/registry/v3/groups/{groupId}/artifacts/{artifactId}/versions/{versionExpression}/render
Request body
{
  "variables": {
    "variableName": "value",
    "anotherVariable": 123
  }
}
Response body
{
  "rendered": "The fully rendered template with substituted values",
  "groupId": "default",
  "artifactId": "my-prompt",
  "version": "1.0",
  "validationErrors": []
}
Java implementation

The PromptRenderingService class (app/src/main/java/io/apicurio/registry/services/PromptRenderingService.java) includes the following features:

Table 13. Rendering service features
Feature Description

Content parsing

Parses YAML or JSON prompt templates

Variable substitution

Replaces {{variable}} placeholders with provided values

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

Validation error response

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.

Table 14. Source files
File Purpose

schema-util/common/…​/content/ModelSchemaContentAccepter.java

MODEL_SCHEMA content type detection

schema-util/common/…​/rules/validity/ModelSchemaContentValidator.java

MODEL_SCHEMA validation

schema-util/common/…​/rules/compatibility/ModelSchemaCompatibilityChecker.java

MODEL_SCHEMA backward compatibility checking

schema-util/common/…​/content/PromptTemplateContentAccepter.java

PROMPT_TEMPLATE content type detection

schema-util/common/…​/rules/validity/PromptTemplateContentValidator.java

PROMPT_TEMPLATE validation (including template variable cross-checking)

schema-util/common/…​/rules/compatibility/PromptTemplateCompatibilityChecker.java

PROMPT_TEMPLATE backward compatibility checking

schema-util/util-provider/…​/ModelSchemaArtifactTypeUtilProvider.java

MODEL_SCHEMA provider wiring

schema-util/util-provider/…​/PromptTemplateArtifactTypeUtilProvider.java

PROMPT_TEMPLATE provider wiring