एजेंटिक वेब प्रोटोकॉल (AWP)

ADK-Rust Agentic Web Protocol (AWP) प्रकार और वेबसाइटों तथा सेवाओं को AI एजेंटों के लिए सुलभ बनाने हेतु Axum एकीकरण प्रदान करता है। कार्यान्वयन दो crates में फैला है: awp-types (शुद्ध प्रोटोकॉल प्रकार) और adk-awp (रूट्स, मिडलवेयर, और सेवा इंटरफेस)। अनुप्रयोग एजेंट डिस्पैच, प्रमाणीकरण, प्राधिकरण, और स्थायी वेबहुक डिलीवरी प्रदान करते हैं।

अवलोकन

AWP किसी भी वेबसाइट को अपनी क्षमताओं, नीतियों, और व्यावसायिक संदर्भ को मशीन-पठनीय प्रारूप में घोषित करने में सक्षम बनाता है। AI एजेंट इन क्षमताओं की खोज कर सकते हैं, प्रोटोकॉल संस्करणों पर बातचीत कर सकते हैं, घटनाओं की सदस्यता ले सकते हैं, और टाइप किए गए A2A संदेशों के माध्यम से इंटरैक्ट कर सकते हैं। adk-awp अपने HTTP सीमा पर body और rate limits लागू करता है; application handlers पहचान और capability authorization लागू करते हैं।

AWP का उपयोग तब करें जब:

  • आप चाहते हैं कि AI एजेंट आपके सेवा को प्रोग्रामेटिक रूप से खोजें और उससे इंटरैक्ट करें
  • आपको trust-level मेटाडेटा और application-enforced access control के लिए एक hook चाहिए
  • आप मानव आगंतुकों और AI एजेंटों दोनों को एक ही endpoints से सेवा देना चाहते हैं
  • आपको event subscriptions और HMAC-SHA256 signing primitives की आवश्यकता है
  • आप service monitoring के लिए एक health state machine चाहते हैं

आर्किटेक्चर

AWP अनुरोध प्रवाह

Rendering architecture…

एप्लिकेशन लेआउट

┌─────────────────────────────────────────────────┐
│                  Your Application                │
│                                                  │
│  ┌──────────────┐  ┌──────────────────────────┐ │
│  │  LLM Agent   │  │  awp_routes(state)       │ │
│  │  (adk-agent) │  │  ├ /.well-known/awp.json │ │
│  │              │  │  ├ /awp/manifest          │ │
│  │  Instructions│  │  ├ /awp/health            │ │
│  │  derived from│  │  └ /awp/a2a              │ │
│  │  business.   │  │  auth + management routes│ │
│  │  toml        │  │                           │ │
│  └──────────────┘  └──────────────────────────┘ │
│         ▲                      ▲                 │
│         │                      │                 │
│    ┌────┴──────────────────────┴────┐            │
│    │     BusinessContextLoader      │            │
│    │     (business.toml + ArcSwap)  │            │
│    └────────────────────────────────┘            │
└─────────────────────────────────────────────────┘

Crates

क्रेटउद्देश्यनिर्भरताएँ
awp-typesप्रोटोकॉल प्रकार (एनम, स्ट्रक्ट, त्रुटियाँ)शून्य adk-* निर्भरताएँ — serde, uuid, chrono, thiserror केवल
adk-awpरूट्स, मिडलवेयर, सेवा इंटरफेस, और इन-मेमोरी कार्यान्वयनawp-types, adk-core, axum 0.8, tokio, dashmap

विभाजन का मतलब है कि कोई भी Rust प्रोजेक्ट awp-types पर निर्भर हो सकता है, बिना ADK ट्री को शामिल किए।

त्वरित शुरुआत

1. एक business.toml बनाएं

site_name = "My Shop"
site_description = "An online store powered by AWP"
domain = "myshop.example.com"
contact = "hello@myshop.example.com"

[business]
country = "US"
currency = "USD"
languages = ["en"]

[brand_voice]
tone = "friendly and helpful"
greeting = "Welcome! How can I help?"

[[capabilities]]
name = "browse_products"
description = "Browse the product catalog"
endpoint = "/api/products"
method = "GET"
access_level = "anonymous"

[[capabilities]]
name = "place_order"
description = "Place an order"
endpoint = "/api/orders"
method = "POST"
access_level = "known"

