Building Reusable JSON Schemas for SitecoreAI Agents

A SitecoreAI agent can produce a perfectly readable answer and still fail the system that consumes it. A missing field can break an HTML template. A new property can be rejected by an API. A value that changes from an array to a comma-separated string can turn a clean workflow into a debugging session. Natural-language quality matters, but dependable agent automation begins with a dependable contract.

SitecoreAI addresses that contract problem with schemas. In Agentic studio, a schema defines structured JSON output for an agent. Sitecore documents schemas as a way to make output consistent, predictable, validatable, and reusable. Administrators can create reusable schemas in Settings, while workflow builders can also define schemas inside an agent and select them for actions or parameter options. A corresponding Handlebars HTML template can then transform the structured result into a human-readable layout.

The basic example is straightforward: declare an object, add properties, identify required fields, and reject unexpected properties. The architectural challenge appears later. Several agents need the same content metadata. A regional workflow adds localization fields. An API consumer depends on a stable identifier. A template assumes a field is always present. A team edits a shared schema without knowing which workflows consume it. At that point, a schema is no longer a formatting preference. It is a versioned interface.

This guide develops a practical pattern for building reusable JSON Schemas for SitecoreAI agents. It covers the boundary between shared and agent-specific fields, composition with $defs and $ref, validation constraints that guide generation without making it brittle, versioning, workflow and template integration, and a test strategy that treats schemas as production assets. The examples use the JSON Schema vocabulary documented by the JSON Schema project and the structures shown in current SitecoreAI documentation for reusable schemas.

1. Treat the schema as an output contract, not a formatting hint

Isometric flow showing a JSON Schema contract turning varied agent inputs into validated structured output.

The most useful mental model is simple: the prompt explains the work, while the schema defines the shape of the result. A prompt might tell an agent to write a product launch brief for a technical buyer. The schema says that the result must contain a headline, a summary, an audience object, an array of evidence items, and a call to action. Those responsibilities overlap, but they are not interchangeable.

Prompt-only output contracts are weak because they ask a generative model to remember structure as prose. A sentence such as “return a title, a summary, and three recommendations” communicates intent, yet it leaves dozens of questions unanswered. Are recommendations strings or objects? Is the summary optional? Can a recommendation contain evidence? Should empty arrays be emitted? Are additional properties allowed? A formal schema makes those decisions inspectable.

Sitecore’s agent configuration guidance reinforces this separation. The Schemas tab controls structured output, while the Workflow action can define system prompts and message templates. Sitecore also notes that clear field descriptions guide the model toward more consistent results. That means descriptions are not documentation added after the fact. They are part of the generation interface.

Start by identifying the consumers of the output. A single agent result might be consumed by:

Each consumer creates a compatibility requirement. If the template contains {{headline}}, then renaming headline to title is a breaking change even if the new name seems clearer. If an HTTP action addresses {{generate_content.generatedContent.text}}, changing text from a string to an object breaks the downstream request. Sitecore’s workflow-agent example demonstrates this exact kind of variable path: structured content is generated under a schema and later read by another action.

Define invariants before properties

Before writing JSON, list the truths that every valid output must satisfy. For a reusable marketing content artifact, the invariants might be:

Only then should you choose property names and types. This order prevents a common failure mode: building a schema that mirrors the first agent’s output and later discovering that the structure cannot support a second agent.

Here is a small contract that separates universal metadata from content-specific payload:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://schemas.example.com/sitecoreai/content-artifact/v1",
  "title": "SitecoreAI content artifact",
  "type": "object",
  "properties": {
    "schemaVersion": {
      "type": "string",
      "const": "1.0"
    },
    "artifactType": {
      "type": "string",
      "enum": ["article-brief", "social-post", "email"]
    },
    "locale": {
      "type": "string",
      "description": "BCP 47 language tag, such as en-US or fr-CA."
    },
    "content": {
      "type": "object"
    }
  },
  "required": ["schemaVersion", "artifactType", "locale", "content"],
  "additionalProperties": false
}

The $schema declaration identifies the dialect. The JSON Schema documentation explains that a dialect determines the keywords and semantics used during evaluation. Declaring it removes ambiguity for validators and maintainers. The $id gives the schema a stable identifier, which becomes important when other schemas reference it. Sitecore’s editor examples do not require these two keywords for a basic inline schema, so verify the supported vocabulary in your tenant before depending on advanced composition. Even when a UI stores only the inner schema, keeping a canonical source-controlled copy with an explicit dialect is valuable.

