Skip to content

Latest commit

 

History

History
409 lines (291 loc) · 9.62 KB

File metadata and controls

409 lines (291 loc) · 9.62 KB

AAIP Usage Guide (v2)

A practical guide for implementing the AI Agent Identification Protocol.


Quick Start

Add identity to your requests:

headers = {
    "AI-Agent": "OpenAI/GPT-5.2 (Atlas; 1.0) [aid=myapp-001]"
}

That's it for minimal compliance. Add capabilities when appropriate.


Building Your Identity String

Step 1: Vendor and Model (Required)

OpenAI/GPT-5.2
Anthropic/claude-4.5-opus
Google/gemini-3-pro-preview
Meta/llama-3-70b
YourCompany/custom-model

If model unknown:

Vendor/unknown

Step 2: Application Context (Required)

(MyApp; 1.0.0)
(LangChain; 0.2.0)
(InternalBot; 2025.01)
(Tool; unknown)       # Version not available
(SecretApp; redacted) # Intentionally withheld

Combined:

OpenAI/GPT-5.2 (MyApp; 1.0.0)

Step 3: Agent ID (Optional but Recommended)

Stable identifier for analytics and allowlists:

[aid=myapp-prod-001]
[aid=a1b2c3d4e5f6]

Combined:

OpenAI/GPT-5.2 (MyApp; 1.0.0) [aid=myapp-prod-001]

Step 4: Capabilities (Optional)

Use coarse levels by default:

Level Meaning
cap:readonly Read-only, no side effects
cap:browse Web browsing, API calls
cap:execute Code execution, file modification
AI-Agent-Capabilities: cap:browse

Detailed (when safe):

AI-Agent-Capabilities: cap:execute;tools:bash,python;mcp:github

Code Examples

Python (requests)

import requests

headers = {
    "AI-Agent": "OpenAI/GPT-5.2 (MyBot; 1.0) [aid=mybot-001]",
    "AI-Agent-Capabilities": "cap:browse"
}

response = requests.get("https://api.example.com/data", headers=headers)

Python (httpx async)

import httpx

headers = {
    "AI-Agent": "Anthropic/claude-4.5 (AsyncBot; 2.0) [aid=async-001]",
    "AI-Agent-Capabilities": "cap:execute;tools:web_search"
}

async with httpx.AsyncClient(headers=headers) as client:
    response = await client.get("https://example.com")

JavaScript (fetch)

const headers = {
  "AI-Agent": "OpenAI/GPT-5.2 (WebApp; 1.0) [aid=webapp-001]",
  "AI-Agent-Capabilities": "cap:readonly"
};

const response = await fetch("https://example.com/api", { headers });

gRPC (Python)

import grpc

metadata = [
    ('x-ai-agent', 'OpenAI/GPT-5.2 (MyApp; 1.0) [aid=grpc-001]'),
    ('x-ai-agent-capabilities', 'cap:execute'),
]

response = stub.MyMethod(request, metadata=metadata)

cURL

curl -H "AI-Agent: OpenAI/GPT-5.2 (CLI; 1.0) [aid=cli-001]" \
     -H "AI-Agent-Capabilities: cap:browse" \
     https://example.com/api

When to Use AAIP

Note: Not all AI agents make network requests. AAIP applies to agents that interact with external services, regardless of autonomy level.

