Skip to content

Agent Intent Protocol (AIP)

AIP is an open protocol that lets AI agents discover, pay for, and use services by declaring what they need — not how to get it. One API call handles provider selection, execution, and on-chain payment settlement.


How It Works

Agent sends intent (e.g. "chat_completion", budget $0.05)
  → AIP resolves the best provider (price / quality / speed)
  → Executes the request
  → Settles payment on-chain (USDC via x402)
  → Returns result + settlement receipt
StageWhat happens
ResolveMatches your intent to available providers based on constraints (price, latency, features)
ExecuteRoutes the request to the selected provider and runs it
SettleDeducts exact cost via x402 (USDC on Base or Solana), returns verifiable on-chain receipt

Design Principles

PrincipleDescription
Intent-FirstAgents declare desired outcomes, not specific endpoints
Payment-NativeEvery call has a payment rail; no free-tier ambiguity
Provider-AgnosticProviders register capabilities; protocol handles routing
Risk-AwareBuilt-in risk scoring prevents budget overruns and abuse
MCP-CompatibleAIP endpoints are also exposed as MCP tools for discoverability

Authentication

Two methods — choose one:

MethodHeaderWhen to use
API KeyAuthorization: Bearer <key>Managed billing — platform settles on-chain from your managed wallet
Private Key (x402)PAYMENT-SIGNATURE (or X-PAYMENT)Autonomous agents — agent signs payment directly with its own wallet

x402 Mode: The SDK automatically handles the 402 Payment Required → sign → retry flow. Your code looks the same — only initialization differs. Every request settles on-chain.

PAYMENT-SIGNATURE and X-PAYMENT are both accepted and carry the same base64 payload; PAYMENT-SIGNATURE wins if you send both.

Supported chains: Base (EVM 0x... private key) and Solana (Base58 private key). Solana is offered only when the fee payer is known — if the gateway has not yet resolved one, the 402 lists Base alone. The Go SDK is EVM-only today; use the Python SDK for Solana.

Read-only GETs are free; the POST forms are not

GET /v1/intent/resolve, /types, /discover and /v1/providers are public. The POST resolution and every execute path require auth — they consume embedding and upstream resources.


Supported Intent Types

Thirteen intent types are defined locally:

Intent TypeDescriptionTypical Price
chat_completionText generation / conversation$0.0001–0.05/call
image_generationAI image generation$0.015–0.11/call
video_generationAI video generationper second — see Video
text_to_speechSpeech synthesis$0.05–0.12/1k chars
web_searchWeb search$0.012/call
knowledge_searchVector knowledge base search$0.004–0.012/call
prompt_optimizationAI-powered prompt rewriting$0.002/call (flat)
code_generationCode writing / completion$0.001–0.05/call
translationText translation$0.0001–0.01/call
document_processingDocument parsing / extractionVaries
data_analysisStructured data analysisVaries
code_executionSandboxed code execution$0.001–0.012/call
utilityMiscellaneous utility servicesVaries

Network peers contribute more intent types on top of these (blockchain, geo, dns, email, storage, web, audio_generation, general, and others as peers join).

Always read the live list

GET /v1/intent/types returns the union of the local constants and every intent indexed from the provider registry, so it is authoritative and changes as peers come and go. Don't hardcode the table above.


API Endpoints

POST /v1/intent/resolve

Find the best providers for your intent without executing.

Request:

json
{
  "intent": "chat_completion",
  "constraints": {
    "max_price_usd": 0.05,
    "max_latency_ms": 3000,
    "features": ["function_calling", "json_mode"]
  },
  "preferences": {
    "optimize_for": "quality",
    "limit": 10
  }
}
FieldTypeDescription
intentstringRequired. Intent type identifier
querystringOptional free-text query used for semantic relevance scoring
constraints.max_price_usdnumberMust be positive if present
constraints.max_latency_msintegerMust be positive if present
constraints.featuresstring[]Required provider capabilities
preferences.optimize_forstringcost | quality | latency | budget
preferences.limitintegerMax matches to return (default 10)

Response:

json
{
  "matches": [
    {
      "provider_id": "deepseek/deepseek-chat",
      "score": 0.95,
      "estimated_price_usd": 0.0003,
      "pricing": { "input_per_million": 0.1, "output_per_million": 0.2 },
      "endpoint": "/v1/chat/completions",
      "model": "deepseek/deepseek-chat",
      "reason": "lowest cost: $0.000300/req"
    }
  ],
  "intent_type": "chat_completion",
  "total_available": 45
}
FieldDescription
matches[].provider_idProvider identifier (model ID, marketplace/x, or federation/<id>/<name>)
matches[].scoreComposite ranking score, 0–1
matches[].estimated_price_usdEstimated per-request cost. For token pricing this assumes a 500-in / 500-out request
matches[].pricingRaw rate card: input_per_million, output_per_million, or per_call
matches[].endpointPath to call for this provider
matches[].modelUpstream model name, when applicable
matches[].reasonHuman-readable explanation of the ranking
total_availableProviders matching the intent before constraint filtering

Resolutions are not reservations

There is no resolution_id and no expires_at — nothing is held for you. Resolve is a ranking query; prices can move between resolving and executing. preferred_providers, excluded_providers and a context block are not supported: filter on features and max_price_usd, or pick from matches yourself.

Method matters: GET /v1/intent/resolve is free and unauthenticated but only returns usage documentation. The ranked resolution is POST, which requires auth and consumes embedding resources.


POST /v1/intent/execute

The primary endpoint. Resolves the best provider, executes the request, settles payment, and returns the result — all in one call.

Request:

json
{
  "intent": "chat_completion",
  "constraints": { "max_price_usd": 0.05 },
  "preferences": { "optimize_for": "quality" },
  "payload": {
    "messages": [
      {"role": "system", "content": "You are a helpful assistant."},
      {"role": "user", "content": "Explain quantum computing in 3 sentences."}
    ],
    "temperature": 0.7,
    "max_tokens": 200
  }
}
FieldTypeDescription
intentstringIntent type. Required unless resource_id is set
resource_idintegerNetwork resource ID — selects a provider directly and skips resolution
payloadobjectBody forwarded to the provider. Optional for GET-style marketplace endpoints
constraints / preferencesobjectSame shape as /resolve
endpointstringSub-path within a multi-endpoint service, query string included
methodstringHTTP method for forwarding. Defaults to POST
headersobjectExtra headers to forward upstream

Routing is three-level: resource_id wins, then intent, and a request with neither is rejected with 400. Payment is settled by the x402 middleware before this handler runs; there is no payment object in the request body — the amount comes from the 402 challenge.

Response — local, marketplace and builtin providers:

The upstream response is passed through unmodified. For chat_completion that means a standard OpenAI-shaped completion:

json
{
  "id": "chatcmpl-abc123",
  "object": "chat.completion",
  "created": 1717200000,
  "model": "deepseek/deepseek-chat",
  "choices": [
    { "index": 0, "message": { "role": "assistant", "content": "Quantum computing leverages..." }, "finish_reason": "stop" }
  ],
  "usage": { "prompt_tokens": 24, "completion_tokens": 156, "total_tokens": 180 },
  "price": { "amount": "0.003200", "currency": "USD" }
}

Response — network providers:

Network execution is wrapped, because the gateway has to report its own settlement:

json
{
  "success": true,
  "data": { "...": "provider response body" },
  "tx_hash": "0xabc123...",
  "cost_usd": 0.0032,
  "upstream_cost": 0.0029,
  "latency_ms": 812,
  "settlement": {
    "tx_hash": "0xabc123...",
    "amount": "0.003200",
    "currency": "USDC",
    "chain": "base",
    "provider_used": "federation/532/Image Generate",
    "timestamp": "2026-07-08T10:30:00Z",
    "facilitator": "https://api.cdp.coinbase.com/platform/v2/x402",
    "attestation": {
      "intent_hash": "0x...",
      "result_hash": "0x...",
      "signer": "0x...",
      "signature": "0x..."
    }
  }
}

Two different response shapes

There is no execution_id or top-level provider_used, and no uniform result wrapper. Whether you get a passthrough body or the network envelope depends on which source the resolver picked — check for success/data to tell them apart. A settlement object only appears when an on-chain settlement actually happened.

If a network provider fails, the gateway falls back to a local provider serving the same intent. When no fallback exists it returns 502 with {error, detail, provider}.


POST /v1/intent/execute-budget