[[products]]
sku = "WIDGET-001"
name = "Standard Widget"
price = 1999
inventory = 500
tags = ["widget"]

[[policies]]
name = "privacy"
description = "Minimal data collection, no tracking."
policy_type = "privacy"

[payments]
providers = ["stripe"]
auto_approve_threshold = 5000

[support]
escalation_contacts = ["support@myshop.example.com"]
hours = "Mon-Fri 9-5 EST"

2. AWP रूट्स लोड करें और सर्व करें

use std::sync::Arc;

use adk_awp::{AwpA2aHandler, AwpState, BusinessContextLoader, awp_routes};
use async_trait::async_trait;
use awp_types::AwpError;
use axum::http::{HeaderMap, header};
use serde_json::{Value, json};

struct ApplicationA2a {
    bearer_token: Arc<str>,
}

#[async_trait]
impl AwpA2aHandler for ApplicationA2a {
    async fn handle(&self, headers: HeaderMap, message: Value) -> Result<Value, AwpError> {
        let expected = format!("Bearer {}", self.bearer_token);
        let authorized = headers
            .get(header::AUTHORIZATION)
            .and_then(|value| value.to_str().ok())
            .is_some_and(|value| value == expected);
        if !authorized {
            return Err(AwpError::Unauthorized("invalid A2A credential".to_string()));
        }
        // Authorize the requested capability and dispatch to the application agent.
        Ok(json!({ "status": "processed", "messageId": message["id"] }))
    }
}

let loader = BusinessContextLoader::from_file("business.toml".as_ref())?;
let a2a_token: Arc<str> = std::env::var("AWP_A2A_TOKEN")?.into();
let state = AwpState::builder(loader.context_ref())
    .a2a_handler(Arc::new(ApplicationA2a { bearer_token: a2a_token }))
    .build();

let app = axum::Router::new()
    .merge(awp_routes(state))
    .merge(your_custom_routes);

let listener = tokio::net::TcpListener::bind("127.0.0.1:3456").await?;
axum::serve(
    listener,
    app.into_make_service_with_connect_info::<std::net::SocketAddr>(),
)
.await?;

यह संस्करण-वार्ता, दर-सीमांकन, और 64 KiB A2A बॉडी सीमा के साथ चार सार्वजनिक AWP एंडपॉइंट्स पंजीकृत करता है। बिना एक AwpA2aHandler के, POST /awp/a2a 503 लौटाता है और उस कार्य को कभी स्वीकार नहीं करता जो डिस्पैच नहीं किया गया था। ConnectInfo सहकर्मी पता प्रदान करता है, जिसका उपयोग गुमनाम दर-सीमा बकेट्स को अलग करने के लिए किया जाता है; इसके बिना, अज्ञात कॉलर जानबूझकर एक ही बकेट साझा करते हैं।

सार्वजनिक AWP एंडपॉइंट्स

विधिपथविवरण
GET/.well-known/awp.jsonडिस्कवरी दस्तावेज़ — एजेंटों के लिए प्रवेश बिंदु
GET/awp/manifestJSON-LD क्षमता मैनिफेस्ट
GET/awp/healthस्वास्थ्य स्थिति (Healthy/Degrading/Degraded)
POST/awp/a2aएप्लिकेशन-प्रदानित A2A dispatch

प्रमाणित प्रबंधन एंडपॉइंट्स

awp_management_routes() सदस्यता प्रबंधन को अलग से और बिना किसी प्रमाणीकरण परत के लौटाता है। इसे मर्ज करने से पहले एप्लिकेशन के auth middleware लागू करें:

विधिपथविवरण
POST/awp/events/subscribeएक webhook subscription बनाएँ
GET/awp/events/subscriptionsसभी subscriptions की सूची बनाएँ
DELETE/awp/events/subscriptions/{id}एक सदस्यता हटाएँ

डिस्कवरी दस्तावेज़

/.well-known/awp.json पर स्थित डिस्कवरी दस्तावेज़ आपके business.toml से स्वचालित रूप से जनरेट होता है:

{
  "version": { "major": 1, "minor": 0 },
  "siteName": "My Shop",
  "siteDescription": "An online store powered by AWP",
  "capabilityManifestUrl": "https://myshop.example.com/awp/manifest",
  "a2aEndpointUrl": "https://myshop.example.com/awp/a2a",
  "eventsEndpointUrl": "https://myshop.example.com/awp/events/subscribe",
  "healthEndpointUrl": "https://myshop.example.com/awp/health",
  "supportedTrustLevels": ["anonymous"]
}