Scenario Use AAIP?
Browsing websites ✅ Yes
Calling external APIs ✅ Yes
Using MCP servers ✅ Yes
gRPC service calls ✅ Yes
Internal function calls only ⚪ Optional
User-initiated browser requests ❌ No (that's User-Agent)
Local-only operations ❌ N/A

General rule: If your AI agent interacts with external services—whether autonomous, semi-autonomous, or human-directed—include identity.


Agentic AI Browsers

Browser products (or browser-embedded agents) that can autonomously navigate and act on pages—not just fetch URLs—require special consideration for AAIP.

AAIP is Additive to User-Agent

The browser will still send a conventional User-Agent string identifying the browser engine. AAIP is the agent identity and SHOULD be sent as additional headers on every navigation request.

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0
AI-Agent: Perplexity/sonar-2 (Comet; 1.0) [aid=comet-prod]

Deployment Models

Model Description Examples
Embedded Agent Browser Browser product itself is agentic Perplexity Comet, Opera Browser Operator
Remote Agent + Browser Agent uses "its own browser" for tasks OpenAI Operator
Agentic Feature in Browser Mainstream browser with AI feature Arc Max, Opera AI features

Recommended AAIP Fields for Browsers

Field How to Populate
vendor/model The agent decision engine when known; use unknown if not introspectable
(<application>; <version>) The browser product (Comet, Operator) or controlling agent app
aid= Identifies the agent instance/deployment, NOT the end user

Pattern A: Embedded AI Browser

The browser product itself is agentic. The "application" is the browser.

Example: Perplexity Comet

# Model known
AI-Agent: Perplexity/sonar-2 (Comet; 1.0) [aid=comet-prod]
AI-Agent-Capabilities: cap:browse

# Model not reliably knowable
AI-Agent: Perplexity/unknown (Comet; 1.0) [aid=comet-prod]
AI-Agent-Capabilities: cap:browse

Pattern B: Remote Agent Using Its Own Browser

An agent that explicitly uses its own browser instance.

Example: OpenAI Operator

AI-Agent: OpenAI/GPT-5.2 (Operator; 2026.01) [aid=operator-prod]
AI-Agent-Capabilities: cap:browse

Pattern C: Agentic Feature Inside Mainstream Browser

A mainstream browser with an agentic AI feature.

Example: Opera Browser Operator

AI-Agent: Opera/unknown (Opera-Browser-Operator; 1.0) [aid=opera-operator]
AI-Agent-Capabilities: cap:browse

Example: Arc Max

AI-Agent: Arc/unknown (Arc-Max; 1.5) [aid=arc-max]
AI-Agent-Capabilities: cap:browse

Implementation in Agentic Browsers

Rule: AAIP MUST be attached at the network boundary that actually emits requests.

Browser Stack Implementation
Puppeteer/Playwright-like Attach as extra request headers (sent with every request)
Browser extension Inject via webRequest.onBeforeSendHeaders
Proxy-based Inject headers at proxy layer
Cannot set headers Use fallback: WebSocket first message, proxy injection

Puppeteer note: Extra headers are sent with every request and header names are lowercased.

// Puppeteer / internal automation
await page.setExtraHTTPHeaders({
  'ai-agent': 'Perplexity/sonar-2 (Comet; 1.0) [aid=comet-prod]',
  'ai-agent-capabilities': 'cap:browse'
});

Verification for Agentic Browsers

Some ecosystems (e.g., Operator) already authenticate agent requests using HTTP message signatures. AAIP pairs well with this:

AI-Agent: OpenAI/GPT-5.2 (Operator; 2026.01) [aid=operator-prod]
AI-Agent-Signature: ed25519=<signature>

See VERIFICATION.md for signature and JWT options.


Best Practices

DO ✅

  • Use accurate vendor/model names
  • Keep aid stable across versions
  • Update application version with releases
  • Use coarse capability levels by default
  • Include identity on all external requests

DON'T ❌

  • Impersonate other vendors
  • Include user identifiers
  • Over-disclose capabilities
  • Use empty brackets [] or {}
  • Change aid frequently

Identity vs Capabilities

AAIP v2 separates these concerns:

Layer Header Purpose
Identity AI-Agent Stable, always safe to log
Capabilities AI-Agent-Capabilities Optional, may be sensitive

Why?

  • Identity rarely changes; capabilities may vary
  • Logging identity is low-risk; capabilities may aid attackers
  • Rate limits may depend on identity, not capabilities

Handling Unknown Values

Value Meaning Example
unknown Not available (App; unknown)
redacted Intentionally hidden (App; redacted)
# Model not introspectable
AI-Agent: Vendor/unknown (MyApp; 1.0)

# Version hidden for security
AI-Agent: OpenAI/GPT-5.2 (SecretApp; redacted) [aid=secret-001]

Multi-Agent Scenarios

Orchestrator + Workers

# Orchestrator
AI-Agent: OpenAI/GPT-5.2 (Orchestrator; 1.0) [aid=orch-001]

# Worker (delegated)
AI-Agent: Anthropic/claude-4.5 (Worker; 1.0) [aid=work-001] [delegated=orch-001]

Multi-Tenant

AI-Agent: OpenAI/GPT-5.2 (SaaS; 2.0) [aid=saas-001] [behalf=customer-tenant]

Server-Side Parsing

Extract Fields (Python)

import re

def parse_ai_agent(header):
    pattern = r'^([^/]+)/([^\s(]+)\s*\(([^;]+);\s*([^)]+)\)(?:\s*\[aid=([^\]]+)\])?'
    match = re.match(pattern, header)
    if match:
        return {
            'vendor': match.group(1),
            'model': match.group(2),
            'app': match.group(3),
            'version': match.group(4),
            'aid': match.group(5)
        }
    return None

# Usage
identity = parse_ai_agent("OpenAI/GPT-5.2 (MyApp; 1.0) [aid=atlas-prod]")
# {'vendor': 'OpenAI', 'model': 'GPT-5.2', 'app': 'MyApp', 'version': '1.0', 'aid': 'abc123'}

Logging (Express.js)

app.use((req, res, next) => {
  const aiAgent = req.headers['ai-agent'];
  if (aiAgent) {
    console.log(`AI request: ${aiAgent}`);
    req.isAiAgent = true;
  }
  next();
});

Verification

For trusted identity, use verification extensions (see VERIFICATION.md):

Mechanism Use Case
Signed headers Simple verification
JWT assertions Enterprise IdP integration
mTLS Service-to-service

FAQ

Q: Can I omit the agent ID?
A: Yes, aid= is optional. But it helps with stable analytics.

Q: What if capabilities change per request?
A: Send appropriate capabilities per request. Identity stays stable.

Q: Should I include User-Agent too?
A: Yes. Keep User-Agent for runtime; AI-Agent supplements it.

See FAQ.md for more questions.