Demo Video: ANS Integration Walkthrough
This document describes the ANS integration architecture, configuration, API usage, and operational procedures for the MCP Gateway Registry.
ANS (Agent Name Service) is a PKI-based trust verification service operated by GoDaddy that provides cryptographic identity verification for AI agents. The MCP Gateway Registry integrates with ANS using a read-only "Bring Your Own ANS ID" approach -- the registry never manages PKI certificates or identities directly. Instead, agent owners register with ANS independently and then link their ANS Agent ID to their registry entry for trust verification.
- Cryptographic identity verification for AI agents
- Domain ownership proof via PKI certificates
- Agent identity metadata (name, description, version, organization)
- Endpoint and protocol registration (A2A, MCP, HTTP-API)
- Certificate lifecycle management (issuance, expiration, revocation)
- Stores ANS verification metadata on agent and server records
- Displays trust badges on agent/server cards in the UI
- Periodically re-verifies ANS status via background sync
- Provides admin visibility into ANS integration health
Integration Architecture:
Agent Owner AI Registry GoDaddy ANS API
----------- ----------- ---------------
| | |
| 1. Register with ANS | |
| (out-of-band) ========================> |
| | |
| 2. Link ANS ID | |
| POST /agents/{p}/ans/link |
| ======================> | |
| | 3. Verify with ANS API |
| | ========================> |
| | <== ANS Metadata ====== |
| | |
| 4. Trust badge shown | |
| <===================== | |
| | |
| | 5. Background re-verify |
| | (every 6 hours) |
| | ========================> |
All ANS configuration is managed via environment variables that map to Pydantic Settings fields in registry/core/config.py.
| Parameter | Environment Variable | Description | Default |
|---|---|---|---|
ans_integration_enabled |
ANS_INTEGRATION_ENABLED |
Master switch for ANS integration | false |
ans_api_key |
ANS_API_KEY |
GoDaddy API key for authentication | "" |
ans_api_secret |
ANS_API_SECRET |
GoDaddy API secret for authentication | "" |
| Parameter | Environment Variable | Description | Default |
|---|---|---|---|
ans_api_endpoint |
ANS_API_ENDPOINT |
ANS API base URL | https://api.godaddy.com |
ans_api_timeout_seconds |
ANS_API_TIMEOUT_SECONDS |
HTTP request timeout for ANS calls | 30 |
ans_sync_interval_hours |
ANS_SYNC_INTERVAL_HOURS |
Background verification sync interval | 6 |
ans_verification_cache_ttl_seconds |
ANS_VERIFICATION_CACHE_TTL_SECONDS |
Cache TTL for verification results | 3600 |
# ANS Integration
ANS_INTEGRATION_ENABLED=true
ANS_API_ENDPOINT=https://api.godaddy.com
ANS_API_KEY=your-godaddy-api-key
ANS_API_SECRET=your-godaddy-api-secret
ANS_API_TIMEOUT_SECONDS=30
ANS_SYNC_INTERVAL_HOURS=6For ECS deployments, set these in terraform/aws-ecs/terraform.tfvars:
ans_integration_enabled = true
ans_api_endpoint = "https://api.godaddy.com"
ans_api_key = "your-api-key"
ans_api_secret = "your-api-secret"ANS configuration is visible in the admin System Configuration page under the "ANS Integration" group. Navigate to the registry UI and open the system configuration panel to view and export current ANS settings.
Links an ANS Agent ID to a registered agent. The registry calls the ANS API to verify the identity and stores the metadata.
POST /api/agents/{agent_path}/ans/link
Content-Type: application/json
Authorization: Bearer <token>
X-CSRF-Token: <csrf_token>
{
"ans_agent_id": "ans://v1.0.0.myagent.example.com"
}Response (200):
{
"success": true,
"message": "ANS identity linked and verified",
"ans_metadata": {
"ans_agent_id": "89a5061b-4f89-452b-9b66-dd9ca8baad7f",
"status": "verified",
"domain": "example.com",
"organization": "Example Corp",
"ans_name": "myagent.example.com",
"ans_display_name": "My Agent",
"certificate": {
"not_before": "2025-01-01T00:00:00Z",
"not_after": "2026-01-01T00:00:00Z",
"subject_dn": "CN=myagent.example.com",
"issuer_dn": "CN=ANS CA"
},
"endpoints": [],
"linked_at": "2026-03-26T12:00:00Z",
"last_verified": "2026-03-26T12:00:00Z"
}
}Requirements:
- User must be authenticated
- User must own the agent (
registered_byfield matches username) - Rate limited: 10 link operations per user per hour
- CSRF token required
GET /api/agents/{agent_path}/ans/status
Authorization: Bearer <token>Response (200): Returns full ANS metadata for the agent. Response (404): Agent has no ANS link.
DELETE /api/agents/{agent_path}/ans/link
Authorization: Bearer <token>
X-CSRF-Token: <csrf_token>Response (200):
{
"success": true,
"message": "ANS identity unlinked"
}Servers follow the same pattern as agents:
| Method | Path | Description |
|---|---|---|
| POST | /api/servers/{path}/ans/link |
Link ANS ID to server |
| GET | /api/servers/{path}/ans/status |
Get server ANS status |
| DELETE | /api/servers/{path}/ans/link |
Unlink ANS from server |
Forces an immediate re-verification of all linked ANS identities.
POST /api/admin/ans/sync
Authorization: Bearer <admin_token>
X-CSRF-Token: <csrf_token>Response (200):
{
"total": 15,
"updated": 12,
"errors": 1,
"duration_seconds": 4.2
}Requires: Admin group membership or ans-admin/manage scope.
GET /api/admin/ans/metrics
Authorization: Bearer <admin_token>Response (200):
{
"total_linked": 15,
"by_status": {
"verified": 12,
"expired": 2,
"not_found": 1
},
"by_asset_type": {
"agent": 10,
"server": 5
},
"sync_history": [
{
"timestamp": "2026-03-26T06:00:00Z",
"total": 15,
"updated": 2,
"errors": 0,
"duration_seconds": 3.8
}
]
}GET /api/admin/ans/health
Authorization: Bearer <admin_token>Response (200):
{
"status": "healthy",
"api_reachable": true,
"api_status_code": 200
}Possible status values: healthy, degraded, unhealthy.
The registry management CLI can be used to interact with ANS endpoints.
# Using curl with token file
TOKEN=$(cat .token)
REGISTRY_URL="https://your-registry.example.com"
# Link ANS identity
curl -X POST "${REGISTRY_URL}/api/agents/my-agent/ans/link" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{"ans_agent_id": "ans://v1.0.0.myagent.example.com"}'curl -s "${REGISTRY_URL}/api/agents/my-agent/ans/status" \
-H "Authorization: Bearer ${TOKEN}" | python -m json.toolcurl -X POST "${REGISTRY_URL}/api/admin/ans/sync" \
-H "Authorization: Bearer ${TOKEN}"curl -s "${REGISTRY_URL}/api/admin/ans/metrics" \
-H "Authorization: Bearer ${TOKEN}" | python -m json.toolcurl -s "${REGISTRY_URL}/api/admin/ans/health" \
-H "Authorization: Bearer ${TOKEN}" | python -m json.toolList an agent and check the ans_metadata field:
curl -s "${REGISTRY_URL}/api/agents/my-agent" \
-H "Authorization: Bearer ${TOKEN}" | python -m json.tool | grep -A 20 ans_metadataANS Agent IDs follow the URI format:
ans://v1.0.0.agentname.domain.com
Components:
ans://- Protocol schemev1.0.0- Version identifieragentname- Agent name within the domaindomain.com- Verified domain
The registry also accepts raw UUIDs (e.g., 89a5061b-4f89-452b-9b66-dd9ca8baad7f). When an ans:// URI is provided, the client resolves it to a UUID by searching the ANS API.
| Status | Meaning | Badge Color |
|---|---|---|
verified |
Agent identity is valid and certificate is current | Green |
expired |
Certificate has passed its notAfter date |
Yellow |
revoked |
Agent or certificate has been explicitly revoked | Red |
not_found |
ANS Agent ID no longer exists in ANS | Gray |
pending |
Verification is in progress | Blue |
| File | Purpose |
|---|---|
registry/services/ans_client.py |
Low-level HTTP client for GoDaddy ANS API |
registry/services/ans_service.py |
Business logic for link/unlink/sync operations |
registry/services/ans_sync_scheduler.py |
Background task that re-verifies all linked identities |
| File | Purpose |
|---|---|
registry/api/ans_routes.py |
FastAPI router with all ANS endpoints |
| File | Purpose |
|---|---|
registry/schemas/ans_models.py |
Pydantic models for ANS metadata, certificates, endpoints |
registry/schemas/agent_models.py |
Agent model with ans_metadata field |
registry/core/schemas.py |
Server model with ans_metadata field |
| File | Purpose |
|---|---|
frontend/src/components/ANSBadge.tsx |
Badge component and certificate detail modal |
frontend/src/components/AgentCard.tsx |
Displays ANS badge on agent cards |
frontend/src/components/ServerCard.tsx |
Displays ANS badge on server cards |
The ANS sync scheduler runs as an async background task within the FastAPI application lifecycle.
- On application startup, if
ans_integration_enabled=True, the scheduler starts - Every
ans_sync_interval_hours(default 6), it runssync_all_ans_status() - The sync queries all agents and servers with non-null
ans_metadata - For each linked asset, it calls the ANS API to re-verify the identity
- Updates
ans_metadata.statusandans_metadata.last_verifiedtimestamp - Stores sync results in memory (last 20 runs), viewable via admin metrics endpoint
Application Start
|
v
[ANS Enabled?] --No--> Skip
|
Yes
v
Start Scheduler Loop
|
v
Sleep(sync_interval_hours)
|
v
sync_all_ans_status()
|
+---> For each agent with ans_metadata:
| verify_ans_agent(ans_agent_id)
| Update status + last_verified
|
v
Store sync stats
|
v
Loop back to Sleep
The ANS client implements a circuit breaker to prevent cascading failures when the ANS API is unavailable.
| Parameter | Value |
|---|---|
| Failure threshold | 5 consecutive failures |
| Reset timeout | 3600 seconds (1 hour) |
| Behavior when open | Returns None immediately without calling API |
Each ANS API call includes automatic retries:
| Parameter | Value |
|---|---|
| Max retries | 3 |
| Backoff strategy | Exponential (1s, 2s, 4s) |
| Timeout per request | ans_api_timeout_seconds (default 30s) |
Per-user rate limiting on link operations prevents abuse:
| Parameter | Value |
|---|---|
| Max requests | 10 per user |
| Window | 3600 seconds (1 hour) |
The registry authenticates with GoDaddy's ANS API using SSO-key authentication:
Authorization: sso-key {ans_api_key}:{ans_api_secret}
This is a GoDaddy-specific authentication scheme. API keys are obtained from the GoDaddy developer portal.
| Method | ANS API Path | Purpose |
|---|---|---|
| GET | /v1/agents/{uuid} |
Fetch agent details and certificate info |
| GET | /v1/agents?name={name} |
Resolve ans:// URI to UUID |
ANS metadata is stored as a dict[str, Any] field on both agent and server MongoDB documents. This allows schema evolution without database migrations.
{
"path": "/my-agent",
"name": "My Agent",
"ans_metadata": {
"ans_agent_id": "89a5061b-4f89-452b-9b66-dd9ca8baad7f",
"status": "verified",
"domain": "example.com",
"organization": "Example Corp",
"ans_name": "myagent.example.com",
"certificate": { ... },
"endpoints": [ ... ],
"linked_at": "2026-03-26T12:00:00Z",
"last_verified": "2026-03-26T12:00:00Z"
}
}The agent list (GET /api/agents) and server list (GET /api/servers) API responses now include ans_metadata for each entry. This is reflected in the OpenAPI spec (openapi.json). When an agent or server has a linked ANS identity, the full metadata object is returned inline, allowing API consumers to display trust information without making additional calls.
# List agents - each entry includes ans_metadata when linked
curl -s "${REGISTRY_URL}/api/agents" \
-H "Authorization: Bearer ${TOKEN}" | python -m json.toolExample agent entry in the list response:
{
"path": "/jewel-homes-support-agent",
"name": "Jewel Homes Support Agent",
"description": "Real estate support agent",
"ans_metadata": {
"ans_agent_id": "89a5061b-4f89-452b-9b66-dd9ca8baad7f",
"status": "verified",
"domain": "helpagent.club",
"organization": "Jewel Homes",
"last_verified": "2026-03-26T12:00:00Z"
}
}When no ANS identity is linked, ans_metadata is null.
The semantic search API (GET /api/search) now returns a trust_verified boolean field in each result. This field is derived from ans_metadata.status == "verified" and provides a simple flag for consumers to identify agents with valid ANS verification without needing to parse the full metadata.
# Semantic search - results include trust_verified field
curl -s "${REGISTRY_URL}/api/search?q=real+estate+support" \
-H "Authorization: Bearer ${TOKEN}" | python -m json.toolExample search result:
{
"results": [
{
"path": "/jewel-homes-support-agent",
"name": "Jewel Homes Support Agent",
"description": "Real estate support agent",
"score": 0.92,
"trust_verified": true
},
{
"path": "/generic-helper",
"name": "Generic Helper",
"description": "General purpose helper",
"score": 0.78,
"trust_verified": false
}
]
}This allows search consumers to prioritize or filter results by trust status. Agents with trust_verified: true have a valid, non-expired, non-revoked ANS identity.
When registering a new agent, an optional ans_agent_id field can be included in the request body. If provided and ANS integration is enabled, the registry will attempt to link and verify the ANS identity as part of registration. This is a best-effort operation -- if ANS verification fails, the agent is still registered and can be linked later via the dedicated endpoint.
curl -X POST "${REGISTRY_URL}/api/agents" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"name": "My Agent",
"path": "/my-agent",
"description": "An example agent",
"ans_agent_id": "ans://v1.0.0.myagent.example.com"
}'ANS routes must be registered in registry/main.py before the agent router because the agent router contains a catch-all {path:path} route that would otherwise consume ANS-specific paths like /agents/{path}/ans/status.
# In registry/main.py - order matters
app.include_router(ans_router, prefix="/api", tags=["ANS Integration"]) # BEFORE agent_router
app.include_router(agent_router, prefix="/api", tags=["Agent Management"]) # catch-all {path:path} here- Check ANS is enabled: Verify
ANS_INTEGRATION_ENABLED=truein environment - Check API credentials: Verify
ANS_API_KEYandANS_API_SECRETare set - Check route ordering: ANS router must be registered before agent router in
main.py - Check agent has metadata:
GET /api/agents/{path}should showans_metadatafield - Check API health:
GET /api/admin/ans/healthshould returnhealthy
- Check circuit breaker: If 5+ consecutive failures, circuit opens for 1 hour
- Check API endpoint: Verify
ANS_API_ENDPOINTpoints to correct URL - Check credentials: Test with
GET /api/admin/ans/health - Check timeout: Increase
ANS_API_TIMEOUT_SECONDSif requests are timing out
This typically means the initial verification call failed or timed out. Try:
- Unlink:
DELETE /api/agents/{path}/ans/link - Re-link:
POST /api/agents/{path}/ans/linkwith the ANS Agent ID - Or trigger manual sync:
POST /api/admin/ans/sync
Similar to ANS routes, security scan routes (/agents/{path}/security-scan) must be defined before the catch-all {path:path} route in agent_routes.py. If these return 404, check route ordering.