Skip to content

spec: post-meeting converged AI Card profile proposal#18

Open
muscariello wants to merge 28 commits intomainfrom
feat/proposal-postmeeting
Open

spec: post-meeting converged AI Card profile proposal#18
muscariello wants to merge 28 commits intomainfrom
feat/proposal-postmeeting

Conversation

@muscariello
Copy link
Contributor

@muscariello muscariello commented Feb 23, 2026

Summary

This PR adds a new post-meeting specification proposal that converges the current AI Card draft direction into a single profile focused on:

  1. Preserving protocol autonomy through delegated extension modules.
  2. Supporting multiple discovery and distribution technologies.
  3. Strengthening identity and cryptographic provenance guidance.
  4. Providing a practical migration path from previous draft variants.

Overview

This PR rewrites the SEP-0015 converged AI Card profile as an OCI-based specification, replacing the custom card/catalog model with one that follows OCI Image and Distribution specification. The result is that common AI metadata is natively storable, distributable, and signable in any OCI registry without any custom tooling.

What changes

Data model

The top-level AI Card document becomes a standard OCI Image Manifest, identified as an AI Manifest by its artifactType (application/vnd.aaif.ai.manifest.v1+json). Common metadata like identity and publisher details is moved into a dedicated config blob (application/vnd.aaif.ai.card.metadata.v1+json). Protocol-specific metadata (A2A, MCP) and data asset references become typed OCI layer blobs, with artifactTypes owned by this spec but content schemas owned by the respective upstream projects. The AI Catalog becomes a standard OCI Image Index.

The data model can be expressed using a MerkleDAG:

  • AI Manifest is a node linking common AI card metadata with protocol-specific layers
  • AI Catalog is a node that aggregates multiple AI Manifests for discovery
  • Referrers are nodes linking external data to AI Manifests for application-layer logic
graph TB
  subgraph Catalog["OCI Index"]
    AICatalog["AI Catalog"]
  end

  AICatalog --> AIM1["AI Manifest 1"]
  AICatalog --> AIMn["AI Manifest N"]

  subgraph Manifest1["OCI Manifest"]
    AIM1 --> Config1["AI Card Metadata"]
    AIM1 --> Layer1A["A2A Card"]
    AIM1 --> Layer1B["AGNTCY DIR Record"]
    Config1 ~~~ Layer1A ~~~ Layer1B
  end

  subgraph ManifestN["OCI Manifest"]
    AIMn --> ConfigN["AI Card Metadata"]
    AIMn --> LayerN1["MCP Server"]
    AIMn --> LayerN2["HuggingFace Model"]
    ConfigN ~~~ LayerN1 ~~~ LayerN2
  end

  subgraph AppLayer["OCI Referrers"]
    Ext1["Signature"]
    Ext2["Identity Claims"]
  end

  Ext1 --> AIM1
  Ext2 --> AIMn

  style Catalog fill:#dbeafe,stroke:#3b82f6,color:#1e3a5f
  style Manifest1 fill:#dcfce7,stroke:#22c55e
  style ManifestN fill:#dcfce7,stroke:#22c55e
  style AppLayer fill:#fef3c7,stroke:#f59e0b
Loading

Signing

The embedded signatures array and the associated subject commitment model are removed entirely. Signing and attestation are handled via the OCI Referrers API using cosign or notation, following the same pattern already used for signing container images.

Discovery

A new statically hosted registry binding is defined, rooted at /.well-known/ai-registry. This implements the read-only subset of the OCI Distribution Spec (manifest fetch, blob fetch, tags list, referrers list). For static only serving, _catalog.json is defined which serves AI Catalog file (OCI Index). Dynamic autodiscovery is also supported through a common subject descriptor included in the AI Manifest and works out-of-box with existing OCI registries.

Spec document

The document is refactored from a proposal into a normative specification: RFC 2119 conformance language, an Abstract section, a Related Work section referencing CNCF ModelPack/AGNTCY DIR, removal of Open Questions, and updated conformance levels (L0–L3).