My position is intentionally strict: if an agent output feeds another automated step, additionalProperties: false should be the default at every object boundary. Some teams prefer permissive objects because they appear future-proof. In practice, permissiveness hides drift. A model can invent keyTakeaways beside the intended takeaways, validation still passes, and the template silently ignores the new field. Rejecting unknown properties turns that invisible defect into a testable failure.

There is a limitation. JSON Schema can validate representation, not truth. It can require a URL-shaped string, but it cannot prove that the cited page supports a claim. It can require an evidence array, but it cannot establish whether the evidence is relevant. Grounding, source selection, and editorial review still belong in the workflow and system prompt. A schema is a contract for structure, not a substitute for judgment.

2. Design a schema library around stable domain concepts

Isometric modular schema library shared by several SitecoreAI agent outputs.

Reuse works when the shared unit represents a stable concept. It fails when teams create a giant “common” schema containing every field any agent has ever needed. The goal is not maximum deduplication. The goal is a small vocabulary of concepts whose meaning stays consistent across agents.

A useful library often has three layers:

  1. Primitives: constrained strings, identifiers, locale codes, URLs, scores, and timestamps.
  2. Domain components: audience, evidence item, call to action, content metadata, review status, and brand guidance.
  3. Agent outputs: article brief, campaign concept, social post, content audit, or research summary.

The first two layers can be shared. The third layer should remain specific enough to express the agent’s real outcome. A social post and a long-form article may both use the same audience and evidence components, but forcing both into a generic content string discards useful structure.

Choose components by semantic identity

Two fields should share a schema component only if they share meaning, constraints, and change cadence. A summary used in a search card and a summary used as a research abstract may both be strings, but they may have different length limits, audiences, and editorial rules. Reusing a component because the property names match is accidental coupling.

Conversely, differently named fields may represent the same concept. An agent might call a field targetAudience, while another calls it persona. If both contain the same segment identifier, name, needs, and exclusions, the library should define one canonical audience component and the agent schemas should adopt it. Reuse is also a naming discipline.

A compact component library might begin like this:

{
  "$defs": {
    "nonEmptyText": {
      "type": "string",
      "minLength": 1
    },
    "audience": {
      "type": "object",
      "properties": {
        "name": {
          "$ref": "#/$defs/nonEmptyText",
          "description": "Human-readable audience or segment name."
        },
        "needs": {
          "type": "array",
          "items": { "$ref": "#/$defs/nonEmptyText" },
          "minItems": 1,
          "uniqueItems": true
        }
      },
      "required": ["name", "needs"],
      "additionalProperties": false
    },
    "evidenceItem": {
      "type": "object",
      "properties": {
        "claim": { "$ref": "#/$defs/nonEmptyText" },
        "sourceUrl": {
          "type": "string",
          "format": "uri"
        },
        "sourceTitle": { "$ref": "#/$defs/nonEmptyText" }
      },
      "required": ["claim", "sourceUrl", "sourceTitle"],
      "additionalProperties": false
    },
    "callToAction": {
      "type": "object",
      "properties": {
        "label": { "$ref": "#/$defs/nonEmptyText" },
        "destination": {
          "type": "string",
          "format": "uri-reference"
        }
      },
      "required": ["label", "destination"],
      "additionalProperties": false
    }
  }
}

The $defs keyword provides a standardized location for reusable subschemas inside a schema document. The official JSON Schema guide to modular schemas recommends using $ref for an external schema or an internal subschema in $defs. Descriptive component names make a large schema readable at a high level before a maintainer studies each constraint.

Keep agent-specific concerns at the edge

Suppose three SitecoreAI agents produce content:

The evidence item and audience can be shared. The research agent’s confidence model should not be forced into every output. The social agent’s hashtag constraints should stay local. The article outline deserves its own structure because later workflow steps may iterate over sections.

ConceptLibrary layerReason
Non-empty textPrimitiveSame representation across many components.
AudienceDomain componentStable marketing concept consumed by several agents.
Evidence itemDomain componentCommon provenance shape for research-backed output.
Article sectionAgent output componentSpecific to long-form planning and rendering.
Hashtag listAgent output componentChannel-specific limits and semantics.

A schema library also needs ownership. Add metadata outside the validation object or in repository documentation: owner, status, consumers, version, change log, and review date. Sitecore lets administrators add a name, description, and tags to reusable schemas. Use those fields as operational metadata, not decoration. A description should say what the schema represents, who should use it, and which compatibility expectations apply. Tags can group schemas by domain, lifecycle, or team.

Prefer explicit duplication over false abstraction

This is a justified preference, not an absolute law: I prefer duplicating a ten-line channel-specific subschema to creating a vaguely named abstraction such as genericContentBlock. Small duplication is visible and easy to remove when a real shared concept emerges. A premature abstraction spreads semantic confusion across every consumer.