क्षमता मैनिफेस्ट

/awp/manifest पर स्थित मैनिफेस्ट JSON-LD फ़ॉर्मेट का उपयोग करता है:

{
  "@context": "https://schema.org",
  "@type": "WebAPI",
  "name": "My Shop",
  "description": "An online store powered by AWP",
  "capabilities": [
    {
      "name": "browse_products",
      "description": "Browse the product catalog",
      "endpoint": "/api/products",
      "method": "GET"
    }
  ]
}

विश्वास स्तर

AWP बढ़ती पहुँच के साथ चार विश्वास स्तरों का उपयोग करता है:

स्तरविभेदककैसे असाइन किया गया
Anonymous0कोई क्रेडेंशियल नहीं
Known1मान्य API कुंजी या JWT
Partner2JWT के साथ partner स्कोप
Internal3JWT के साथ internal स्कोप

विश्वास स्तर क्रमबद्ध हैं: Anonymous < Known < Partner < Internal. business.toml में प्रत्येक capability अपना न्यूनतम access_level घोषित करती है।

DefaultTrustAssigner हर अनुरोध को Anonymous के रूप में वर्गीकृत करता है। एक bearer या API key header तब तक विश्वसनीय नहीं माना जाता जब तक कोई application verifier उसे मान्य न कर दे। इसलिए उच्च trust levels के लिए एक custom assigner आवश्यक होता है।

उस assigner के साथ .supported_trust_levels(...) को भी configure करें ताकि discovery केवल वही levels advertise करे जिन्हें deployment सत्यापित कर सकता है।

Custom Trust Assignment

कस्टम logic के लिए TrustLevelAssigner trait को implement करें:

use std::sync::Arc;

use adk_awp::TrustLevelAssigner;
use async_trait::async_trait;
use awp_types::TrustLevel;
use axum::http::{HeaderMap, header};

struct MyTrustAssigner {
    bearer_token: Arc<str>,
}

#[async_trait]
impl TrustLevelAssigner for MyTrustAssigner {
    async fn assign(&self, headers: &HeaderMap) -> TrustLevel {
        let expected = format!("Bearer {}", self.bearer_token);
        if headers
            .get(header::AUTHORIZATION)
            .and_then(|value| value.to_str().ok())
            .is_some_and(|value| value == expected)
        {
            TrustLevel::Known
        } else {
            TrustLevel::Anonymous
        }
    }
}

Partner या Internal assign करते समय, application के बाकी हिस्से के समान ही verified identity और scope source का उपयोग करें।

Rate Limiting

Built-in InMemoryRateLimiter per-trust-level limits के साथ sliding window algorithm का उपयोग करता है:

विश्वसनीयता स्तरडिफ़ॉल्ट सीमा
अनाम30 अनुरोध/मिनट
ज्ञात120 अनुरोध/मिनट
भागीदार600 अनुरोध/मिनट
आंतरिकअसीमित

Rejected requests receive HTTP 429 with a Retry-After header.

कस्टम सीमाएँ

use std::collections::HashMap;
use awp_types::TrustLevel;
use adk_awp::{InMemoryRateLimiter, RateLimitConfig};

let mut limits = HashMap::new();
limits.insert(TrustLevel::Anonymous, RateLimitConfig {
    max_requests: 10,
    window_secs: 60,
});
limits.insert(TrustLevel::Known, RateLimitConfig {
    max_requests: 100,
    window_secs: 60,
});

let limiter = InMemoryRateLimiter::with_config(limits);

संस्करण नेगोशिएशन

सभी AWP routes में version negotiation middleware शामिल है:

  • Clients AWP-Version: 1.1 header भेजते हैं (optional — defaults to current version)
  • Server major version compatibility की जाँच करता है
  • Compatible requests आगे बढ़ते हैं; incompatible requests को HTTP 406 मिलता है
  • Malformed version values को HTTP 400 मिलता है
  • Response में AWP-Version: 1.0 header शामिल होता है

इवेंट सब्सक्रिप्शन

Subscription management एक privileged surface है. Accept करने से पहले authentication के पीछे awp_management_routes() को mount करें। Callback URLs absolute HTTPS URLs होना चाहिए और signing secrets में कम से कम 32 bytes होने चाहिए:

# Subscribe
curl -X POST http://localhost:3456/awp/events/subscribe \
  -H "Authorization: Bearer $AWP_ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "subscriber": "my-agent",
    "callbackUrl": "https://my-agent.example/webhook",
    "eventTypes": ["health.changed"],
    "secret": "replace-with-at-least-32-random-bytes"
  }'

# List subscriptions
curl -H "Authorization: Bearer $AWP_ADMIN_TOKEN" \
  http://localhost:3456/awp/events/subscriptions

InMemoryEventSubscriptionService matching deliveries पर sign और log करता है लेकिन कोई network I/O नहीं करता। Production applications destination validation, एक durable queue, bounded retries, और अपना HTTP client के साथ EventSubscriptionService implement करती हैं।

एक HTTP delivery implementation HMAC-SHA256 signature के साथ एक X-AWP-Signature header carry कर सकती है:

X-AWP-Signature: sha256=<hex_digest>

Signatures को adk_awp::verify_signature(payload, secret, signature) के साथ verify करें।

Health State Machine

Health endpoint service state को strictly validated transitions के साथ track करता है:

Healthy → Degrading → Degraded
    ↑         │           │
    └─────────┘           │
    └─────────────────────┘

State changes सभी matching subscribers को health.changed events emit करती हैं।

use adk_awp::HealthStateMachine;

// Transition to degrading
health.report_degrading("database latency high").await?;

// Transition to degraded
health.report_degraded("database unreachable").await?;

// Recover
health.report_healthy().await?;

Invalid transitions (e.g., Healthy → Degraded) error return करते हैं।

AWP में एक consent storage interface शामिल है। Regulatory compliance के लिए application-specific notice, lawful basis, retention, access controls, और deletion policy भी आवश्यक हैं; किसी storage implementation को चुनना compliance स्थापित नहीं करता:

use adk_awp::InMemoryConsentService;

let consent = InMemoryConsentService::new();

// Capture consent
consent.capture_consent("visitor-123", "analytics").await?;

// Check consent
let has_consent = consent.check_consent("visitor-123", "analytics").await?;

// Revoke consent
consent.revoke_consent("visitor-123", "analytics").await?;

Requester Type Detection

AWP यह detect करता है कि request किसी human से आई है या किसी AI agent से:

  1. X-AWP-Channel: agent header → Agent (explicit override)
  2. Accept: application/json + agent User-Agent pattern → Agent
  3. Otherwise → Human

Agent User-Agent patterns: bot, crawler, spider, agent, gpt, claude, gemini, perplexity, anthropic, openai.

use adk_awp::detect_requester_type;
use axum::http::HeaderMap;

let mut headers = HeaderMap::new();
headers.insert("X-AWP-Channel", "agent".parse().unwrap());
let requester = detect_requester_type(&headers);
// RequesterType::Agent

AWP संदेश प्रकार

Generic A2A messages से आगे, AWP agent routing के लिए typed message categories परिभाषित करता है:

प्रकारविवरण
VisitorIntentSignalखरीद या सेवा का इरादा
ContentGapSignalगायब या पुरानी सामग्री का पता चला
PaymentIntentभुगतान जीवनचक्र संदेश
SupportEscalationमानव सहायता को एस्केलेशन
ReviewSignalकिसी प्लेटफ़ॉर्म से समीक्षा या प्रतिक्रिया
OperationsProposalइन्वेंटरी, शेड्यूलिंग प्रस्ताव
InvokeCapabilityघोषित क्षमता को कॉल करें
RenderUiUI रेंडरिंग का अनुरोध करें
OutboundTriggerसक्रिय आउटबाउंड संदेश
use awp_types::{AwpMessageType, AwpTypedMessage};

let msg = AwpTypedMessage {
    id: uuid::Uuid::now_v7(),
    sender: "visitor-agent".to_string(),
    recipient: "payment-agent".to_string(),
    awp_type: AwpMessageType::PaymentIntent,
    timestamp: chrono::Utc::now(),
    payload: serde_json::json!({"sku": "WIDGET-001", "amount": 2500}),
};

भुगतान इरादे

AWP स्वामी-नीति-संचालित भुगतानों के लिए एक सरलीकृत भुगतान जीवनचक्र परिभाषित करता है:

Draft → PendingApproval → Approved → Executing → Settled
                                                → Rejected
                                                → Cancelled