$schema: text,
specVersion: text,
cardVersion: text,
cardKind: "live-service" / "data-asset" / "hybrid",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think tying the entire card to a single cardKind at the root level might create a false dichotomy. As mentioned by Mauro in the discussion doc, an AI service often has both: it might expose a 'live-service' via an A2A endpoint for real-time inference, but also offer a 'data-asset' (like downloading its specialized skills, artifacts) via a Skills.

I see hybrid was added here to handle services that are both data-assets and live-services. However, from a routing / client use perspective, hybrid creates ambiguity.

If a caller sees cardKind: "hybrid", it still has to iterate through the flat locators array and write custom logic to guess which URL is the live API and which URL is the data download.

? trust: Trust,
? signatures: [* Signature],
? modules: [* Module],
? locators: [* Locator],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following up on the overall review comment: if an agent supports both the MCP protocol and the A2A protocol, or the one A2A could have multiple endpoints uris, flattening all endpoints into a single locators array means a router has to inspect each locator to figure out which protocol it belongs to.

If we wrap these inside a protocols: { "mcp": {...}, "a2a": {...} } map, the router or client can instantly grab the exact endpoints and artifacts it needs for the protocol it speaks, and ignore the rest.

Copy link
Member

@mindpower mindpower left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @muscariello , thanks for putting this converged view together! I'm really glad to see we are completely aligned on the core structural objects here - the Publisher, Trust, and Attestation blocks look great and match the #4 proposal perfectly.

I also completely agree with your addition of the artifacts array. Having a dedicated way to reference static data (like model weights, datasets, or static skill files) is a great addition.

My main piece of feedback is regarding the transport/endpoint layer. I notice this drops the protocols map from PR #4 in favor of moving locators, artifacts, and modules to the root level alongside a cardKind enum (live-service, data-asset, hybrid).

My concern is that flattening this creates ambiguity for routers / clients, especially with the hybrid designation. If an agent exposes both an MCP protocol and an A2A protocol, a flattened locators array forces the routing client to loop through every URL and guess which endpoint belongs to which protocol based on the URI or media type. It breaks the strong typing we achieved in the core objects.

Could we look at a 'best of both' approach?

  1. Keep the artifacts: [* Artifact] array at the root level for static data downloads (the 'nouns').
  2. Restore the protocols: { "mcp": {...}, "a2a": {...} } map for live endpoints (the 'verbs'). This gives each protocol a clean, isolated namespace.
  3. Drop the cardKind enum and the generic locators array. If a card has artifacts, we know it has data assets. If it has protocols, we know it's a live service. If it has both, it's natively a 'hybrid' without needing a string enum to tell the router to guess.

This keeps the strict typing you aimed for, but ensures the transport layer remains cleanly isolated. What are your thoughts on combining these approaches?

@muscariello
Copy link
Contributor Author

The reason I added the card kind was to manage more general cases where you have an MCP card as data asset and also as live services. The current MCP registry is about data assets with a mix of live services too. To learn more about the kind of card you need to scan inside, and therefore you cannot filter early.

I am not sure my intent was to flatten, I am mostly concerned about discriminating live vs data. The main reason for that is that the security model is very different for these two use case: one is authentication the other is mostly provenance.

@mindpower
Copy link
Member

The reason I added the card kind was to manage more general cases where you have an MCP card as data asset and also as live services. The current MCP registry is about data assets with a mix of live services too. To learn more about the kind of card you need to scan inside, and therefore you cannot filter early.

I am not sure my intent was to flatten, I am mostly concerned about discriminating live vs data. The main reason for that is that the security model is very different for these two use case: one is authentication the other is mostly provenance.

Ah, that makes complete sense for the registry layer . Having cardKind for that O(1) early filtering so the registry doesn't have to parse the whole payload is a great optimization.