The practical test is substitution. If component A can replace component B without changing what the field means to the model, validator, template, and downstream system, they are candidates for reuse. If only their JSON shape matches, keep them separate.

3. Compose schemas with $defs, $ref, and deliberate boundaries

Isometric schema components connected by references and composition gates into one validated artifact.

JSON Schema supports both local and external reuse. Local reuse places components under $defs and references them with JSON Pointers such as #/$defs/audience. External reuse assigns schemas stable identifiers and references those identifiers from other documents. The right choice depends on how SitecoreAI stores and resolves schemas in your environment.

Begin with local composition because it is self-contained. A single schema copied into SitecoreAI Advanced mode carries all its definitions. There is no network resolver, registry availability, or URI mapping to configure. Once multiple schemas need the same component, keep canonical external files in source control and bundle them into self-contained artifacts during deployment if the target editor does not resolve external references.

Consider an article brief schema built from reusable local components:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://schemas.example.com/sitecoreai/article-brief/v1",
  "type": "object",
  "properties": {
    "schemaVersion": { "const": "1.0" },
    "headline": {
      "type": "string",
      "minLength": 10,
      "maxLength": 100,
      "description": "Specific working headline. Do not use clickbait."
    },
    "audience": { "$ref": "#/$defs/audience" },
    "sections": {
      "type": "array",
      "items": { "$ref": "#/$defs/articleSection" },
      "minItems": 3,
      "maxItems": 12
    },
    "evidence": {
      "type": "array",
      "items": { "$ref": "#/$defs/evidenceItem" },
      "minItems": 1
    },
    "callToAction": { "$ref": "#/$defs/callToAction" }
  },
  "required": [
    "schemaVersion",
    "headline",
    "audience",
    "sections",
    "evidence",
    "callToAction"
  ],
  "additionalProperties": false,
  "$defs": {
    "audience": {
      "type": "object",
      "properties": {
        "name": { "type": "string", "minLength": 1 },
        "problem": { "type": "string", "minLength": 1 }
      },
      "required": ["name", "problem"],
      "additionalProperties": false
    },
    "articleSection": {
      "type": "object",
      "properties": {
        "heading": { "type": "string", "minLength": 1 },
        "purpose": { "type": "string", "minLength": 1 },
        "keyPoints": {
          "type": "array",
          "items": { "type": "string", "minLength": 1 },
          "minItems": 2,
          "uniqueItems": true
        }
      },
      "required": ["heading", "purpose", "keyPoints"],
      "additionalProperties": false
    },
    "evidenceItem": {
      "type": "object",
      "properties": {
        "claim": { "type": "string", "minLength": 1 },
        "sourceUrl": { "type": "string", "format": "uri" }
      },
      "required": ["claim", "sourceUrl"],
      "additionalProperties": false
    },
    "callToAction": {
      "type": "object",
      "properties": {
        "label": { "type": "string", "minLength": 1 },
        "destination": { "type": "string", "format": "uri-reference" }
      },
      "required": ["label", "destination"],
      "additionalProperties": false
    }
  }
}

This schema makes the reusable boundaries obvious. A reader can understand the top-level output without first reading the component internals. The nested objects are closed independently, so extra fields cannot slip into audience or an individual section.

Use composition keywords for real alternatives

JSON Schema includes allOf, anyOf, and oneOf. These are powerful, but they can make model-facing schemas difficult to reason about. Use them when the domain truly contains alternatives, not merely to mimic inheritance.

For example, an evidence item might reference either a web source or an internal Sitecore artifact:

{
  "oneOf": [
    {
      "type": "object",
      "properties": {
        "kind": { "const": "web" },
        "url": { "type": "string", "format": "uri" },
        "title": { "type": "string", "minLength": 1 }
      },
      "required": ["kind", "url", "title"],
      "additionalProperties": false
    },
    {
      "type": "object",
      "properties": {
        "kind": { "const": "artifact" },
        "artifactId": { "type": "string", "minLength": 1 },
        "title": { "type": "string", "minLength": 1 }
      },
      "required": ["kind", "artifactId", "title"],
      "additionalProperties": false
    }
  ]
}

The discriminator-like kind field makes each branch unambiguous. Without it, a generated object may accidentally satisfy both branches or neither. oneOf means exactly one subschema must validate. anyOf means one or more may validate. That distinction matters when branches overlap.