Same as Execute, but runs the full orchestrated pipeline with a hard budget cap: validate budget → score risk → pick a payment path → pre-deduct → execute → confirm or roll back. If the cost would exceed the cap, the request is rejected before execution.

Request:

json
{
  "intent": "chat_completion",
  "budget": {
    "max_total_usd": 0.50,
    "preferred_payment_method": "auto",
    "allow_overdraft": false
  },
  "payload": {
    "messages": [{"role": "user", "content": "Summarize this document..."}]
  }
}
FieldTypeDescription
budget.max_total_usdnumberRequired. Hard cap for this request
budget.preferred_payment_methodstringbalance | credit | crypto | auto (default auto)
budget.allow_overdraftbooleanPermit proceeding on credit when balance is short

No per-call or daily fields here

per_call_limit_usd and daily_limit_usd are not part of this request. Persistent caps live on the wallet — set them with PUT /v1/wallet/limits (per_request_max_usd, daily_max_usd, monthly_max_usd, auto_pause_below_usd). See Wallet & Treasury.

Response:

json
{
  "request_id": "b6f2c1de-...",
  "status": "success",
  "provider": "deepseek/deepseek-chat",
  "model": "deepseek/deepseek-chat",
  "result": { "...": "provider response" },
  "actual_cost_usd": 0.0032,
  "risk_level": "low",
  "duration_ms": 812,
  "settlement": {
    "id": "stl_b6f2c1de-..._9a1f...",
    "request_id": "b6f2c1de-...",
    "user_id": 42,
    "payer_address": "0x...",
    "decision": { "method": "crypto_x402", "quota_to_deduct": 1600, "reason": "..." },
    "actual_cost_usd": 0.0032,
    "status": "confirmed",
    "created_at": "2026-07-08T10:30:00Z",
    "confirmed_at": "2026-07-08T10:30:01Z"
  }
}

status is success, rejected, error, or risk_blocked. HTTP status follows: rejected and risk_blocked return 403, error returns 500. Note this endpoint's settlement is a SettlementRecord (internal accounting) — a different shape from the attested receipt returned by /execute on network calls.


POST /v1/intent/resolve/natural

Natural language resolution. Describe what you need in plain language and AIP uses embedding similarity with a keyword fallback to identify the intent and rank providers.

Resolves only — does not execute or charge

