Thank you for contributing to the spec! This guide covers the conventions you must follow so that every schema remains machine-readable, internally consistent, and backward-compatible.
- Pre-requisites
- Repository structure recap
- Adding a new schema
- Modifying an existing schema
- URN naming guide
- Updating the API specs
- Writing examples
- Pull-request checklist
- Breaking vs additive changes
# Validate schemas and examples with AJV (Node ≥ 18)
npm install -g ajv-cli
# Validate OpenAPI spec
npm install -g @stoplight/spectral-cli
# Validate AsyncAPI spec
npm install -g @asyncapi/clischemas/ JSON Schema (draft 2020-12) — one file per type
examples/ One conforming example JSON per schema type
openapi.yaml Metadata-plane REST API
openapi.agent-plane.patch.yaml Agent-plane additive REST patch
asyncapi.yaml Metadata-plane event channels
asyncapi.agent-plane.patch.yaml Agent-plane additive event channels
semantic/ JSON-LD context + Hydra API documentation
docs/adr/ Architecture Decision Records
Save it to schemas/<TypeName>.json. The filename must be PascalCase and match the title field exactly.
Required top-level fields:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://schemas.srcos.ai/v2/<TypeName>.json",
"title": "<TypeName>",
"description": "One-sentence description of what this object represents.",
"type": "object",
"additionalProperties": false,
"required": ["id", "type", "specVersion", ...],
"properties": {
"id": {
"type": "string",
"pattern": "^urn:srcos:<type-slug>:",
"description": "Stable URN identifier. Pattern: urn:srcos:<type-slug>:<local-id>"
},
"type": {
"const": "<TypeName>",
"description": "Discriminator constant — always \"<TypeName>\"."
},
"specVersion": {
"type": "string",
"description": "Spec version of this document, e.g. \"2.0.0\"."
}
}
}Rules:
- Every property must have a
"description"field (or a$refthat resolves to a described type). "additionalProperties": falseis required on every object.- Nullable fields use
"type": ["<base-type>", "null"]. - Timestamps use
"type": "string", "format": "date-time". - All cross-object references use a URN
"pattern"constraint that matches the target type's URN prefix.
Update schemas/README.md — add a row to the correct family table.
Create examples/<typename>.json (lowercase filename). The example must validate against the schema:
ajv validate -s schemas/<TypeName>.json -d examples/<typename>.jsonAdd a POST /v2/<plural-path> operation to openapi.yaml (metadata-plane types) or openapi.agent-plane.patch.yaml (agent-plane types). Every operation must include summary, description, tags, and at minimum 200, 400, and 422 responses.
Add the channel to asyncapi.yaml or asyncapi.agent-plane.patch.yaml. Include a description on both the channel and the message.
If the new type is a first-class domain concept (not a supporting sub-type), add it to semantic/context.jsonld and add a hydra:supportedClass entry to semantic/hydra.jsonld.
Create docs/adr/NNN-<short-title>.md using the template at docs/adr/0000-template.md.
| Change type | Allowed? | Notes |
|---|---|---|
| Add optional property | ✅ Minor bump | Existing documents remain valid |
| Add required property | Existing documents become invalid — must bump specVersion major and log in CHANGELOG.md + ADR |
|
| Remove property | Same as above | |
Narrow a type (e.g. string → enum) |
||
| Widen a type (e.g. add enum value) | ✅ Minor bump | |
Fix a pattern bug |
✅ Patch bump | |
Change a description |
✅ No version bump |
All stable identifiers follow the scheme urn:srcos:<type-slug>:<local-id>.
type-slugis lowercase, hyphen-separated, and maps one-to-one to a schema title (see the full table in ARCHITECTURE.md).local-idis a URL-safe slug chosen by the producer. It must be unique within the type namespace. Recommended format:[a-z0-9][a-z0-9_-]*.- Use existing URN prefixes — do not invent new slugs without updating
ARCHITECTURE.mdand this guide.
openapi.yamlandopenapi.agent-plane.patch.yamlfollow OpenAPI 3.0.3.- All operations must have:
operationId(camelCase verb + noun),summary(≤ 10 words),description, at least onetagsentry, and response codes200,400,401,403,422. asyncapi.yamlandasyncapi.agent-plane.patch.yamlfollow AsyncAPI 2.6.0.- All channels must have a
description. All messages must havename,title,summary, anddescription.
Validate before committing:
spectral lint openapi.yaml
asyncapi validate asyncapi.yaml
git grep -nE '^(<{7}|={7}|>{7})' -- .
rg -n '^(<{7}|={7}|>{7})' .github/PULL_REQUEST_TEMPLATE.md CHANGELOG.md CONTRIBUTING.md README.md asyncapi.agent-plane.patch.yaml asyncapi.yaml examples/community.json examples/rating.json openapi.agent-plane.patch.yaml openapi.yaml schemas/AgentSession.json schemas/Agreement.json schemas/AuthorityLink.json schemas/CapabilityToken.json schemas/Comment.json schemas/Community.json schemas/Connector.json schemas/DataRef.json schemas/DataSphere.json schemas/Dataset.json schemas/EntityField.json schemas/EventEnvelope.json schemas/Exception.json schemas/ExecutionDecision.json schemas/ExecutionSurface.json- One file per schema type, saved as
examples/<typename>.json(all-lowercase filename matching the schematitlelowercased). - The example must be a complete, valid document — all required fields present.
- Use the shared cross-reference URNs already established in other examples (e.g.
urn:srcos:dataset:health_obs) so the example set tells a coherent end-to-end story. - Validate the example before committing:
ajv validate -s schemas/<TypeName>.json -d examples/<typename>.jsonThe PR template will remind you, but here is the complete list:
- Schema file created/updated in
schemas/ -
"description"present on schema and all properties -
"additionalProperties": falseon all object types - Example file created/updated in
examples/and passes AJV validation -
schemas/README.mdupdated (schema family table) -
openapi.yamlor patch updated with full operation metadata -
asyncapi.yamlor patch updated with channel/message descriptions -
CHANGELOG.mdupdated - ADR created in
docs/adr/if design rationale is non-obvious -
semantic/context.jsonldandhydra.jsonldupdated for first-class types -
specVersionbumped if required (see Breaking vs additive changes) - No Git merge conflict markers remain in touched files
A breaking change is any change that can cause a previously valid document to become invalid, or a previously invalid document to become valid in an unexpected way. Breaking changes:
- Must bump the
specVersionmajor version in the affected schema(s). - Must be documented in
CHANGELOG.mdunder a new## [X.0.0]heading. - Must have a corresponding ADR in
docs/adr/. - Should include a migration guide in the ADR.
An additive change (new optional field, new enum value, new endpoint) bumps the minor version only.
A bug fix (pattern correction, description improvement) bumps the patch version only.