Avoid large allOf hierarchies combined with additionalProperties: false unless your validator’s behavior is well understood. In older drafts, additionalProperties only sees sibling properties, which can produce surprising failures when schemas are extended through composition. Draft 2020-12 includes unevaluatedProperties for more expressive composition, but support varies across tooling. A flatter bundled schema is often safer for an agent-output contract.

Do not assume every JSON Schema keyword is supported identically

Sitecore documents that schemas use JSON Schema format and shows practical keywords such as type, properties, required, items, maxLength, maxItems, and additionalProperties. That is a strong baseline. It does not automatically prove that every keyword in every JSON Schema dialect is accepted by every model provider or SitecoreAI execution path.

Test the exact vocabulary you plan to deploy. Start with a minimal schema containing the keyword, run the agent, and validate the returned instance with an independent validator. If $ref is not resolved by the target path, bundle the referenced component inline. If a format is treated as annotation rather than assertion, add explicit workflow validation for the requirement. This admitted limitation is why a schema build step matters: the authoring form and the deployed form do not need to be identical.

A good repository layout makes that distinction explicit:

schemas/
  components/
    audience.schema.json
    evidence-item.schema.json
    call-to-action.schema.json
  agents/
    article-brief.schema.json
    social-post.schema.json
    research-summary.schema.json
  bundled/
    article-brief.sitecore.json
    social-post.sitecore.json
  fixtures/
    valid/
    invalid/
  manifest.json

Canonical components live under components. Agent contracts reference them. A bundling step produces self-contained SitecoreAI artifacts. Fixtures prove behavior. The manifest records versions and consumers. This structure scales more safely than copying schemas between agent editors by hand.

4. Add constraints that improve generation without making it brittle

Isometric validation pipeline converting varied inputs into consistent structured output.

A reusable schema should be strict about structure and selective about content. Overly loose schemas permit drift. Overly strict schemas cause valid generations to fail for reasons that add little business value. The design task is to identify which constraints protect a consumer or encode a genuine rule.

Use required for contractual presence

A field should be required when every consumer needs it or when its absence changes the meaning of the object. Do not mark a field required merely because it is usually desirable. If an evidence item can legitimately lack a publication date, requiring a date encourages fabricated values or validation failures.

Optionality also needs a representation policy. Choose one of these approaches and apply it consistently:

Do not mix omitted, null, and empty-string states without a consumer need. Templates and APIs otherwise need three branches for the same absence. For agent-generated content, I prefer omission for optional scalar fields and an empty array for collections that templates iterate over. The reason is operational: Handlebars conditionals and loops can handle those states predictably, while empty strings often look like valid content.

Constrain strings where the limit has a consumer

Use minLength to prevent empty output. Use maxLength when a channel, UI, or API has a real limit. Sitecore’s X post example uses maxLength: 280, and its description tells the model that the field contains one standalone post. The numeric constraint protects the platform boundary; the description explains the editorial intent.

Descriptions should answer four questions:

  1. What does the field mean?
  2. What should it contain?
  3. What should it exclude?
  4. How will it be consumed?

Compare these two definitions:

{
  "summary": {
    "type": "string"
  }
}
{
  "summary": {
    "type": "string",
    "minLength": 80,
    "maxLength": 320,
    "description": "A self-contained executive summary for a review card. State the decision and primary reason. Do not repeat the title or include Markdown."
  }
}

The second definition guides both validation and generation. The range must still reflect a real display requirement. Arbitrary precision creates unnecessary retries.

Use enums for controlled vocabularies, not open language

An enum is appropriate for workflow states, content types, risk levels, and other values whose consumers branch on exact strings. It is a poor fit for topics, audience names, and natural-language categories that evolve frequently.

{
  "reviewStatus": {
    "type": "string",
    "enum": ["draft", "needs-review", "approved", "rejected"],
    "description": "Workflow state. Select exactly one allowed value."
  }
}

Keep machine values stable and map them to display labels in the template or consuming application. Changing needs-review to review_required is a breaking interface change even if the business meaning stays the same.

Constrain arrays to protect downstream behavior

Arrays deserve more attention than they usually receive. Define items. Set minItems when at least one item is meaningful. Set maxItems when a template, channel, or human review process has a limit. Use uniqueItems: true for primitive values such as hashtags, but remember that semantic duplicates can still differ as strings.

For arrays of objects, include stable identifiers only when a later step needs to address individual items. Do not ask the model to invent globally unique IDs without defining how uniqueness is guaranteed. A local sequence key such as section-1 may be enough for template anchors, but its stability across regeneration must be tested.

Close nested objects

Setting additionalProperties: false only at the root does not close nested objects. Each object needs its own rule. This is one of the most common errors in hand-authored schemas:

{
  "type": "object",
  "properties": {
    "audience": {
      "type": "object",
      "properties": {
        "name": { "type": "string" }
      },
      "required": ["name"]
    }
  },
  "required": ["audience"],
  "additionalProperties": false
}

The root rejects unknown fields, but audience still permits them. A model could return audience.segmentName, audience.notes, or any other invented property. Add additionalProperties: false inside the nested object or reference a closed component.

Validate semantics outside the schema when necessary

Some rules do not belong in JSON Schema. “Every claim must be supported by one source” requires cross-item analysis. “The call to action must match the campaign objective” is contextual. “The French output must not contain untranslated English copy” is linguistic. Implement these checks as a later workflow action, a review agent, or application code.

A useful boundary is this: JSON Schema validates shape and local constraints; workflow validators enforce cross-field and external rules; human review handles editorial judgment and risk. Mixing all three into one enormous schema makes the contract hard to generate and harder to maintain.

5. Version schemas like APIs

Isometric versioning lanes separating compatible schema updates from breaking changes.

A reusable schema has consumers, so it needs a compatibility policy. Sitecore lets administrators update schemas, but the ability to edit a shared asset does not mean every edit is safe. Before changing one, identify all agents, parameter options, workflow actions, templates, exports, and external integrations that depend on it.

Classify changes by consumer impact

A practical policy can use semantic-versioning ideas even if the Sitecore schema name stores only a major version:

With additionalProperties: false, adding an optional property changes the accepted output set and may still affect consumers that perform their own strict validation. Treat “minor” as a hypothesis to verify, not an automatic label.

ChangeLikely impactRecommended action
Add a field descriptionGeneration behavior may improve; shape unchangedPatch and regression-test outputs
Add optional subtitleOld templates usually ignore it; strict consumers may reject itMinor only after consumer tests
Make subtitle requiredOld instances become invalidMajor version
Rename headline to titleTemplate and variable paths breakMajor version plus migration
Remove enum valuePreviously valid instances failMajor version
Lower maxLengthPreviously valid content failsMajor unless proven safe

Expose a version in the instance

Give the output a schemaVersion field with a const value. This may feel redundant because the agent already points to a schema. It becomes useful when artifacts are exported, saved, sent to APIs, compared over time, or processed outside SitecoreAI.

{
  "schemaVersion": {
    "type": "string",
    "const": "2.0",
    "description": "Version of the output contract."
  }
}

Use a major version in URLs, schema IDs, and saved schema names, such as Article Brief v2. Keep minor and patch history in source control and release notes. This avoids forcing workflow builders to choose among many nearly identical assets while still preserving an audit trail.

Run old and new versions side by side

Do not edit a widely consumed v1 schema into a breaking v2 shape. Create a new reusable schema, update one agent or workflow, test it, migrate its template and downstream actions, and then move other consumers. Retire v1 only when usage reaches zero.

A migration checklist should include:

  1. Clone the schema under a new major-version name.
  2. Update the instance schemaVersion.
  3. Update the matching HTML template.
  4. Update workflow variable paths and HTTP bodies.
  5. Run valid and invalid fixtures against both versions.
  6. Execute representative agent runs.
  7. Compare rendered output and downstream requests.
  8. Record migrated consumers in the manifest.
  9. Archive the old schema only after confirmation.

If a downstream system must accept both versions during migration, add an adapter step. Convert v1 output into the v2 internal model or route by schemaVersion. Do not burden every consumer with indefinite support for every historic shape.

Descriptions can be behavior changes

Schema descriptions influence generation, so changing one can alter output even when validation remains identical. A description edit from “short summary” to “state the recommendation and rationale in 2–3 sentences” is technically a patch to structure but behaviorally significant. Regression tests should compare not only validity but content characteristics that matter to the business.

This is another reason to keep canonical schemas in source control. Sitecore’s UI is where a reusable schema is configured, but Git is where teams can review diffs, link changes to decisions, run tests, and recover prior versions. Treat the UI copy as a deployed artifact.

6. Integrate schemas with SitecoreAI workflows, templates, and APIs

Isometric SitecoreAI workflow connecting prompts, schema validation, templates, and an API destination.

A schema delivers value only when the rest of the workflow respects it. SitecoreAI allows schemas to be selected for actions and parameter options, and HTML templates can map structured data into layouts through Handlebars placeholders. Workflow actions can also pass generated variables into later steps, save artifacts, or send fields to an HTTP endpoint.

Align prompt, schema, and template

These three assets form one interface:

Every field referenced by the template must exist in the schema. Every required schema field should be explained by either its description or the prompt. The prompt should not request output that has nowhere to go. Misalignment creates predictable defects: omitted content, unused fields, duplicated instructions, and empty template sections.

For an article brief, a template could render the same structured output consistently:

<article class="article-brief">
  <h1>{{headline}}</h1>
  <p><strong>Audience:</strong> {{audience.name}}</p>
  <p>{{audience.problem}}</p>

  <ol>
    {{#each sections}}
      <li>
        <h2>{{heading}}</h2>
        <p>{{purpose}}</p>
        <ul>
          {{#each keyPoints}}
            <li>{{this}}</li>
          {{/each}}
        </ul>
      </li>
    {{/each}}
  </ol>

  <a href="{{callToAction.destination}}">
    {{callToAction.label}}
  </a>
</article>

Test templates with the smallest valid instance, the largest expected instance, empty optional collections, long allowed strings, and characters that require HTML escaping. A schema-valid instance can still produce a broken or unsafe layout if the template assumes more than the contract guarantees.

Use workflow variables as typed paths

Although workflow variable references appear as template strings, treat them like typed property paths. Sitecore’s workflow documentation shows structured output being referenced in later action configuration. A path such as {{generate_content.generatedContent.text}} depends on both the producing action variable and the schema property.

Document these paths in the consumer manifest:

{
  "schema": "article-brief",
  "version": "2.0",
  "consumers": [
    {
      "agent": "campaign-planner",
      "action": "render_brief",
      "template": "article-brief-v2"
    },
    {
      "agent": "campaign-planner",
      "action": "send_to_api",
      "paths": [
        "generatedContent.headline",
        "generatedContent.sections",
        "generatedContent.schemaVersion"
      ]
    }
  ]
}

This artifact does not need to be imported into SitecoreAI. It exists to make impact analysis possible. A pull request that changes headline can immediately identify the template and HTTP action that require migration.

Do not send the entire output when an API needs three fields

Map the smallest stable payload at the integration boundary. If an API needs a headline, body, and locale, construct that request explicitly. Passing the entire agent output couples the external system to every optional field and future schema decision.

{
  "title": "{{generate_content.generatedContent.headline}}",
  "locale": "{{generate_content.generatedContent.locale}}",
  "body": "{{generate_content.generatedContent.body}}"
}

Validate again at the boundary. The agent schema may accept a relative URI for a template link, while an external API may require an absolute HTTPS URL. The reusable domain schema and the transport contract have different responsibilities.

Apply reusable schemas through a controlled deployment process

Sitecore documents two useful scopes: administrators can create reusable schemas under Agentic studio Settings, and builders can define schemas within workflow-agent configuration. Use global reusable schemas for stable organization-wide contracts. Use local schemas for experimentation, a single workflow, or a contract that is not ready for shared governance.

A promotion path can be:

  1. Prototype the schema locally inside a development agent.
  2. Collect representative outputs and failure cases.
  3. Extract stable components into the source-controlled library.
  4. Run automated validation and template tests.
  5. Create the reusable schema in a non-production SitecoreAI environment.
  6. Update one consumer and complete end-to-end tests.
  7. Promote the schema and template with release notes.
  8. Track all consumers before allowing shared edits.

Sitecore also supports exporting and importing agent JSON. That is useful for inspecting how schemas, templates, and action variables fit together, but exported configuration should still be reviewed for environment-specific identifiers and secrets before promotion.

Plan for model variance

A valid schema narrows output, but models and execution paths can behave differently. Keep the schema comprehensible. Prefer shallow objects, clear field descriptions, explicit discriminators, and a modest number of alternatives. A formally elegant schema that relies on deep recursion and overlapping oneOf branches may be harder for generation than a slightly more repetitive flat contract.

When a generation fails validation, log the schema version, agent version, model, prompt inputs, raw structured output when permitted, validation errors, and retry outcome. Without that context, teams tend to loosen the schema after one failure and lose the constraint that protected a consumer.

7. Test and govern the schema library as production code

Isometric testing and governance pipeline for a shared JSON Schema library.

A schema that opens in an editor is not necessarily correct. It may contain an invalid reference, accept an unintended object, reject a valid migration payload, or disagree with a template. Testing should cover the schema itself, instances, generation behavior, and consumers.

Test four layers

  1. Meta-schema validation: confirm that each schema is valid for its declared dialect.
  2. Instance tests: validate positive fixtures and prove that negative fixtures fail for the expected reason.
  3. Contract tests: verify that templates and integration mappings use properties that exist with compatible types.
  4. Agent tests: run representative prompts and measure valid-output rate, retry rate, and content-quality checks.

The first layer catches authoring errors. The second proves the business constraints. The third protects consumers. The fourth reveals whether the schema is practical for generation.

Write negative fixtures deliberately

Positive fixtures are easy. The real value comes from instances that must fail:

Example valid fixture:

{
  "schemaVersion": "1.0",
  "headline": "A Practical Contract for Agent-Generated Article Briefs",
  "audience": {
    "name": "Content operations leaders",
    "problem": "Agent outputs vary across teams and downstream workflows."
  },
  "sections": [
    {
      "heading": "Define the contract",
      "purpose": "Explain the consumer boundary.",
      "keyPoints": [
        "Identify required fields",
        "Close object boundaries"
      ]
    },
    {
      "heading": "Compose shared components",
      "purpose": "Reuse stable domain concepts.",
      "keyPoints": [
        "Use local definitions",
        "Bundle external references"
      ]
    },
    {
      "heading": "Test the result",
      "purpose": "Protect templates and APIs.",
      "keyPoints": [
        "Add negative fixtures",
        "Run integration checks"
      ]
    }
  ],
  "evidence": [
    {
      "claim": "SitecoreAI schemas define predictable structured output.",
      "sourceUrl": "https://doc.sitecore.com/sai/en/users/sitecoreai/sites/overview-of-agent-configuration-tabs.html"
    }
  ],
  "callToAction": {
    "label": "Review the schema",
    "destination": "/schemas/article-brief"
  }
}

Example negative fixture:

{
  "schemaVersion": "1.0",
  "headline": "",
  "audience": {
    "name": "Content team",
    "problem": "Inconsistent output",
    "notes": "This property is not allowed."
  },
  "sections": [],
  "evidence": [],
  "callToAction": {
    "label": "Continue",
    "destination": "/next"
  }
}

This fixture should fail because the headline is too short, audience.notes is unknown, and required arrays do not meet minimum size. Assert those errors. If the validator reports only a generic failure, improve test diagnostics before the library grows.

Measure generation behavior, not just validity

For each representative prompt set, record at least:

Do not copy an industry benchmark into your acceptance criteria. Establish a baseline in your own SitecoreAI environment, with your agents, prompts, models, and schemas. Then require that a schema change does not regress the metrics that matter. An observed metric is valuable only when the measurement conditions are recorded.

Add a lightweight governance gate

A shared-schema change should answer these questions before deployment:

For high-impact contracts, require review from both the domain owner and an implementation owner. The domain reviewer catches semantic mistakes. The implementation reviewer catches validator, template, and integration problems.

A practical build checklist

  1. Inventory every consumer before designing the contract.
  2. Write invariants in plain language.
  3. Separate primitives, domain components, and agent outputs.
  4. Use stable names and precise descriptions.
  5. Declare required fields only when absence is invalid.
  6. Close every object boundary intentionally.
  7. Use $defs and $ref for genuine shared concepts.
  8. Bundle schemas when the target execution path cannot resolve external references.
  9. Add a schema version to the output instance.
  10. Create valid and invalid fixtures.
  11. Test the matching Handlebars template and workflow paths.
  12. Deploy a breaking change as a new major version.
  13. Measure real agent runs before broad adoption.
  14. Record ownership, consumers, and change history.

Diagnose failures before loosening the contract

When an agent returns invalid output, classify the failure before editing the schema. Most incidents fall into one of five groups. A structural failure uses the wrong type or omits a required field. A vocabulary failure returns a value outside an enum. A capacity failure exceeds a length or item limit. A composition failure cannot select a valid alternative. A consumer failure passes schema validation but breaks a template or integration. Each category suggests a different response.

Structural failures often point to unclear field descriptions, excessive nesting, or a prompt that contradicts the schema. Improve the description and remove contradictory instructions before making the field optional. Vocabulary failures may reveal that the enum is incomplete, but they may also show that the model needs the allowed values stated in the prompt. Capacity failures require a business decision: either the limit protects a real boundary or it does not. If it protects a channel limit, keep it and revise the generation instruction. If it was an arbitrary preference, remove it.

Composition failures deserve special care. Capture the instance and determine which branches validated. If no branch matches, inspect required fields and discriminators. If several branches match under oneOf, make their discriminators mutually exclusive. Do not replace oneOf with anyOf merely to make a test green; that changes the contract from “exactly one representation” to “one or more representations.”

Consumer failures prove that JSON validity is only one part of the system. A template may assume an optional array always has an item. An HTTP action may interpolate an object where it expects a string. A saved artifact may contain a new version that an external processor cannot recognize. Add a contract test for the failing boundary and then decide whether the schema, template, adapter, or consumer is wrong.

Retries should be bounded and observable. A retry instruction can return the validator’s relevant errors to the generation step, but avoid exposing internal data or enormous error dumps. Record whether the retry succeeded. If the same property repeatedly fails, treat that as a design signal. A schema that validates only after several retries may be formally correct and operationally poor.

Decide when a schema should become reusable

Not every agent schema belongs in the shared library. Promote a local schema when at least two consumers need the same semantic contract, the domain owner can define its meaning, and the team is willing to support compatibility. A schema used by one experimental agent should usually remain local. Global reuse adds coordination cost, and that cost is justified only when the component is stable enough to save more work than it creates.

Use three questions. First, would another consumer interpret every property the same way? Second, can the owner describe which changes are breaking? Third, can the team test the consumers before release? If any answer is no, keep the schema local and learn from real runs. Reuse is a lifecycle stage, not a compliment paid to a design.

Frequently asked questions

What makes a JSON Schema reusable in SitecoreAI? A reusable schema represents a stable output contract that more than one agent, parameter option, template, or workflow can consume without redefining its meaning. SitecoreAI lets administrators save these schemas in Agentic studio Settings and select them across agent configuration. Technical reuse comes from consistent names, constraints, descriptions, and versioning; saving an object in a shared list does not make a weak design reusable.

Should every shared schema use $defs and $ref? No. Use them when they make component boundaries clearer and the target execution path supports them. For small contracts, an explicit inline schema may be easier to read. For environments that do not resolve external references, author modular source files and bundle them into one self-contained schema for deployment.

Should additionalProperties be false? For automated outputs, usually yes. Closing objects detects misspelled and invented fields before they reach templates or APIs. Apply the rule at each nested object, not only at the root. Leave an object open only when extension data is an intentional part of the contract, and isolate that extensibility under a named property rather than making the whole output permissive.

How should optional values be represented? Choose a consistent policy. Omit optional scalar properties when no value exists, use empty arrays for repeatable collections that templates iterate, and allow null only when null has a distinct meaning or a consumer requires it. Avoid empty strings as a generic absence marker because they often pass superficial checks while carrying no content.

How do reusable schemas interact with HTML templates? The schema defines data; the Handlebars template defines presentation. Every template path should correspond to a schema property, and template tests should cover optional fields, array bounds, maximum string lengths, escaping, and both the smallest and largest valid instances. Version the template with the schema when property paths or types change.

Can a schema prevent hallucinated facts? No. It can require an evidence object and a source URL, but it cannot prove that a claim is true or supported. Use grounded prompts, trusted knowledge sources, review actions, application checks, and human approval for factual quality. The schema makes provenance representable and required; the workflow verifies it.

When is a schema change breaking? A change is breaking when an existing valid instance becomes invalid or an existing consumer can no longer read the output correctly. Renames, removals, type changes, new required fields, enum-value removals, and tighter limits are common breaking changes. Create a new major version and migrate consumers rather than editing the shared contract in place.

What is the first schema a team should standardize? Choose an output already consumed by more than one workflow and whose inconsistencies create visible rework. Article briefs, research summaries, content-audit findings, and campaign concepts are good candidates when they feed templates or later actions. Avoid starting with a universal content model. A narrow contract with real consumers produces faster feedback and clearer ownership.

The durable pattern

Reusable JSON Schemas for SitecoreAI agents work best as a small product, not a collection of snippets. The product has users: agent builders, template authors, integration developers, reviewers, and downstream systems. It has releases, compatibility rules, tests, documentation, and owners.

The core design is straightforward. Put stable domain concepts in reusable components. Keep channel and agent concerns at the edge. Close object boundaries. Use descriptions to guide generation. Compose only where the target tooling supports it, and bundle when necessary. Version breaking changes instead of editing contracts in place. Test valid output, invalid output, templates, workflow paths, and actual agent runs.

SitecoreAI provides the practical surfaces for this approach: reusable schemas in Settings, agent-level schemas, workflow action selection, structured variables, HTML templates, and exported agent configuration. JSON Schema supplies the contract language. The engineering discipline around those tools determines whether reuse reduces work or merely spreads a fragile design farther.

Start with one high-value output used by more than one workflow. Identify its consumers, extract two or three stable components, create a closed schema, pair it with fixtures and a template test, and publish it as version 1. That narrow implementation will teach more than a broad “enterprise schema” initiative. Reuse should be earned by stable meaning.

For reference, consult Sitecore’s overview of agent configuration tabs, its guide to creating reusable schemas, the official JSON Schema composition guide, and the JSON Schema dialect documentation.