I would gently push back on one nuance, though: in a zero-trust Agentic world, live services also heavily rely on provenance. Authentication alone isn't enough for an agent API - we still need supply-chain provenance (like AI-BOMs, signed build manifests, or base model attestations) to actually trust the live inference endpoint.

But your core point about early filtering sounds right. What if we combine both of our goals to satisfy both the Registry and the router?

  1. Keep cardKind at the root: This gives the registry the exact early-filtering index it needs to know what it's dealing with before parsing the payload.
  2. Replace the flat locators array with protocols (for live APIs) and artifacts (for static data): This fixes the routing ambiguity. If the router pulls a live-service, it instantly grabs protocols.a2a or protocols.mcp without having to loop through generic locators to guess the transport. If it pulls a data-asset, it just grabs the artifacts array.

This way, the Registry gets its fast filtering, the Router gets its strict typing without guessing, and the unified Trust block at the root handles provenance for both use cases.

Does that sounds good to you?

@muscariello
Copy link
Contributor Author

Let me take into account your feedback @mindpower.
I realize the map you are proposing contains multiple cards so cardKind does not make sense.

We can keep the map like you proposed. I would call this map "modules" to contains "protocols", "artifacts" and more in the future.

This means that locators are only part of the inner cards as it would not make much sense to have different locators listed outside of the map.

I have a concern about announce and discovery. An outer card (say an ai record) in a catalog which contains several other cards needs a labels which can be used to announce and discover this object beyond the simple index.
These labels could be standardized to summarize the entire collection of inner cards as we should assume every project would have a specific way to label their own card. A2A uses skills, but they might be others in general.

Have a look at the next commit.

Signed-off-by: Luca Muscariello <muscariello@ieee.org>
@mindpower
Copy link
Member

mindpower commented Mar 5, 2026

This latest commit looks fantastic, @muscariello ! We are practically 100% converged. Dropping the rigid cardKind and bringing back the map structure completely solves the routing ambiguity we discussed. Combined with the tags you included earlier, this perfectly aligns with the extensible routing and registry discovery goals we originally set out to achieve.

I just have one minor structural thought, and a quick procedural suggestion:

1. The modules wrapper: Do we gain much by nesting protocols and artifacts inside a generic modules object? (i.e., card.modules.protocols.a2a vs card.protocols.a2a). Usually, keeping primary domain concepts at the root level reduces parsing friction for clients. If we just promote protocols and artifacts directly to the root (right next to tags and publisher), it keeps the JSON incredibly clean and flat.

2. Preserving the Working Group History:
Since this converged schema now beautifully reflects the isolated namespaces and core identity blocks we've been hammering out (plus your excellent addition of the artifacts array!), how do you want to handle the merge? The original PR #4 currently holds 70+ comments of deep architectural history and consensus-building from both the working group and the broader open-source community.

Would you be open to pushing this final, converged CDDL (with the flattened root) directly into PR #4? That way, we keep all the rich historical context and decision logs attached to the final merge, rather than fragmenting it.

Either way, incredible work pulling all these threads together! Let me know what you think.

Signed-off-by: Luca Muscariello <muscariello@ieee.org>
@muscariello
Copy link
Contributor Author

@mindpower I am fine with any approach to merge. I can redirect to PR #4, no problem. I am trying to make sure I am including all the discussion points. Hope to get more feedback too.

I am not sure modules is actually required but it has some value as interface if we start adding and deprecating protocols in the future as this avoid to change parsers to some extent. But it's a question of taste probably.

In this latest commit I added some comments to your other PR on naming. I had some concerns that I shared in here. Hope you can have a look at this.

"type": "https",
"role": "api",
"uri": "https://api.acme-finance.com/a2a/v1"
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something we've done in the a2a AgentCard is move the protocol version down into the locator (AgentInterface), this allows for a single agent to serve multiple A2A protocol versions cleanly which is required for backwards compatiblity / safe rolling upgrades etc.

