diff --git a/marketplace/index.html b/marketplace/index.html index 556aa72..2c9db94 100644 --- a/marketplace/index.html +++ b/marketplace/index.html @@ -16,12 +16,12 @@

AgenTrust Marketplace

Build with the
verifiable AI ecosystem.

Find integrations across AgenTrust and the Microsoft Agent Governance Toolkit—from framework adapters to policy enforcement and portable trust evidence.

-

Explore the ecosystem

Find the right integration

15 integrations

+

Explore the ecosystem

Find the right integration

integrations

-
+

Make the ecosystem bigger

Your integration belongs here.

Connect a framework, platform, policy engine, or governance product to the AgenTrust stack. The submission path is public, self-serve, and governed by the same rules for everyone.

List your integration ↗
- + diff --git a/marketplace/marketplace.js b/marketplace/marketplace.js index 248f666..2f3da6a 100644 --- a/marketplace/marketplace.js +++ b/marketplace/marketplace.js @@ -1,36 +1,20 @@ (async function () { 'use strict'; const AGENTRUST_CATALOG = 'https://raw.githubusercontent.com/agentrust-io/integrations/main/marketplace/catalog.json'; - const AGT_DIRECTORY = 'https://api.github.com/repos/microsoft/agent-governance-toolkit/contents/agent-governance-python/agentmesh-integrations?ref=main'; - const AGT_NAMES = { - 'a2a-protocol': 'A2A Protocol', 'adk-agentmesh': 'Google ADK', 'agentmesh-avp': 'AgentMesh AVP', - 'audit-accountability-export': 'Audit Accountability Export', 'copilot-governance': 'Copilot Governance', - 'crewai-agentmesh': 'CrewAI', dify: 'Dify', 'flowise-agentmesh': 'Flowise', - 'haystack-agentmesh': 'Haystack', 'langchain-agentmesh': 'LangChain for AGT', - 'langflow-agentmesh': 'Langflow', 'langgraph-trust': 'LangGraph Trust', - 'llamaindex-agentmesh': 'LlamaIndex for AGT', 'mastra-agentmesh': 'Mastra', - 'mcp-receipt-governed': 'MCP Receipt Governance', 'mcp-trust-proxy': 'MCP Trust Proxy', - 'nostr-wot': 'Nostr Web of Trust', 'openai-agents-agentmesh': 'OpenAI Agents for AgentMesh', - 'openai-agents-trust': 'OpenAI Agents Trust', 'openshell-skill': 'OpenShell Skill', - 'pydantic-ai-governance': 'PydanticAI Governance', 'structural-authz-agentmesh': 'Structural Authorization' - }; + const AGT_CATALOG = 'https://raw.githubusercontent.com/agentrust-io/integrations/main/marketplace/agt-catalog.json'; let items = []; const state = { query: '', stacks: new Set(), types: new Set(), sort: 'featured' }; const search = document.getElementById('market-search'), grid = document.getElementById('market-grid'), empty = document.getElementById('market-empty'), status = document.getElementById('catalog-status'); const slug = (value) => value.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, ''); - const initials = (value) => value.split(/[^A-Za-z0-9]+/).filter(Boolean).slice(0, 2).map((word) => word[0]).join('').toUpperCase(); function escape(value) { const node = document.createElement('span'); node.textContent = value; return node.innerHTML; } async function fetchJson(url) { const controller = new AbortController(), timeout = setTimeout(() => controller.abort(), 8000); try { const response = await fetch(url, { headers: { Accept: 'application/json' }, signal: controller.signal }); if (!response.ok) throw new Error(`${url} returned ${response.status}`); return await response.json(); } finally { clearTimeout(timeout); } } function normalizeAgenTrust(catalog) { if (catalog.catalog_version !== 1 || !Array.isArray(catalog.integrations) || catalog.count !== catalog.integrations.length) throw new Error('unsupported AgenTrust catalog'); return catalog.integrations.map((item) => ({ ...item, type: item.category, source: 'AgenTrust', sourceClass: 'community' })); } - function normalizeAgt(directory) { - if (!Array.isArray(directory)) throw new Error('invalid AGT directory'); - return directory.filter((entry) => entry.type === 'dir' && entry.name !== 'template-agentmesh').map((entry) => { - const name = AGT_NAMES[entry.name] || entry.name.split('-').map((part) => part[0].toUpperCase() + part.slice(1)).join(' '); - return { name, package_name: entry.name, vendor: 'Microsoft', description: 'An AGT integration maintained in the Agent Governance Toolkit framework-adapter collection.', url: entry.html_url, repository: 'https://github.com/microsoft/agent-governance-toolkit', homepage: null, tier: 'project', stack: ['AGT'], type: 'AGT integrations', category: 'AGT integrations', mark: initials(name), featured: null, keywords: [entry.name, 'Agent Governance Toolkit', 'AgentMesh'], source: 'AGT', sourceClass: 'project' }; - }).sort((a, b) => a.name.localeCompare(b.name)); + function normalizeAgt(catalog) { + if (catalog.catalog_version !== 1 || !/^[0-9a-f]{40}$/.test(catalog.source_commit) || !Array.isArray(catalog.integrations) || catalog.count !== catalog.integrations.length) throw new Error('unsupported AGT catalog'); + return catalog.integrations.map((item) => ({ ...item, type: item.category, source: 'AGT', sourceClass: 'project' })); } function card(item, compact) { const tags = item.stack.map((tag) => `${escape(tag)}`).join(''); @@ -50,12 +34,12 @@ const params = new URLSearchParams(); if (state.query) params.set('q', state.query); if (state.stacks.size) params.set('stack', [...state.stacks].join(',')); if (state.types.size) params.set('type', [...state.types].join(',')); if (state.sort !== 'featured') params.set('sort', state.sort); history.replaceState(null, '', `${location.pathname}${params.size ? `?${params}` : ''}${location.hash}`); } function clearAll() { state.query = ''; state.stacks.clear(); state.types.clear(); state.sort = 'featured'; search.value = ''; document.getElementById('market-sort').value = 'featured'; document.querySelectorAll('[data-filter]').forEach((input) => { input.checked = false; }); render(); } - const [agentrustResult, agtResult] = await Promise.allSettled([fetchJson(AGENTRUST_CATALOG), fetchJson(AGT_DIRECTORY)]); + const [agentrustResult, agtResult] = await Promise.allSettled([fetchJson(AGENTRUST_CATALOG), fetchJson(AGT_CATALOG)]); const warnings = []; let agentrustItems = [], agtItems = []; if (agentrustResult.status === 'fulfilled') { try { agentrustItems = normalizeAgenTrust(agentrustResult.value); } catch (error) { warnings.push('AgenTrust catalog unavailable'); } } else warnings.push('AgenTrust catalog unavailable'); if (agtResult.status === 'fulfilled') { try { agtItems = normalizeAgt(agtResult.value); } catch (error) { warnings.push('AGT catalog unavailable'); } } else warnings.push('AGT catalog unavailable'); items = [...agentrustItems, ...agtItems]; document.getElementById('hero-count').textContent = items.length; document.getElementById('native-count').textContent = agentrustItems.length; document.getElementById('agt-count').textContent = agtItems.length; - status.textContent = warnings.length ? `${warnings.join(' · ')}. Showing the source that loaded successfully.` : 'Live inventory from the AgenTrust integrations and Microsoft Agent Governance Toolkit repositories.'; status.classList.toggle('catalog-warning', Boolean(warnings.length)); + status.textContent = warnings.length ? `${warnings.join(' · ')}. Showing the source that loaded successfully.` : 'Repository-generated inventory, including a daily commit-pinned snapshot of Microsoft AGT integrations.'; status.classList.toggle('catalog-warning', Boolean(warnings.length)); const stacks = [...new Set(items.flatMap((item) => item.stack))].sort((a, b) => a.localeCompare(b)), types = [...new Set(items.map((item) => item.type))].sort((a, b) => a.localeCompare(b)); addFilters('stack-filters', stacks, 'stacks'); addFilters('type-filters', types, 'types'); document.getElementById('featured-list').innerHTML = agentrustItems.filter((item) => item.featured && item.featured <= 3).map((item) => card(item, true)).join(''); const params = new URLSearchParams(location.search); state.query = params.get('q') || ''; state.sort = ['az', 'za'].includes(params.get('sort')) ? params.get('sort') : 'featured'; (params.get('stack') || '').split(',').filter((value) => stacks.includes(value)).forEach((value) => state.stacks.add(value)); (params.get('type') || '').split(',').filter((value) => types.includes(value)).forEach((value) => state.types.add(value)); search.value = state.query; document.getElementById('market-sort').value = state.sort; document.querySelectorAll('[data-filter]').forEach((input) => { input.checked = state[input.dataset.filter].has(input.value); });