agentmesh · a2a ui links extension

UI links on the card

Many agents serve web surfaces for people: a dashboard, a reports page, a status page. The card has no field for them. This small data-only extension lists their URLs with labels for who each surface is for and what happens at the door. It is not a UI format: efforts like A2UI stream interface into a session, while this extension lists standing destinations a person opens in a browser.

the declaration

How a surface is declared

The extension is declared in the card's capabilities.extensions array. Because it is data-only, required MUST NOT be true. The payload is params.uis, an array of entries:

{
  "uri": "https://dev.agentmesh.ai/extensions/ui-links/v1",
  "description": "Web surfaces this agent's publisher offers to people",
  "required": false,
  "params": {
    "uis": [
      {
        "url": "https://agent.example/reports",      // REQUIRED, https only
        "label": "Reports",                        // REQUIRED, short human label
        "purpose": "Download outputs of completed work.",
        "audience": "client",                     // public | client | operator
        "access": "authenticated",                // open | authenticated
        "kind": "reports",                        // open vocabulary
        "skill": "some-declared-skill-id"        // the one skill this UI fronts
      }
    ]
  }
}
  • url (required): an HTTPS URL. Nothing else qualifies.
  • label (required): a short human label, suited to link text.
  • purpose (optional): one sentence on what a person can do there.
  • audience (optional): public, client, or operator. Directories show public entries broadly, client entries only inside an engagement, operator entries to nobody by default.
  • access (optional): open or authenticated. What happens at the door.
  • kind (optional): suggested values are dashboard, status, reports, settings, docs, chat, storefront. Unknown values are allowed and rendered as-is, never refused.
  • skill (optional): the id of one skill declared in the card that this surface fronts.

the rules

A ui-link is a label, and it grants nobody access

  • audience and access are labels. They state the publisher's intent; the door itself enforces. A consumer MUST NOT treat operator as secrecy (the URL is in a published card) nor open as safety.
  • Every entry is an untrusted link. Never auto-open, never auto-embed, never iframe. A flat v1 rule: embedding, if ever wanted, is a future versioned addition with its own security section.
  • Same-origin is computed, never declared. Consumers SHOULD compare each entry's origin against the card's own origin and flag cross-origin entries visibly. Cross-origin is often legitimate; the reader just gets to see the seam.
  • A UI is never proof of identity. Visiting an entry establishes nothing about the agent, and an entry MUST NOT be treated as an authentication context because a signed card pointed at it. The signature covers the pointer bytes, never the safety of what is behind them.
  • Absence states nothing. A card without the extension is silent about surfaces, not surface-free. And a dead link is evidence of nothing except that the URL failed to load.
left out on purpose

No screenshots or thumbnails (bloat, staleness, a spoofing surface). No auth scheme details beyond the boolean (a credential phishing surface). No locale in v1. No liveness or uptime claims: an entry asserts the publisher offers the surface, not that it is up.

worked example

A worked example with three surfaces

Larkfield Payroll (fictional) serves its card at agent.larkfield.example and declares a run-payroll skill. Its card lists an operator dashboard, a client reports page bound to that skill, and a public status page:

"uis": [
  { "url": "https://agent.larkfield.example/ops",
    "label": "Operations dashboard",
    "audience": "operator", "access": "authenticated", "kind": "dashboard" },
  { "url": "https://agent.larkfield.example/reports",
    "label": "Payroll reports",
    "purpose": "Download completed payroll runs and filings for your account.",
    "audience": "client", "access": "authenticated",
    "kind": "reports", "skill": "run-payroll" },
  { "url": "https://status.larkfield.example/",
    "label": "Service status",
    "audience": "public", "access": "open", "kind": "status" }
]

A public directory lists only the status page. A client app, rendering this agent inside an engagement, adds the reports link next to the work it fronts. Nothing renders the operator dashboard by default, and nothing pretends the URL is secret either. The status page lives on a different origin than the card, so a conforming renderer flags it as cross-origin, which here is merely true, not alarming.

ecosystem

This is not a UI format

Adjacent efforts standardize UI as message content. A2UI has an agent stream declarative component blueprints into a host application during a session, and the host renders them natively; AG-UI is a transport such payloads ride; MCP Apps embeds pre-built HTML in sandboxed iframes. All of them answer how an agent puts interface in front of a user mid-conversation.

This extension is UI as standing destination: the card lists URLs of web surfaces the agent's publisher serves, opened in a browser, session or no session. It defines no components, no rendering model, no transport, and no format; it carries addresses, not interfaces. The two are complementary: an agent may stream A2UI components in conversation while its card advertises its standing dashboard through this extension.

where it lives

It sits beside the contract stack rather than in it

This extension carries no contract vocabulary, which is why it is hosted here rather than on the standards sites where the terms, verification, and reputation extensions live (a2a-card-extensions). The intent is to propose it upstream to the A2A project's extension governance; if an equivalent official extension emerges, this URI will be deprecated in its favor.

# extension URI
https://dev.agentmesh.ai/extensions/ui-links/v1

Full specification: https://dev.agentmesh.ai/SPEC-A2A-UI-LINKS.md