Should "data" here really just be the AgentCard embedded in the ai card? If so we should fix the example to align it properly with the AgentCard schema. Similarly we should make sure the "data" for MCP is aligned with the MCP server card.

@mindpower
Copy link
Member

@mindpower I am fine with any approach to merge. I can redirect to PR #4, no problem. I am trying to make sure I am including all the discussion points. Hope to get more feedback too.

I am not sure modules is actually required but it has some value as interface if we start adding and deprecating protocols in the future as this avoid to change parsers to some extent. But it's a question of taste probably.

In this latest commit I added some comments to your other PR on naming. I had some concerns that I shared in here. Hope you can have a look at this.

Awesome, really appreciate you being open to using PR #4 to preserve the community history, @muscariello ! And thank you for doing the heavy lifting to synthesize all these discussion points - it’s incredibly helpful for the working group.

1. On the modules wrapper: I definitely see your point about insulating parsers from future additions. My lean towards a flat structure (promoting protocols and artifacts directly to the root) is mostly inspired by how OpenAPI or Kubernetes handle top-level extensions - it usually keeps the base types a bit cleaner for developers to read. Since it's a question of taste, maybe we can keep it flat for simplicity in v1? It's usually easier to add a wrapper later than to remove one once parsers are built. But I'm completely open to whatever the broader group prefers!

2. On Naming:
I saw your notes on naming in the latest commit, great catches. I’ll take a detailed look at those today and drop my thoughts so we can nail down the exact taxonomy.

Next Steps:
To keep things moving and save you from cross-fork Git headaches, I'll review your naming comments today and apply those tweaks along with the flattened root, and pull your converged CDDL directly merge into PR #4? I will make sure you are tagged as a co-author on the commit as well.

}