This endpoint returns matches. It does not run the request and does not settle payment. Take the provider you want from matches and call /v1/intent/execute (or the provider's endpoint) yourself.

Request:

json
{
  "query": "I want to generate an image of a cyberpunk city",
  "session_id": "optional-for-multi-turn-clarification",
  "constraints": { "max_price_usd": 0.10 },
  "preferences": { "optimize_for": "cost" }
}

query is required. constraints.max_price_usd and max_latency_ms must be positive when present. There is no budget field.

Response (resolved):

json
{
  "status": "resolved",
  "intent": "image_generation",
  "confidence": 0.96,
  "matches": [
    {
      "provider_name": "federation/532/Image Generate",
      "model": "",
      "intent": "image_generation",
      "score": 0.70,
      "price_usd": 0.0115,
      "latency_ms": 0,
      "endpoint": "/image-generate"
    }
  ]
}

Response (clarification needed):

json
{
  "status": "clarify",
  "session_id": "s_8f3a...",
  "clarify": {
    "question": "Did you want a still image or a video clip?",
    "options": ["image_generation", "video_generation"],
    "round": 1
  },
  "message": "Multiple intents matched with similar confidence."
}

status is one of resolved, clarify, budget_insufficient, no_match. On clarify, pass the returned session_id back with your follow-up query. options is a flat array of intent identifiers, not objects.


GET /v1/intent/audit

Retrieve the recent lifecycle log for AIP orchestration.

Takes no query parameters and returns the newest entries from an in-memory ring buffer (10,000 entries, persisted asynchronously).

Response:

json
{
  "entries": [
    {
      "timestamp": "2026-07-08T10:30:01.482Z",
      "request_id": "b6f2c1de-...",
      "user_id": 42,
      "event_type": "settlement_confirmed",
      "details": { "amount_usd": 0.0032, "tx_hash": "0xabc123..." }
    }
  ],
  "count": 142
}

event_type is a pipeline lifecycle event, not an intent name:

EventMeaning
intent_resolvedA provider was selected
budget_validatedBudget passed validation
risk_flaggedRisk scorer raised a concern
payment_routedPayment path chosen
pre_deductedFunds reserved
execution_started / execution_complete / execution_failedUpstream call lifecycle
settlement_confirmed / settlement_rolled_backFinal payment outcome

Not a paginated ledger

There is no total, page, or page_size, and no filtering by date or intent type. For spend history and per-model breakdowns use the analytics endpoints below, or GET /v1/wallet/history.


GET /v1/intent/types

List every intent type you can resolve against — the union of the locally-defined constants and every intent indexed from the provider registry, sorted. No authentication required.

json
{ "intent_types": ["audio_generation", "blockchain", "chat_completion", "code_execution", "..."] }

GET /v1/providers

List all registered providers with their metadata and rate cards. No authentication required.

json
{ "providers": [ { "id": "...", "name": "...", "intent_types": ["..."], "pricing": {}, "source": "federation" } ], "total": 3412 }

Path and payload size

This is /v1/providersnot /v1/intent/providers. The response is large (~1.6 MB with the current network size). To show a headline number, use GET /v1/network/stats instead.


GET /v1/network/stats

Aggregate counts only — the size of the resolvable network. Public, unauthenticated, and cheap to poll.

json
{
  "success": true,
  "data": {
    "total_providers": 3412,
    "by_source": { "federation": 3350, "marketplace": 15, "local": 47 },
    "intent_types": 21,
    "federation": { "servers": 128, "healthy_servers": 121, "resources": 3350 }
  }
}

Analytics

Spend and efficiency reporting. Scope is enforced server-side from the auth context, never from a client-supplied value. An API-token (sk-...) caller always sees only their own rows — user_id is ignored on this path, including for admin-owned tokens. Only admins signed in to the dashboard (session auth) can widen the scope with user_id (user_id=0 for global).

EndpointDescription
GET /api/analytics/aggregateAggregated spend and settlement rows
GET /api/analytics/qualityCache hit rate, error rate and latency per model
GET /api/analytics/insightsDeep-scan summary over consume and marketplace logs

Shared query parameters: period (24h, 7d default, 30d, 90d), group_by (any of day, model, api_source, principal_type, channel, group, client_id; defaults to day,model,api_source), model, user_id and filter_api_source / filter_principal_type / filter_client_id / filter_channel / filter_group.

AIP usage appears in these same rows tagged api_source="aip". The older /v1/aip/analytics/* endpoints have been removed.


Subscriptions (SSE)

EndpointMethodDescription
/v1/intent/subscribePOSTExecute an intent and stream the response over Server-Sent Events
/v1/intent/subscribeGETList your active subscriptions
/v1/intent/subscribe/:idDELETECancel a subscription

Events arrive as event: / data: pairs. Both SDKs wrap this — see SDK Reference.


Optimization Strategies

The optimize_for parameter controls provider selection:

ValueBehavior
costCheapest provider that meets constraints (default)
qualityHighest-scored provider (may cost more)
latencyLowest-latency provider
budgetWeights payment overhead heavily — for tight per-call budgets

Unknown values fall back to cost

speed and balance are not valid. An unrecognised value is silently treated as cost, so a typo costs you the behaviour you asked for without an error. Use latency, not speed.

When a query is supplied and the embedding backend is reachable, semantic relevance takes 55% of the final score and the price/quality/latency/reliability blend takes the rest. Without a query, the blend is used alone.


Settlement

An execution that settles on-chain returns a settlement object:

FieldDescription
tx_hashOn-chain transaction hash (verifiable on any block explorer)
amountExact amount settled in USDC
currencyAlways USDC
chainbase
provider_usedProvider that served the request
facilitatorThe x402 facilitator that processed the payment
timestampRFC 3339 UTC timestamp
attestationSigned receipt — present when an attestation key is configured

All settlements are fully on-chain and non-custodial. You can verify any transaction on the corresponding chain's block explorer.

Offline-verifiable attestation

When attestation is enabled, the receipt carries an EIP-712 signature you can check without trusting the gateway:

json
{
  "attestation": {
    "intent_hash": "0x...",
    "result_hash": "0x...",
    "signer": "0x...",
    "signature": "0x...",
    "canonical": { "scheme": "eip712", "domain": { "name": "JarvisClaw-AIP", "version": "1", "chainId": 8453 } }
  }
}

To verify: recompute intent_hash from the canonicalized request payload and result_hash from the exact response bytes (keccak256 both), recover the EIP-712 signer over SettlementReceipt(intent_hash, result_hash, provider_used, amount, currency, tx_hash, timestamp), and confirm it matches the signer advertised in /.well-known/agent-intent-protocol.jsonattestation.signer. Then check tx_hash on-chain.


Errors

AIP endpoints return a flat {"error": "<message>"} body. There is no stable machine-readable code field on this surface — match on HTTP status and, where you must, on the message text.

HTTP StatusWhenExample message
400Malformed body or invalid constraintmax_price_usd must be a positive value
400Neither resource_id nor intent suppliedeither resource_id or intent is required
401Auth context missing on a budget/network callauthentication required
402x402 payment needed (SDKs handle this automatically)402 challenge body — see x402
402Network settlement failed... settle ...
403Budget rejected or risk-blocked (/execute-budget)status: "rejected" / "risk_blocked"
404No provider matches the intentno matching provider for intent
404resource_id not in registryresource 532 not found in registry
429Rate limitedrecommend rate limit exceeded (20 req/min), try again later
500Resolver or orchestrator failurestatus: "error"
502Upstream execution failed with no fallbackexecution failed / federation execution failed, no local fallback available
503Peer disabled or unhealthy... unhealthy ...

/execute-budget reports outcomes in the response status field as well as the HTTP status, so check both: success, rejected, error, risk_blocked.


Platform Services

Beyond the standard intents (chat_completion, web_search, etc.), AIP can call platform-hosted services directly — for example, the surf market-data service. These are invoked through the same /v1/intent/execute endpoint.

A platform service usually exposes several functional endpoints (price lookups, trading-pair info, and so on). Use intent to select the service category and endpoint to pick a specific function path:

bash
curl -X POST https://api.jarvisclaw.ai/v1/intent/execute \
  -H "Authorization: Bearer $JC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "intent": "web_search",
    "endpoint": "exchange/price?pair=BTC-USDT",
    "method": "GET"
  }'

Response (HTTP 200):

json
{
  "success": true,
  "data": { "pair": "BTC-USDT", "price": "64251.94" }
}
FieldDescription
intentIntent category the service maps to
endpointFunction path within the service (query params included)
methodHTTP method. Defaults to POST — pass GET explicitly for data reads

Intents map to these service base paths:

IntentBase path
web_search/v1/marketplace/surf
knowledge_search/v1/marketplace/exa
image_generation/v1/images/generations
video_generation/v1/videos/generations
text_to_speech/v1/audio/speech
prompt_optimization/v1/prompt-coach/optimize
everything else/v1/chat/completions

A provider registered with its own explicit endpoint uses that instead of the table above.

Billing

Like every AIP call, platform services are settled per-call on-chain via x402 (USDC). Cost is charged precisely at execution time.


Network

AIP supports a shared resource network — multiple platforms share resources through peer discovery. Any platform serving .well-known/agent-intent-protocol.json can join the network.

How It Works

  1. Platforms register as peers by domain
  2. A sync crawler visits each peer's .well-known endpoint on a recurring interval (30 minutes by default)
  3. Resources from all peers are aggregated into a unified catalog
  4. Agents discover and execute network resources through the same API

Network Endpoints

EndpointMethodAuthDescription
/v1/network/searchGETNoneFull-text search across network resources
/v1/network/apisGETNoneBrowse all network resources
/v1/network/serversGETNoneList network peers
/v1/network/healthGETNoneHealth status of all peers
/v1/network/recommendPOSTNone (deep tier: x402)Resource recommendation
/v1/network/executePOSTRequiredExecute a network resource

Search (keyword):

bash
curl "https://api.jarvisclaw.ai/v1/network/search?q=stock&category=finance&limit=5"

Recommend (natural language discovery):

json
POST /v1/network/recommend
{
  "query": "I need to analyze stock market data",
  "category": "finance",
  "max_results": 5,
  "min_score": 0.5,
  "healthy_only": true
}

query is required — the field is not called intent, and the result cap is max_results, not limit. Response:

json
{
  "query": "I need to analyze stock market data",
  "results": [ { "resource": { "...": "..." }, "server_name": "...", "server_url": "...", "score": 0.82 } ],
  "count": 5,
  "cached": false,
  "tier": "standard"
}

Two recommend tiers

The default standard tier is free and keyword-scored, rate limited to 20 requests/minute per caller. Pass X-Recommend-Tier: deep (or ?tier=deep) for LLM-enhanced semantic ranking at $0.01 per call via x402 — without a payment header that tier returns 402. Identical queries are served from cache.

Execute a network resource:

json
POST /v1/network/execute
{
  "resource_id": 532,
  "payload": {"ticker": "AAPL"}
}

resource_id is the numeric id from /v1/network/apis — not a slug like "stock-analysis". You may pass intent instead to let the resolver pick a resource. The request body is the same ExecuteRequest shape used by /v1/intent/execute, so endpoint, method and headers work here too.

Becoming a Network Peer

  1. Serve GET /.well-known/agent-intent-protocol.json with your metadata
  2. Implement a resource execution endpoint accepting x402 payment
  3. Contact us to register your domain

Minimum .well-known schema:

json
{
  "aip_version": "1.0",
  "platform_name": "Your Platform",
  "base_url": "https://your-platform.example.com",
  "capabilities": ["resolve", "execute", "federation"],
  "resources": [
    {
      "id": "your-resource-id",
      "name": "Your Resource Name",
      "category": "category",
      "description": "What this resource does",
      "price_per_call": "0.005",
      "currency": "USDC"
    }
  ],
  "payment": {
    "x402": {
      "facilitator": "https://api.cdp.coinbase.com/platform/v2/x402",
      "networks": ["base"],
      "supported": true
    }
  },
  "contact": "https://t.me/JarvisClawai"
}

facilitator should point at the x402 facilitator that settles your payments — for CDP-based setups that is https://api.cdp.coinbase.com/platform/v2/x402. Peers are health-checked; an unhealthy peer's resources stop being offered until it recovers.


MCP Compatibility

Part of the AIP surface is exposed as MCP tools. Names are flat, aip_-prefixed identifiers:

MCP ToolMaps to
aip_resolvePOST /v1/intent/resolve
aip_execute_with_budgetPOST /v1/intent/execute-budget
aip_list_intentsGET /v1/intent/types
aip_estimate_costLocal cost estimate — no direct HTTP equivalent

Alongside the general gateway tools list_models, chat, search_apis, get_api_detail, discover_agents, and one uapi_{slug} tool per published user API. See MCP Configuration.

Not every endpoint is an MCP tool

/v1/intent/execute, /v1/intent/resolve/natural and /v1/intent/audit have no MCP tool — call them over HTTP.


Endpoint Summary

EndpointMethodAuthDescription
/v1/intent/resolveGETNoneUsage documentation for the POST form
/v1/intent/resolvePOSTRequiredRank providers for an intent
/v1/intent/resolve/naturalPOSTRequiredNatural-language resolution (no execution)
/v1/intent/discoverGETNoneDiscover intents and providers
/v1/intent/discoverPOSTRequiredSemantic discovery over embeddings
/v1/intent/executePOSTRequiredResolve + execute + settle
/v1/intent/execute-budgetPOSTRequiredOrchestrated execution with a budget cap
/v1/intent/subscribePOSTRequiredExecute and stream over SSE
/v1/intent/subscribeGETRequiredList active subscriptions
/v1/intent/subscribe/:idDELETERequiredCancel a subscription
/v1/intent/auditGETRequiredRecent orchestration lifecycle log
/v1/intent/typesGETNoneList intent types
/v1/providersGETNoneList providers with rate cards
/v1/network/statsGETNoneAggregate network size
/api/analytics/*GETRequiredSpend aggregate, quality metrics, insights
/v1/network/searchGETNoneKeyword search across network resources
/v1/network/apisGETNoneBrowse network resources
/v1/network/serversGETNoneList network peers
/v1/network/healthGETNonePeer health status
/v1/network/recommendPOSTNone (deep: x402)Resource recommendation
/v1/network/executePOSTRequiredExecute a network resource
/v1/aip/federation/peersGET/POST/DELETEAdminManage peers
/v1/aip/federation/crawlPOSTAdminTrigger a peer sync
/v1/wallet/*GET/PUTRequiredBalance, history, limits, pools
/.well-known/agent-intent-protocol.jsonGETNonePlatform discovery