PaymentPolicy यह मूल्यांकन करता है कि स्वतः अनुमोदन करना है या स्वामी अनुमोदन आवश्यक है:

use awp_types::{PaymentPolicy, TrustLevel};

let policy = PaymentPolicy::default(); // $50 auto-approve, $500 require approval

let decision = policy.evaluate(2500, TrustLevel::Known);
// PaymentPolicyDecision::AutoApprove (amount $25 <= $50 threshold)

let decision = policy.evaluate(60_000, TrustLevel::Partner);
// PaymentPolicyDecision::RequireApproval (amount $600 > $500 threshold)

business.toml स्कीमा

पूर्ण स्कीमा समृद्ध व्यावसायिक कॉन्फ़िगरेशन का समर्थन करता है:

अनुभागफ़ील्डआवश्यक
(मूल)site_name, site_description, domain, contactहाँ (संपर्क को छोड़कर)
[business]name, country, languages, currency, timezoneनहीं
[brand_voice]tone, greeting, escalation_messageनहीं
[[products]]sku, name, price, inventory, tags, descriptionनहीं
[[capabilities]]name, description, endpoint, method, access_levelहाँ
[[policies]]name, description, policy_typeहाँ
[channels]whatsapp, email, website, smsनहीं
[payments]providers, auto_approve_threshold, require_approval_thresholdनहीं
[support]escalation_contacts, hours, slaनहीं
[content]topics, auto_draft, publish_delayनहीं
[reviews]platforms, auto_respond_thresholdनहीं
[outreach]follow_up_delay, require_consentनहीं

सभी विस्तारित अनुभाग वैकल्पिक हैं — मौजूदा न्यूनतम business.toml फ़ाइलें काम करती रहती हैं।

हॉट रीलोड

BusinessContextLoader, ArcSwap के माध्यम से हॉट-रीलोड का समर्थन करता है:

let loader = BusinessContextLoader::from_file("business.toml".as_ref())?;
loader.watch("business.toml".into()).await?;
// Changes to business.toml are picked up automatically every 5 seconds

उदाहरण चलाना

एक पूर्ण AWP एजेंट उदाहरण शामिल है:

cd examples/awp_agent
cp .env.example .env   # add your GOOGLE_API_KEY
cargo run

उदाहरण:

  1. उत्पादों, नीतियों, और ब्रांड वॉइस के साथ business.toml लोड करता है
  2. व्यावसायिक संदर्भ से निकाले गए निर्देशों के साथ एक LLM एजेंट बनाता है
  3. उस एजेंट के लिए प्रमाणित A2A डिस्पैच स्थापित करता है
  4. एक अलग डेमो क्रेडेंशियल के पीछे प्रबंधन रूट्स माउंट करता है
  5. हर एंडपॉइंट का परीक्षण करता है और प्रोटोकॉल सत्यापन प्रिंट करता है

सर्वोत्तम प्रथाएँ

  1. न्यूनतम business.toml से शुरू करें — केवल site_name, site_description, domain, क्षमताएँ, और नीतियाँ आवश्यक हैं
  2. क्षमता प्राधिकरण लागू करेंaccess_level मैनिफ़ेस्ट मेटाडेटा है; एप्लिकेशन हैंडलर को इसे लागू करना होगा
  3. उत्पादन में हॉट-रीलोड सक्षम करें — बिना डाउनटाइम कॉन्फ़िग अपडेट के लिए loader.watch() कॉल करें
  4. कस्टम TrustLevelAssigner लागू करें — डिफ़ॉल्ट जानबूझकर केवल Anonymous असाइन करता है
  5. प्रबंधन रूट्स को प्रमाणित करें — असुरक्षित राउटर से कभी भी सब्सक्रिप्शन CRUD उजागर न करें
  6. वास्तविक A2A डिस्पैच स्थापित करें — फ़ेल-क्लोज़्ड डिफ़ॉल्ट 503 लौटाता है
  7. स्थायी इवेंट डिलीवरी का उपयोग करें — डेस्टिनेशन नीति, क्यूइंग, और सीमित पुनःप्रयास लागू करें
  8. वेबहुक हस्ताक्षरों की पुष्टि करें — आने वाले वेबहुक पर X-AWP-Signature सत्यापित करें

पिछला: ← A2A प्रोटोकॉल | अगला: मूल्यांकन →