HostInfo = {
name: text,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

displayName


HostInfo = {
name: text,
? id: text,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Identifier for the catalog. Could be a DID.

records: [* CatalogEntry]
}

HostInfo = {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the AI Catalog contain the FQDN, which would tie the ai catalog to the domain? This might not be desirable.

],
"modules": {
"artifacts": {
"dataset": {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this key? And how is it different than the Id of the artifact?

AICatalog = {
$schema: text,
specVersion: text,
host: HostInfo,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry commented on the wrong PR, lifting here:

Can host be optional? I think many MCP use cases would not care to populate this, so not sure we want this to be a required field.

name: text,
description: text,
? tags: [* text],
cardUrl: text,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry commented on the wrong PR, lifting here --

Could we consider allowing pointing to an MCP Server Card (or A2A Agent Card) directly here?

This is probably tied to the uncertainty around "do we definitely want/need an envelope AI card format". If we were to adopt the shared extension approach @ToddSegal brought up in the first call, we wouldn't need the AI card intermediating here.

From my POV, for much of what MCP wants out of discovery:

  • It would be sufficient to have a .well-known location where ai-catalog.json can be found
  • We want a way to get from ai-catalog.json to an instance of an MCP Server Card
  • So if this cardUrl can be an MCP Server Card (perhaps with an additional protocol field of some sort), I think that's likely to work for us, and we accomplish our shared goal of having a unified discovery layer.

This current model requires an extra hop, to go ai-catalog.json -> AI Card -> MCP Server Card. And the current proposal for AI Card has shapes/duplication of values we intend to (additionally?) store in MCP Server Card, and I'm not sure we'd want to combine governance of those fields to be in the critical path of discovery.

Pushing for alignment on all of AI Card's current scope will be a long road, I think. For example, I think tags, maturity, logoUrl, etc all require discussion that we've discussed at length in various ways within the MCP ecosystem. And if we strip out all the controversial things that require alignment, I worry we end up with a very thin AI Card layer (in which case why not sidestep all that coordination and just link to MCP Server Cards / A2A Agent Cards directly here)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tadasant this is a reasonable concern. What you describe is similar to a manifest file, with referrers to cards which exist as atomic and independent unit. In that case the ai-catalog or the ai-card seems like the same thing. Let me try to propose something that addresses these concerns.

Copy link
Contributor Author

@muscariello muscariello Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tadasant @mindpower @darrelmiller @ToddSegal
We believe the current manifest approach addresses all concerns and requirements raised so far by the participating projects and individual contributors:

  • Delegation: each card has a media type owned and managed by its project.
  • The AI Card spec only needs to track media types.
  • The AI Card is a flat manifest collection of referrers by digest, making it globally unique and secure.
  • The catalog is fully portable and location-independent, and can be hosted statically or behind an API server for convenience.
  • Provenance is supported out of the box, and multiple attestations can be added incrementally.

mindpower added a commit to mindpower/ai-card that referenced this pull request Mar 5, 2026
…update naming from PR Agent-Card#18

Co-authored-by: Luca Muscariello <lumuscar@cisco.com>
@mindpower
Copy link
Member

Hey @muscariello , just a quick update: Based on discussions #18 (comment). I've pulled the converged CDDL into PR #4! I went ahead and flattened the protocols and artifacts up to the root (dropping the modules wrapper) as we discussed, and I also added you as a Co-Author on the commit and also updated you as an Assignee on that PR so we can drive it across the finish line together. Whenever you are ready, feel free to close this PR out, and we can continue the final naming/polish discussions over on #4 where all the historical context lives. Thanks again for driving this convergence.

Tehsmash added 2 commits March 9, 2026 11:56
Replace the custom card/catalog model with a proper OCI-native design:

- AI Card → AI Manifest (OCI Image Manifest with artifactType)
- AI Card Config moves to a dedicated config blob
- Modules → typed OCI layers (A2A, MCP, ModelPack dataset)
- AI Catalog → OCI Image Index
- Signing removed from config; replaced by OCI Referrers (cosign/notation)
- cardKind dropped; inferred from layers present

Add statically hosted registry binding rooted at /.well-known/ai-registry,
implementing the read-only OCI Distribution Spec subset (end-1/2/3/8a/12a/b)
with a /_catalog.json entry point for zero-configuration discovery.

Update schemas (schema.json, catalog-schema.json), add config-schema.json,
update CDDL definitions, and rewrite all examples to match.
Tehsmash and others added 4 commits March 9, 2026 12:03
- Replace proposal frontmatter with Version/Status/Authors header
- Add Abstract section
- Add RFC 2119 conformance language (Section 1)
- Remove 'This proposal defines' / 'This profile defines' language throughout
- Drop Open Questions section
- Rename 'Summary' -> 'Abstract', 'Discovery Bindings' -> 'Distribution',
  'Design Principles' -> 'Design Goals'
- Tighten MUST/SHOULD/MAY normative language in data model sections
- Fix schema/example paths to be relative to specification/
Signed-off-by: Luca Muscariello <muscariello@ieee.org>
muscariello and others added 10 commits March 10, 2026 10:24
Signed-off-by: Luca Muscariello <muscariello@ieee.org>
Signed-off-by: Ramiz Polic <ramiz.polic@hotmail.com>
Signed-off-by: Ramiz Polic <ramiz.polic@hotmail.com>
Signed-off-by: Ramiz Polic <ramiz.polic@hotmail.com>
Signed-off-by: Ramiz Polic <ramiz.polic@hotmail.com>
Signed-off-by: Ramiz Polic <ramiz.polic@hotmail.com>
Signed-off-by: Ramiz Polic <ramiz.polic@hotmail.com>
Signed-off-by: Ramiz Polic <ramiz.polic@hotmail.com>
Signed-off-by: Ramiz Polic <ramiz.polic@hotmail.com>
feat(spec): rewrite SEP-0015 as OCI-native AI Manifest spec
mindpower added a commit that referenced this pull request Mar 12, 2026
…ing from PR #18

Co-authored-by: Luca Muscariello <lumuscar@cisco.com>
ramizpolic and others added 7 commits March 13, 2026 16:04
Signed-off-by: Ramiz Polic <ramiz.polic@hotmail.com>
Signed-off-by: Ramiz Polic <ramiz.polic@hotmail.com>
Signed-off-by: Ramiz Polic <ramiz.polic@hotmail.com>
Signed-off-by: Ramiz Polic <ramiz.polic@hotmail.com>
docs(spec): patch specs with auto-discovery and app-usage
Signed-off-by: Ramiz Polic <ramiz.polic@hotmail.com>
Signed-off-by: Ramiz Polic <ramiz.polic@hotmail.com>
@mindpower
Copy link
Member

mindpower commented Mar 16, 2026

Hi @muscariello and @ramizpolic , first off, thank you for putting this together. This is an incredibly thorough and elegant application of the OCI specification. Moving the enterprise trust, signing (via cosign/notation), and distribution into standard OCI registries makes perfect sense for heavy, enterprise-grade AI asset management.

As I digest this, I want to make sure we don't accidentally kill the grassroots adoption we are seeing from the MCP, A2A and web-native developer communities. For many of those developers, standing up an OCI registry or understanding Image Manifests just to share a simple agent card introduces too much friction. They love the simplicity of hosting a static .json file over basic HTTP (which we just locked in with PR #4).

Proposed Architectural Framing:
Rather than this OCI spec replacing the JSON card/catalog model we just merged, what if we frame this as the Enterprise OCI Distribution Binding, while keeping the PR #4 model as the Lightweight Web/HTTP Binding?

  1. The Logical Model: The architecture we aligned on in PR spec: AI card and AI catalog draft proposal #4 remains our conceptual core. (either "Envelope + reference" or "common data layer" model - the core logical part)
  2. The Web Binding (Level 0): Developers can just host the raw JSON envelopes and catalogs on a standard web server (low friction, high adoption for MCP/A2A).
  3. The OCI Binding (Level 1+): Enterprises can map that exact same logical envelope into an OCI Image Manifest and OCI Layer Blobs (this PR) to get advanced registry discovery, cosign attestation, and MerkleDAG integrity.

By treating OCI as a powerful storage/distribution profile rather than the only data model, we satisfy Enterprise's need for strict supply-chain security without scaring away the lightweight Agent developers.

What are your thoughts on framing this as an advanced distribution profile alongside the baseline we just merged? Happy to jump on a call to whiteboard how they map to each other!

@muscariello
Copy link
Contributor Author

muscariello commented Mar 16, 2026

@mindpower there is no need to stand an OCI server. Try to reproduce the small demo. You can have an OCI layout w/o a server.
As soon as you put and API server in front of this layout like I see in your proposal in another PR you are redoing an OCI server if you also require security.

I have concerns about the fact that we have lined up all the requirements which are common to OCI and will inevitable lead to redoing OCI but not as good. In that case OCI is a better option as we have to write no code.

So IMO, this proposal can be used in a purely static way as the OCI layout is a list of files in a folder.

My claim is that this proposal covers all the requirements combined without adding complexity.
And for the basic use case, users will have to store one single json file per card.

@Tehsmash
Copy link

Tehsmash commented Mar 18, 2026

For many of those developers, standing up an OCI registry or understanding Image Manifests just to share a simple agent card introduces too much friction.

In addition to what @muscariello said, most developers should never need to interact directly with the proposed structure unless they are building a CLI, library or registry on top of the spec which needs to understand the structure in order to navigate it.

For most agentic developers there should be tooling, libraries, or CLIs to interact with the ai-card catalog/registry whether static or dynamic. For example:

If you're using modelpack to publish a model you create a Modelfile (like a Dockerfile) and go through modctl which packs the data into the OCI structure and uses ORAS underneath. You also use modctl to pull from the registry static local or remote and extract the model back into a directory.

I envision the ecosystem will be similar for AI Card as for modelpack, and if we use the same structure for static and for dynamic catalogs then the same tooling can be used for both at least from a reader client's perspective.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants