From cb4086459fbe7e66762116c27de13dfaf29944f9 Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Sun, 18 Jan 2026 11:17:27 -0500 Subject: [PATCH 1/6] feat: Add Sponsored Intelligence Protocol documentation Define the SI protocol for conversational brand experiences in AI assistants. Like VAST defines video ad serving, SI defines how to serve and interact with brand agent endpoints. Key concepts: - SI Manifest: Brand declares capabilities (modalities, components, commerce) - Capability negotiation: Brand declares what it CAN do, host responds with what it SUPPORTS, session uses the intersection - Identity consent: Clear PII with explicit consent (not hashed) including shipping address for accurate pricing - Standard components: text, link, image, product_card, carousel, action_button that work everywhere (like AMP) - Platform extensions: Richer capabilities on platforms that support them - Session lifecycle: Initiate with natural language context + offer_id, terminate with handoff to ACP for transactions - Frequent flyer/loyalty: Brand looks up from email, hosts don't store Adds: - docs/sponsored-intelligence/overview.mdx - Navigation entry in docs.json - Glossary entries for SI, ACP, AgenticAdvertising.org Co-Authored-By: Claude Opus 4.5 --- docs.json | 6 + docs/reference/glossary.mdx | 128 ++++---- docs/sponsored-intelligence/overview.mdx | 402 +++++++++++++++++++++++ 3 files changed, 469 insertions(+), 67 deletions(-) create mode 100644 docs/sponsored-intelligence/overview.mdx diff --git a/docs.json b/docs.json index 1948f95e56..a5e21b264c 100644 --- a/docs.json +++ b/docs.json @@ -151,6 +151,12 @@ "docs/curation/coming-soon" ] }, + { + "group": "Sponsored Intelligence Protocol", + "pages": [ + "docs/sponsored-intelligence/overview" + ] + }, { "group": "Media Buy Protocol", "pages": [ diff --git a/docs/reference/glossary.mdx b/docs/reference/glossary.mdx index dbe1fec44a..493449064c 100644 --- a/docs/reference/glossary.mdx +++ b/docs/reference/glossary.mdx @@ -6,26 +6,28 @@ title: Glossary ## A -**Account Type** +**Account Type** Classification of MCP session credentials as either "platform" (aggregator) or "customer" (direct advertiser/agency). -**Activation** +**Activation** The process of making a signal available for targeting on a specific platform and seat. **Ad Context Protocol (AdCP)** An open standard for AI-powered advertising workflows. AdCP defines domain-specific tasks and schemas that work over MCP and A2A as transports, enabling natural language interfaces for advertising operations. -**Agentic eXecution Engine (AXE)** +**Agentic Commerce Protocol (ACP)** +An open standard developed by OpenAI and Stripe for programmatic commerce flows in AI assistants. ACP defines how agents can initiate checkout, delegate payment, and complete transactions without becoming the merchant of record. In the context of Sponsored Intelligence, ACP handles the transaction after a brand agent hands off a user with purchase intent. + +**Agentic eXecution Engine (AXE)** The real-time execution layer that sits between orchestrators and decisioning platforms, handling dynamic audience targeting, brand safety enforcement, frequency management, and first-party data activation at impression time. See [AXE documentation](/docs/media-buy/advanced-topics/agentic-execution-engine) for details. -**Signal Discovery** -The process of finding relevant data signals (audiences, contextual, geographical, temporal) using natural language descriptions. +**AgenticAdvertising.org** +The member organization that stewards the Ad Context Protocol (AdCP) and related open standards for AI-powered advertising. -**Signal ID** -A unique identifier for a signal within a provider's catalog. +## B -**Signal Type** -Classification of signals as "marketplace" (third-party), "owned" (first-party), "destination" (bundled with media), "contextual", "geographical", or "temporal". +**Budget** +Total monetary allocation for a media buy, which can be distributed across multiple packages. ## C @@ -86,6 +88,9 @@ Predicted timeframe for signal deployment, typically 24-48 hours for new activat **Flat Rate** Fixed-cost pricing model where a single payment is made regardless of delivery volume. Common for sponsorships and takeovers. +**Flight** +A time-bounded advertising campaign segment, mapped to line items in ad servers. + **Frequency** The average number of times an individual is exposed to an advertisement during a campaign. @@ -99,24 +104,41 @@ A unit of measurement for television and radio advertising representing 1% of th **Households** Size unit representing unique household addresses, useful for geographic and family-based targeting. +**Human-in-the-Loop (HITL)** +Protocol feature allowing publishers to require manual approval for operations. + ## I -**Impressions** (Media Buy Protocol) +**Impressions** (Media Buy Protocol) The number of times an ad is displayed, used for pricing and delivery tracking. -**Individuals** (Signals Protocol) +**Individuals** (Signals Protocol) Size unit representing unique people, best for frequency capping and demographic targeting. -**Inventory** +**Inventory** Available advertising space on websites, apps, or other media properties. +## L + +**Line Item** +The basic unit of inventory in ad servers like Google Ad Manager, represented as packages in AdCP. + +**Loop Duration** +The length of time for a complete rotation of ads in a DOOH display, measured in seconds. Used to calculate frequency and share of voice. + +**Loop Plays** +The number of times an ad was displayed in a DOOH loop rotation. Key metric for DOOH delivery reporting. + ## M -**MCP (Model Context Protocol)** +**Marketplace Signal** +Third-party signal available for licensing from data providers. + +**MCP (Model Context Protocol)** The underlying protocol framework that enables AI assistants to interact with external systems. -**Marketplace Signal** -Third-party signal available for licensing from data providers. +**Media Buy** +A complete advertising campaign containing packages, budget, targeting, and creative assets. ## N @@ -130,6 +152,9 @@ First-party signal data belonging to the advertiser or platform. ## P +**Package** +A specific advertising product within a media buy, representing a flight or line item with its own pricing and targeting. + **Platform Account** Master account representing an advertising platform that can syndicate signals to multiple customers. @@ -139,6 +164,12 @@ The method by which advertising inventory is priced and billed. AdCP supports CP **Pricing Option** A specific pricing model offered by a publisher for a product, including rate, currency, and parameters. +**Principal** +An authenticated entity (advertiser, agency, or brand) with unique access credentials and platform mappings. + +**Product** +Advertising inventory available for purchase, discovered through natural language queries. + **Prompt** Natural language description used to discover relevant signals (e.g., "high-income sports enthusiasts", "premium automotive content", "users in urban areas during evening hours"). @@ -184,9 +215,21 @@ Percentage of available ad inventory allocated to a specific advertiser in DOOH **Signal Agent** An MCP server that provides signal discovery and activation services. Enables natural language audience discovery and deploys signals to decisioning platforms. Can be private (owned by a single principal) or marketplace (licensing data to multiple principals). Examples: LiveRamp, Experian, Peer39. +**Signal Discovery** +The process of finding relevant data signals (audiences, contextual, geographical, temporal) using natural language descriptions. + +**Signal ID** +A unique identifier for a signal within a provider's catalog. + +**Signal Type** +Classification of signals as "marketplace" (third-party), "owned" (first-party), "destination" (bundled with media), "contextual", "geographical", or "temporal". + **Size Unit** (Signals Protocol) The measurement type for signal size: individuals, devices, or households. +**Sponsored Intelligence (SI)** +An open standard for conversational brand experiences in AI assistants. Like VAST defines video ad serving, SI defines how to serve and interact with brand agent endpoints. SI handles the engagement; the Agentic Commerce Protocol (ACP) handles transactions. See [Sponsored Intelligence Protocol](/docs/sponsored-intelligence/overview) for details. + **SSP (Supply-Side Platform)** A type of decisioning platform that helps publishers sell advertising inventory programmatically. SSPs connect to multiple demand sources and make ad selection decisions. Examples: Index Exchange, OpenX, PubMatic, Magnite. @@ -214,68 +257,19 @@ Physical location where DOOH advertising is displayed (e.g., airport terminal, t **Venue Package** Named collection of DOOH screens across specific venues (e.g., 'times_square_network', 'airport_terminals'). Used in DOOH pricing parameters. -## B - -**Budget** -Total monetary allocation for a media buy, which can be distributed across multiple packages. - -## F - -**Flight** -A time-bounded advertising campaign segment, mapped to line items in ad servers. - -## H - -**Households** (Signals Protocol) -Size unit representing unique household addresses, useful for geographic and family-based targeting. - -**Human-in-the-Loop (HITL)** (Media Buy Protocol) -Protocol feature allowing publishers to require manual approval for operations. - -## L - -**Line Item** -The basic unit of inventory in ad servers like Google Ad Manager, represented as packages in AdCP. - -**Loop Duration** -The length of time for a complete rotation of ads in a DOOH display, measured in seconds. Used to calculate frequency and share of voice. - -**Loop Plays** -The number of times an ad was displayed in a DOOH loop rotation. Key metric for DOOH delivery reporting. - -## M - -**MCP (Model Context Protocol)** -The underlying protocol framework that enables AI assistants to interact with external systems. - -**Marketplace Signal** -Third-party signal available for licensing from data providers. - -**Media Buy** -A complete advertising campaign containing packages, budget, targeting, and creative assets. - -## P - -**Package** -A specific advertising product within a media buy, representing a flight or line item with its own pricing and targeting. - -**Principal** -An authenticated entity (advertiser, agency, or brand) with unique access credentials and platform mappings. - -**Product** -Advertising inventory available for purchase, discovered through natural language queries. - ## Acronyms +- **ACP**: Agentic Commerce Protocol - **AdCP**: Ad Context Protocol - **API**: Application Programming Interface - **AXE**: Agentic eXecution Engine - **CPM**: Cost Per Mille (thousand) -- **DSP**: Demand-Side Platform - **DMP**: Data Management Platform +- **DSP**: Demand-Side Platform - **MCP**: Model Context Protocol - **PII**: Personally Identifiable Information - **RTB**: Real-Time Bidding +- **SI**: Sponsored Intelligence - **SSP**: Supply-Side Platform - **TTD**: The Trade Desk - **UTC**: Coordinated Universal Time diff --git a/docs/sponsored-intelligence/overview.mdx b/docs/sponsored-intelligence/overview.mdx new file mode 100644 index 0000000000..4e6beeab21 --- /dev/null +++ b/docs/sponsored-intelligence/overview.mdx @@ -0,0 +1,402 @@ +--- +sidebar_position: 1 +title: Overview +--- + +Consumers are discovering and exploring in AI services. They don't want to leave to find and learn about brands and products. So we need a way to bring the brand to the chat. + +The Sponsored Intelligence Protocol defines how AI assistants invoke and interact with brand agent endpoints—enabling rich brand experiences without breaking the conversational flow. + +## The Billion Dollar Sentence + +When OpenAI announced ads in ChatGPT, they promised "answer independence"—ads won't influence responses. But the real value isn't banner ads at the bottom of chat. It's this: + +> "Based on what you're looking for, Delta has flights to Boston starting at $199. Want me to connect you with their assistant to explore options?" + +That sentence—where AI recommends a brand and offers to hand off the conversation—is worth billions. Sponsored Intelligence defines the standard for what happens next. + +## What is Sponsored Intelligence? + +**Sponsored Intelligence (SI)** is an open standard for conversational brand experiences in AI assistants. Like VAST defines video ad serving, SI defines how to serve and interact with brand agent endpoints. + +``` +Ad Serving Standards: +- VAST → Video (video file + companions + tracking) +- MRAID → Rich media/interactive display +- Native → Content-style ads +- SI → Conversational agents (endpoint + modalities + brand assets) +``` + +### SI is More Than a Creative Type + +SI can be used in multiple contexts: + +| Context | Description | Example | +|---------|-------------|---------| +| **Creative** | Served via media buy | Brand syncs SI endpoint, triggered when campaign runs | +| **Embedded Experience** | User expresses interest | "Tell me more about Delta" → seamless transition to brand agent | +| **Standalone Agent** | Organic discovery | User explicitly asks to talk to a brand's agent | + +The key insight: SI isn't a click-through. It's a conversational handoff. + +## How It Works + +SI handles the engagement. The [Agentic Commerce Protocol (ACP)](https://github.com/anthropics/acp)—an open standard by OpenAI and Stripe for programmatic commerce—handles the transaction. This separation keeps the user's trusted relationship with the host while enabling seamless checkout. + +```mermaid +flowchart LR + A[User Intent] --> B[Host Platform] + B --> C{Consent?} + C -->|Yes + Identity| D[Initiate Session] + C -->|Yes, Anonymous| D + C -->|No| E[Continue without brand] + D --> F[Brand Agent] + F <--> G[Conversation Turns] + G --> H{User Done?} + H -->|Transaction| I[Handoff to ACP] + H -->|Complete| J[Return to Host] + H -->|Exit| J + I --> K[Checkout Flow] +``` + +### The Flow + +1. **User expresses interest** → Host identifies opportunity +2. **Consent prompt** → User decides whether to share identity +3. **Session initiation** → Host invokes brand agent with context + capabilities +4. **Conversational engagement** → Brand agent interacts via text, voice, video, or embedded UI +5. **Session termination** → Handoff back for transaction (via ACP) or conversation complete + +## SI Manifest: What Brands Declare + +Brands publish an SI manifest declaring their agent's capabilities: + +```json +{ + "endpoint": { + "transport": "mcp", + "url": "https://delta.com/agent" + }, + "capabilities": { + "modalities": { + "conversational": true, + "voice": { "provider": "elevenlabs", "voice_id": "delta_v1" }, + "video": { "formats": ["mp4", "webm"], "max_duration_seconds": 60 }, + "avatar": { "provider": "d-id", "avatar_id": "delta_avatar" } + }, + "components": { + "standard": ["text", "link", "image", "product_card", "carousel", "action_button"], + "extensions": { + "chatgpt_apps_sdk": { "app_id": "delta-travel" } + } + }, + "commerce": { + "acp_checkout": true, + "booking": true + } + }, + "brand_manifest_url": "https://delta.com/.well-known/brand-manifest.json" +} +``` + +## Capability Negotiation + +Not every host supports every capability. SI uses capability negotiation—brand says what it CAN do, host responds with what it SUPPORTS, session uses the intersection. + +``` +Brand declares: voice, avatar, standard components, chatgpt_apps_sdk +Host supports: voice, standard components, chatgpt_apps_sdk +Session can use: voice, standard components, chatgpt_apps_sdk +``` + +Standard components work everywhere. Extensions enable richer experiences on platforms that support them. Brands can always fall back to standard components for universal compatibility. + +This enables graceful degradation. A brand agent that works beautifully in ChatGPT with a full Apps SDK experience can still function in a simpler host—just with standard product cards and carousels instead. + +## Identity & Privacy Consent + +When a user engages with a brand agent, the host asks whether to share identity. This is the core value exchange: user gets personalized service, brand gets a lead. + +### The Consent Flow + +``` +User: "I want to talk to Delta about flights" + +Host: "I can connect you with Delta's assistant. Would you like me to + share your info so they can personalize your experience? + + [x] Share my name and email with Delta + [x] Share my shipping address (for accurate pricing) + + By continuing, you agree to Delta's Privacy Policy [link]" + +User: "Yes, share my info" +``` + +Shipping address enables brands to calculate accurate taxes and shipping costs during the conversation, leading to faster checkout and better recommendations. + +### Why Clear PII (Not Hashed) + +This isn't RTB with multiple intermediaries. It's a direct, consented handoff: +- User explicitly says "yes, tell them who I am" +- Delta needs actual email to send confirmations +- Hashing would break the use case + +### With Consent + +```json +{ + "identity": { + "consent_granted": true, + "consent_timestamp": "2026-01-18T10:30:00Z", + "consent_scope": ["name", "email", "shipping_address"], + "privacy_policy_acknowledged": { + "brand_policy_url": "https://delta.com/privacy", + "brand_policy_version": "2026-01" + }, + "user": { + "email": "user@example.com", + "name": "Jane Smith", + "locale": "en-US", + "shipping_address": { + "street": "123 Main St", + "city": "New York", + "state": "NY", + "postal_code": "10001", + "country": "US" + } + } + } +} +``` + +### Without Consent (Anonymous) + +```json +{ + "identity": { + "consent_granted": false, + "anonymous_session_id": "anon_xyz789" + } +} +``` + +Brand can still help—just can't personalize or follow up via email. + +## Modalities + +SI supports multiple interaction modalities. These can be combined—a session might use conversational text with embedded product carousels. + +### Conversational +Pure text exchange via MCP tools or A2A messages. The baseline modality that every SI implementation supports. + +### Voice +Audio-based interaction using brand voice. The host renders audio using the brand's TTS configuration (ElevenLabs, OpenAI, etc.). + +### Video +Brand video content played within the conversation. This includes product videos, explainer content, and promotional clips that enhance the brand experience without requiring the user to navigate away. + +### Avatar +Animated video presence with a brand avatar. Providers like D-ID, HeyGen, and Synthesia enable branded video agents that can speak and respond visually. The host renders the avatar using brand-provided configuration. + +### Visual Components + +SI defines a tiered approach to visual experiences—from lightweight components that work everywhere to rich platform-specific apps. + +#### Standard Components (Works Everywhere) + +SI defines a small set of **standard components** that all compliant hosts MUST render. Like AMP standardized mobile web components, these ensure brands can participate without building platform-specific code: + +| Component | Purpose | Data Shape | +|-----------|---------|------------| +| `text` | Conversational message | `{ message: string }` | +| `link` | URL with label | `{ url, label, preview? }` | +| `image` | Single image | `{ url, alt, caption? }` | +| `product_card` | Product display | `{ title, price, image_url, description?, cta? }` | +| `carousel` | Array of cards/images | `{ items: [...], title? }` | +| `action_button` | CTA that triggers callback | `{ label, action, payload? }` | + +Brands provide structured JSON data. Hosts render according to their design system. No framework dependency. + +```json +{ + "ui_elements": [ + { + "type": "product_card", + "data": { + "title": "Boston Flight - Jan 25", + "price": "$199", + "image_url": "https://delta.com/images/bos.jpg", + "cta": { "label": "Book Now", "action": "checkout" } + } + } + ] +} +``` + +#### Platform Extensions + +Hosts may support richer capabilities beyond the standard set. During session initiation, hosts declare what extensions they support: + +```json +{ + "supported_components": { + "standard": ["text", "link", "image", "product_card", "carousel", "action_button"], + "extensions": { + "chatgpt_apps_sdk": "1.0", + "maps": true, + "forms": true + } + } +} +``` + +Brands can then use extended features when available, falling back to standard components otherwise. + +#### App Handoff + +For brands who've built full platform-specific apps (ChatGPT Apps, etc.), SI supports direct handoff: + +```json +{ + "type": "app_handoff", + "apps": { + "chatgpt": { "app_id": "delta-travel", "deep_link": "flights/boston" }, + "web": { "url": "https://delta.com/book?dest=BOS" } + } +} +``` + +This lets brands leverage existing app investments while still participating in the SI protocol. + +#### Commerce Actions + +Standard components include `action_button` for commerce triggers. Currently, this initiates ACP checkout: + +```json +{ + "type": "action_button", + "data": { + "label": "Add to Cart", + "action": "acp_checkout", + "payload": { "sku": "DL-BOS-125", "quantity": 1 } + } +} +``` + +We expect this to extend to persistent carts, multi-item checkout, and richer commerce flows as the ecosystem matures. The standard component schema is designed to accommodate these extensions. + +## Session Lifecycle + +SI sessions have explicit lifecycle management. + +### Initiate Session + +Host → Brand, including context, capabilities, identity (if consented), and any active offer from the campaign: + +```json +{ + "action": "initiate_session", + "session_id": "sess_abc123", + "campaign_id": "delta_q1_premium_upgrade", + "placement": "chatgpt_search", + "context": "User wants to fly to Boston next Tuesday morning on flight 632 at 6 AM.", + "offer_id": "delta_chatgpt_3313", + "identity": { + "consent_granted": true, + "user": { + "email": "jane@example.com", + "name": "Jane Smith", + "shipping_address": { /* ... */ } + } + }, + "supported_capabilities": { /* what host supports */ } +} +``` + +The `context` is natural language - the brand agent parses the user's intent. The `offer_id` references a campaign promotion (like free upgrades on eligible flights) that the brand knows how to apply. + +**Frequent flyer and loyalty data**: The brand looks this up from the user's email - hosts don't store loyalty numbers. Delta recognizes `jane@example.com` and retrieves her SkyMiles status automatically. + +### Session Response + +Brand returns structured content that host renders. Notice how the brand agent uses the specific intent and applies the offer: + +```json +{ + "session_id": "sess_abc123", + "response": { + "message": "Hi Jane! I found DL632 departing at 6:15 AM next Tuesday. Great news—as a SkyMiles Gold member, you qualify for our free Premium Economy upgrade on this flight.", + "ui_elements": [ + { + "type": "product_card", + "data": { + "title": "DL632 to Boston - Tue Jan 27", + "subtitle": "6:15 AM → 9:42 AM (3h 27m)", + "price": "$199", + "badge": "Free Premium Economy Upgrade", + "image_url": "https://delta.com/images/premium-economy.jpg", + "cta": { "label": "Book with Upgrade", "action": "checkout" } + } + } + ] + } +} +``` + +**Key principle**: Brand returns structured content (cards, links, actions). Host decides what to render based on capabilities and policies. The brand agent personalized the response using Jane's email (looked up her SkyMiles status) and applied the campaign offer. + +### Terminate Session + +Multiple termination reasons: + +| Reason | Meaning | What Happens | +|--------|---------|--------------| +| `handoff_transaction` | User wants to buy | Host initiates ACP checkout | +| `handoff_complete` | Conversation done | Return to normal chat | +| `user_exit` | User ended it | Clean up, maybe save context | +| `session_timeout` | Inactivity | Auto-cleanup | +| `host_terminated` | Policy/error | End session | + +## ACP Integration + +When the termination reason is `handoff_transaction`, the host initiates checkout via the Agentic Commerce Protocol (ACP): + +``` +Brand Agent → Host: terminate_session(handoff_transaction) +Host → ACP: Initiate checkout with Delta +ACP → User: Complete purchase flow +``` + +SI handles the engagement. ACP handles the transaction. The user's trusted relationship with the host is maintained throughout. + +## The Value Proposition + +### For AI Platforms (Hosts) + +- **Monetization**: New ad format that doesn't compromise answer independence +- **User experience**: Native conversational commerce, not banner ads +- **Standards-based**: Interoperable with any SI-compliant brand agent + +### For Brands + +- **Direct engagement**: Talk to users in context, when they're interested +- **Rich experiences**: Mini-stores, interactive maps, voice/avatar presence +- **Lead generation**: Consented identity for follow-up + +### For Users + +- **Personalization**: Share identity, get better service +- **Control**: Clear consent for what's shared +- **Convenience**: Shop, book, explore—all within the conversation + +## Next Steps + +- **Technical Teams**: Review the protocol components above +- **Platform Providers**: See implementation considerations for hosts +- **Brands**: Understand how to build SI-compliant agents +- **Everyone**: Join the [Community](https://join.slack.com/t/agenticads/shared_invite/zt-3c5sxvdjk-x0rVmLB3OFHVUp~WutVWZg) to discuss + +--- + +*The Sponsored Intelligence Protocol is part of the broader [AdCP ecosystem](/docs/intro), enabling the next generation of AI-powered advertising.* From aa6b87176e1d797de8ef55e7df16311f63885f9a Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Mon, 19 Jan 2026 12:28:54 -0500 Subject: [PATCH 2/6] fix: Address code review issues in SI implementation - Add session authorization verification to all SI chat routes - Sanitize user input to prevent prompt injection attacks - Fix memory leak in threadSessionMap with TTL-based cache cleanup - Extract duplicate SI session detection logic into helper function - Use centralized model config instead of hardcoded model names - Replace silent error suppression with specific error type checks - Add XSS protection with DOMPurify in chat.html - Replace broken reference links with "coming soon" notices Co-Authored-By: Claude Haiku 4.5 --- docs.json | 15 +- .../implementing-si-agents.mdx | 262 +++ .../implementing-si-hosts.mdx | 136 ++ docs/sponsored-intelligence/overview.mdx | 73 +- docs/sponsored-intelligence/specification.mdx | 415 +++++ docs/sponsored-intelligence/tasks/index.mdx | 109 ++ .../tasks/si_check_availability.mdx | 147 ++ .../tasks/si_initiate_session.mdx | 181 +++ .../tasks/si_send_message.mdx | 209 +++ .../tasks/si_terminate_session.mdx | 282 ++++ server/public/chat.html | 1437 ++++++++++++++++- server/src/addie/bolt-app.ts | 30 + server/src/addie/mcp/si-host-tools.ts | 670 ++++++++ server/src/addie/prompts.ts | 53 +- server/src/addie/services/si-agent-service.ts | 920 +++++++++++ .../migrations/168_si_agent_configuration.sql | 177 ++ .../migrations/169_si_availability_checks.sql | 40 + server/src/db/seeds/si-test-data.sql | 273 ++++ server/src/db/si-db.ts | 882 ++++++++++ server/src/http.ts | 5 + server/src/routes/addie-chat.ts | 75 +- server/src/routes/si-chat.ts | 427 +++++ static/schemas/source/index.json | 63 + .../si-capabilities.json | 114 ++ .../si-check-availability-request.json | 29 + .../si-check-availability-response.json | 74 + .../sponsored-intelligence/si-identity.json | 84 + .../si-initiate-session-request.json | 53 + .../si-initiate-session-response.json | 47 + .../sponsored-intelligence/si-manifest.json | 37 + .../si-send-message-request.json | 37 + .../si-send-message-response.json | 78 + .../si-terminate-session-request.json | 53 + .../si-terminate-session-response.json | 63 + .../sponsored-intelligence/si-ui-element.json | 190 +++ 35 files changed, 7668 insertions(+), 72 deletions(-) create mode 100644 docs/sponsored-intelligence/implementing-si-agents.mdx create mode 100644 docs/sponsored-intelligence/implementing-si-hosts.mdx create mode 100644 docs/sponsored-intelligence/specification.mdx create mode 100644 docs/sponsored-intelligence/tasks/index.mdx create mode 100644 docs/sponsored-intelligence/tasks/si_check_availability.mdx create mode 100644 docs/sponsored-intelligence/tasks/si_initiate_session.mdx create mode 100644 docs/sponsored-intelligence/tasks/si_send_message.mdx create mode 100644 docs/sponsored-intelligence/tasks/si_terminate_session.mdx create mode 100644 server/src/addie/mcp/si-host-tools.ts create mode 100644 server/src/addie/services/si-agent-service.ts create mode 100644 server/src/db/migrations/168_si_agent_configuration.sql create mode 100644 server/src/db/migrations/169_si_availability_checks.sql create mode 100644 server/src/db/seeds/si-test-data.sql create mode 100644 server/src/db/si-db.ts create mode 100644 server/src/routes/si-chat.ts create mode 100644 static/schemas/source/sponsored-intelligence/si-capabilities.json create mode 100644 static/schemas/source/sponsored-intelligence/si-check-availability-request.json create mode 100644 static/schemas/source/sponsored-intelligence/si-check-availability-response.json create mode 100644 static/schemas/source/sponsored-intelligence/si-identity.json create mode 100644 static/schemas/source/sponsored-intelligence/si-initiate-session-request.json create mode 100644 static/schemas/source/sponsored-intelligence/si-initiate-session-response.json create mode 100644 static/schemas/source/sponsored-intelligence/si-manifest.json create mode 100644 static/schemas/source/sponsored-intelligence/si-send-message-request.json create mode 100644 static/schemas/source/sponsored-intelligence/si-send-message-response.json create mode 100644 static/schemas/source/sponsored-intelligence/si-terminate-session-request.json create mode 100644 static/schemas/source/sponsored-intelligence/si-terminate-session-response.json create mode 100644 static/schemas/source/sponsored-intelligence/si-ui-element.json diff --git a/docs.json b/docs.json index a5e21b264c..4fc4ba18e9 100644 --- a/docs.json +++ b/docs.json @@ -154,7 +154,20 @@ { "group": "Sponsored Intelligence Protocol", "pages": [ - "docs/sponsored-intelligence/overview" + "docs/sponsored-intelligence/overview", + "docs/sponsored-intelligence/specification", + { + "group": "Tasks", + "pages": [ + "docs/sponsored-intelligence/tasks/index", + "docs/sponsored-intelligence/tasks/si_check_availability", + "docs/sponsored-intelligence/tasks/si_initiate_session", + "docs/sponsored-intelligence/tasks/si_send_message", + "docs/sponsored-intelligence/tasks/si_terminate_session" + ] + }, + "docs/sponsored-intelligence/implementing-si-agents", + "docs/sponsored-intelligence/implementing-si-hosts" ] }, { diff --git a/docs/sponsored-intelligence/implementing-si-agents.mdx b/docs/sponsored-intelligence/implementing-si-agents.mdx new file mode 100644 index 0000000000..f4dd5a0465 --- /dev/null +++ b/docs/sponsored-intelligence/implementing-si-agents.mdx @@ -0,0 +1,262 @@ +--- +sidebar_position: 3 +title: Implementing SI Agents +--- + +This guide helps brands implement Sponsored Intelligence agents. Once implemented, your agent can be invoked by SI hosts like Addy, ChatGPT, or other AI assistants. + +## Quick Start + +An SI agent is an MCP or A2A server that implements four tasks: + +1. `si_check_availability` - Respond to anonymous availability checks +2. `si_initiate_session` - Start a conversation +3. `si_send_message` - Exchange messages +4. `si_terminate_session` - End the conversation + +## SI Manifest + +First, declare your agent's capabilities in an SI manifest. This can be hosted at `.well-known/si-manifest.json` or referenced from your adagents.json: + +```json +{ + "$schema": "https://adcontextprotocol.org/schemas/sponsored-intelligence/si-manifest.json", + "endpoint": { + "transport": "mcp", + "url": "https://yourbrand.example/si-agent" + }, + "capabilities": { + "modalities": { + "voice": false, + "video": false, + "avatar": false + }, + "components": { + "standard": ["text", "link", "image", "product_card", "carousel", "action_button"], + "extensions": {} + }, + "commerce": { + "acp_checkout": false + } + }, + "brand_manifest_url": "https://yourbrand.example/.well-known/brand-manifest.json" +} +``` + +## Reference Implementation + + +Reference implementations are coming soon. When available, they will demonstrate: +- All four SI tasks implemented as MCP tools +- Session management with timeout handling +- Identity and consent handling +- UI element generation +- ACP checkout handoff + + +### Task Structure + +Each SI task follows the MCP tool pattern: + +```typescript +server.tool( + "si_initiate_session", + "Start a conversational session with this brand agent", + { + context: { type: "string", description: "Natural language user intent" }, + identity: { type: "object", description: "User identity with consent" }, + media_buy_id: { type: "string", description: "AdCP media buy ID (optional)" }, + offer_id: { type: "string", description: "Brand-specific offer reference (optional)" }, + }, + async ({ context, identity, media_buy_id, offer_id }) => { + // Your implementation here + return { + content: [{ + type: "text", + text: JSON.stringify({ + session_id: "sess_abc123", + response: { message: "Hello! How can I help?" }, + negotiated_capabilities: { /* ... */ } + }) + }] + }; + } +); +``` + +## Key Implementation Considerations + +### 1. The Conversation Handoff + +The `context` field in `si_initiate_session` is the host's handoff message - what the host AI tells your brand agent about the user's intent. This is visible to the user as part of the conversation flow. + +For example, when a user says "I need to fly to Boston next week" in ChatGPT, and the host decides to connect them to Delta's SI agent, the handoff might look like: + +> "I'm connecting you with Delta to help with your Boston flight. They can check availability and offers for you." + +Your brand agent receives the context and should respond naturally - as if continuing the conversation: + +```typescript +// Your agent is an AI that responds conversationally +// The context tells you what the user needs - just help them + +// Good response: +"Hi! I'd be happy to help you find a flight to Boston. +When next week were you thinking - any preferred time of day?" + +// Not this - don't mechanically echo back parsed data: +"I detected: category=flight, destination=Boston, timeframe=next_week" +``` + +The key is that SI is a conversation, not an API call. Your brand agent should feel like talking to a helpful person, not filling out a form. + +### 2. Identity Handling + +When `consent_granted` is true, you receive real PII: + +```typescript +async function handleIdentity(identity: Identity) { + if (!identity.consent_granted) { + // Anonymous session - can still help, just can't personalize + return null; + } + + // Look up existing customer by email + const customer = await lookupCustomer(identity.user.email); + + if (customer) { + // Personalize based on history + return { + name: customer.preferred_name || identity.user.name, + loyalty_status: customer.loyalty_tier, + preferences: customer.preferences, + }; + } + + // New customer - use provided identity + return { + name: identity.user.name, + email: identity.user.email, + }; +} +``` + +### 3. UI Elements + +Return structured data that hosts can render: + +```typescript +const uiElements = [ + // Product card for a specific item + { + type: "product_card", + data: { + title: "Premium Widget", + subtitle: "Best seller", + price: "$99", + image_url: "https://...", + cta: { label: "Add to Cart", action: "add_to_cart", payload: { sku: "WIDGET-001" } }, + }, + }, + + // Carousel for browsing options + { + type: "carousel", + data: { + title: "You might also like", + items: [ + { title: "Option A", price: "$49" }, + { title: "Option B", price: "$79" }, + ], + }, + }, + + // Action button for explicit CTA + { + type: "action_button", + data: { + label: "Complete Purchase", + action: "checkout", + payload: { items: ["WIDGET-001"] }, + }, + }, +]; +``` + +### 4. Session Management + +Sessions should have timeouts and cleanup: + +```typescript +const SESSION_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes + +function cleanupExpiredSessions() { + const now = Date.now(); + for (const [id, session] of sessions) { + if (now - session.last_activity.getTime() > SESSION_TIMEOUT_MS) { + sessions.delete(id); + } + } +} + +// Run cleanup periodically +setInterval(cleanupExpiredSessions, 60 * 1000); +``` + +### 5. Handoff to ACP + +When the user is ready to purchase, signal a handoff: + +```typescript +if (userWantsToPurchase) { + return { + session_status: "pending_handoff", + handoff: { + type: "transaction", + intent: { + action: "purchase", + product: selectedProduct, + price: { amount: 99, currency: "USD" }, + }, + context_for_checkout: { + conversation_summary: "User selected Premium Widget after discussing features", + applied_offers: appliedOffers, + }, + }, + }; +} +``` + +## Testing Your Endpoint + +### Local Testing + +Use the MCP Inspector to test your endpoint: + +```bash +npx @anthropic-ai/mcp-inspector your-si-agent +``` + +### Integration Testing with Addy + +Once your endpoint is registered: + +1. Join the AgenticAdvertising.org Slack workspace +2. Start a conversation with Addy +3. Say "connect me with [Your Brand]" +4. Addy will invoke your SI endpoint + +## Registering Your SI Agent + +To make your SI agent available through Addy and other hosts: + +1. Implement the four SI tasks +2. Host your SI manifest at a public URL +3. Contact the AgenticAdvertising.org team to register your endpoint +4. Test the integration in the staging environment + +## Next Steps + +- Review the [Task Reference](./tasks/) for detailed schema specifications +- Explore the [SI Protocol Overview](./overview) for conceptual understanding +- Join the [Working Group](https://join.slack.com/t/agenticads/shared_invite/zt-3c5sxvdjk-x0rVmLB3OFHVUp~WutVWZg) to discuss implementation questions diff --git a/docs/sponsored-intelligence/implementing-si-hosts.mdx b/docs/sponsored-intelligence/implementing-si-hosts.mdx new file mode 100644 index 0000000000..b111280530 --- /dev/null +++ b/docs/sponsored-intelligence/implementing-si-hosts.mdx @@ -0,0 +1,136 @@ +--- +sidebar_position: 4 +title: Implementing SI Hosts +--- + +This guide helps AI platforms implement Sponsored Intelligence host capabilities. Once implemented, your AI assistant can invoke brand agents for rich conversational commerce experiences. + +## Quick Start + +An SI host needs to: + +1. **Discover** brand agents via SI manifests +2. **Check availability** before handoff (optional but recommended) +3. **Negotiate** capabilities with brand agents +4. **Manage** sessions (initiate, message, terminate) +5. **Render** standard UI components +6. **Handle** commerce handoffs + +## Architecture Overview + +```mermaid +flowchart TB + subgraph Platform["Your AI Platform"] + CE[Conversation Engine] + SM[SI Session Manager] + UI[UI Renderer] + MCP[MCP Client] + + CE --> SM + SM --> UI + CE --> MCP + SM --> MCP + UI --> MCP + end + + subgraph Brand["Brand Agent (MCP Server)"] + T1[si_check_availability] + T2[si_initiate_session] + T3[si_send_message] + T4[si_terminate_session] + end + + MCP --> Brand +``` + +## Reference Implementation + + +Reference implementations are coming soon. When available, they will demonstrate: +- MCP client connection to brand agents +- Session management with timeout handling +- Consent flow implementation +- UI component rendering +- Commerce handoff to ACP + + +## Key Implementation Considerations + +### 1. Consent Flow + +Before sharing user identity with brand agents, you must obtain explicit consent: + +1. Present a clear consent dialog identifying the brand and requested data +2. Link to the brand's privacy policy +3. Allow the user to select which fields to share (name, email, shipping address) +4. Record consent timestamp and scope for the identity object + +If consent is denied, create an anonymous session with `consent_granted: false`. + +### 2. UI Component Rendering + +Hosts must render all standard UI components defined in the SI protocol: + +| Component | Purpose | Required Fields | +|-----------|---------|-----------------| +| `text` | Conversational message | `message` | +| `link` | URL with label | `url`, `label` | +| `image` | Single image | `url`, `alt` | +| `product_card` | Product display with CTA | `title`, `price` | +| `carousel` | Array of cards/images | `items` | +| `action_button` | CTA that triggers callback | `label`, `action` | + +When a user clicks an `action_button`, send an `action_response` via `si_send_message` with the action identifier and any payload. + +### 3. Availability Check Flow + +The recommended flow for sponsored results: + +1. **Check availability** (anonymous) - Verify the offer is still valid +2. **Show offer to user** - Display availability details and ask if they want to connect +3. **Get consent** - If yes, present consent dialog +4. **Initiate session** - Include availability token from step 1 + +### 4. Commerce Handoff + +When a session returns `session_status: "pending_handoff"`: + +- For `handoff.type: "transaction"` - Initiate ACP checkout with the provided intent +- Terminate the SI session with reason `handoff_transaction` + +### 5. Session Management + +- Implement session timeouts (recommended: 5 minutes of inactivity) +- Track session state locally and clean up on termination +- Handle error codes: `session_not_found`, `offer_unavailable`, `rate_limited` + +## Testing Your Implementation + +### Local Testing with Brand Simulator + +```bash +# Run the SI brand simulator +npx @adcontextprotocol/si-simulator + +# Connect your host to localhost:3001 +``` + +### Integration Checklist + +- [ ] Can discover brand agents via SI manifest +- [ ] Can check availability (anonymous, no PII) +- [ ] Can initiate sessions with/without identity +- [ ] Can send messages and receive responses +- [ ] Can handle all termination reasons +- [ ] Renders all standard components correctly +- [ ] Handles action buttons and callbacks +- [ ] Implements proper consent flow +- [ ] Handles commerce handoffs +- [ ] Implements session timeout + +## Next Steps + +- Review the [SI Specification](./specification) for normative requirements +- See [Implementing SI Agents](./implementing-si-agents) for brand-side implementation +- Explore the [Task Reference](./tasks/) for detailed schema specifications +- Join the [Community](https://join.slack.com/t/agenticads/shared_invite/zt-3c5sxvdjk-x0rVmLB3OFHVUp~WutVWZg) for implementation support diff --git a/docs/sponsored-intelligence/overview.mdx b/docs/sponsored-intelligence/overview.mdx index 4e6beeab21..2cb56e9c11 100644 --- a/docs/sponsored-intelligence/overview.mdx +++ b/docs/sponsored-intelligence/overview.mdx @@ -7,13 +7,13 @@ Consumers are discovering and exploring in AI services. They don't want to leave The Sponsored Intelligence Protocol defines how AI assistants invoke and interact with brand agent endpoints—enabling rich brand experiences without breaking the conversational flow. -## The Billion Dollar Sentence +## The Trillion Dollar Sentence When OpenAI announced ads in ChatGPT, they promised "answer independence"—ads won't influence responses. But the real value isn't banner ads at the bottom of chat. It's this: > "Based on what you're looking for, Delta has flights to Boston starting at $199. Want me to connect you with their assistant to explore options?" -That sentence—where AI recommends a brand and offers to hand off the conversation—is worth billions. Sponsored Intelligence defines the standard for what happens next. +That sentence—where AI recommends a brand and offers to hand off the conversation—is worth trillions. Sponsored Intelligence defines the standard for what happens next. ## What is Sponsored Intelligence? @@ -35,9 +35,9 @@ SI can be used in multiple contexts: |---------|-------------|---------| | **Creative** | Served via media buy | Brand syncs SI endpoint, triggered when campaign runs | | **Embedded Experience** | User expresses interest | "Tell me more about Delta" → seamless transition to brand agent | -| **Standalone Agent** | Organic discovery | User explicitly asks to talk to a brand's agent | +| **Agentic Landing Page** | Destination for campaigns | The conversational equivalent of a landing page—where brand engagement happens | -The key insight: SI isn't a click-through. It's a conversational handoff. +The key insight: SI isn't a click-through. It's a conversational handoff. Traditional landing pages exist because users leave the discovery context to learn more. With SI, users stay in the conversation while the brand comes to them. ## How It Works @@ -46,6 +46,8 @@ SI handles the engagement. The [Agentic Commerce Protocol (ACP)](https://github. ```mermaid flowchart LR A[User Intent] --> B[Host Platform] + B -.->|Optional| P[Check Availability] + P -.-> C B --> C{Consent?} C -->|Yes + Identity| D[Initiate Session] C -->|Yes, Anonymous| D @@ -62,10 +64,11 @@ flowchart LR ### The Flow 1. **User expresses interest** → Host identifies opportunity -2. **Consent prompt** → User decides whether to share identity -3. **Session initiation** → Host invokes brand agent with context + capabilities -4. **Conversational engagement** → Brand agent interacts via text, voice, video, or embedded UI -5. **Session termination** → Handoff back for transaction (via ACP) or conversation complete +2. **Availability check** (optional) → Host verifies offer/product is available (`si_check_availability`) +3. **Consent prompt** → User decides whether to share identity +4. **Session initiation** → Host invokes brand agent with context + capabilities (`si_initiate_session`) +5. **Conversational engagement** → Brand agent interacts via text, voice, video, or embedded UI (`si_send_message`) +6. **Session termination** → Handoff back for transaction (via ACP) or conversation complete (`si_terminate_session`) ## SI Manifest: What Brands Declare @@ -74,12 +77,14 @@ Brands publish an SI manifest declaring their agent's capabilities: ```json { "endpoint": { - "transport": "mcp", - "url": "https://delta.com/agent" + "transports": [ + { "type": "mcp", "url": "https://delta.com/mcp" }, + { "type": "a2a", "url": "https://delta.com/.well-known/agent.json" } + ], + "preferred": "mcp" }, "capabilities": { "modalities": { - "conversational": true, "voice": { "provider": "elevenlabs", "voice_id": "delta_v1" }, "video": { "formats": ["mp4", "webm"], "max_duration_seconds": 60 }, "avatar": { "provider": "d-id", "avatar_id": "delta_avatar" } @@ -91,14 +96,26 @@ Brands publish an SI manifest declaring their agent's capabilities: } }, "commerce": { - "acp_checkout": true, - "booking": true + "acp_checkout": true } }, "brand_manifest_url": "https://delta.com/.well-known/brand-manifest.json" } ``` +> **Note**: All SI agents support conversational (text) modality by default—it's the baseline. The modalities section declares *additional* capabilities like voice, video, and avatar. + +### Transport Options + +SI supports multiple transport protocols, enabling brands to meet hosts where they are: + +| Transport | Description | Best For | +|-----------|-------------|----------| +| **MCP** | Model Context Protocol - tool-based interaction | Structured tool calls, IDE integrations | +| **A2A** | Agent-to-Agent Protocol - message-based interaction | Rich async conversations, agent collaboration | + +Brands can declare multiple transports and specify a preference. Hosts select based on their capabilities, enabling graceful negotiation. + ## Capability Negotiation Not every host supports every capability. SI uses capability negotiation—brand says what it CAN do, host responds with what it SUPPORTS, session uses the intersection. @@ -286,22 +303,35 @@ Standard components include `action_button` for commerce triggers. Currently, th We expect this to extend to persistent carts, multi-item checkout, and richer commerce flows as the ecosystem matures. The standard component schema is designed to accommodate these extensions. +#### Integration Actions + +Brand agents can offer users the option to establish a deeper connection—adding the brand as an MCP tool or establishing an A2A relationship for ongoing agent collaboration: + +```json +{ + "type": "integration_actions", + "data": { + "actions": [ + { "type": "mcp", "label": "Add as MCP Tool", "highlighted": true }, + { "type": "a2a", "label": "Connect via A2A" } + ] + } +} +``` + +This enables users to "take the brand with them"—installing the brand's capabilities into their own AI environment for future use without needing to re-discover through ads. It's a powerful conversion path: from sponsored moment to persistent tool. + ## Session Lifecycle SI sessions have explicit lifecycle management. ### Initiate Session -Host → Brand, including context, capabilities, identity (if consented), and any active offer from the campaign: +Host → Brand, including context, capabilities, identity (if consented), and any active offer from the media buy: ```json { - "action": "initiate_session", - "session_id": "sess_abc123", - "campaign_id": "delta_q1_premium_upgrade", - "placement": "chatgpt_search", "context": "User wants to fly to Boston next Tuesday morning on flight 632 at 6 AM.", - "offer_id": "delta_chatgpt_3313", "identity": { "consent_granted": true, "user": { @@ -310,11 +340,14 @@ Host → Brand, including context, capabilities, identity (if consented), and an "shipping_address": { /* ... */ } } }, + "media_buy_id": "delta_q1_premium_upgrade", + "placement": "chatgpt_search", + "offer_id": "delta_chatgpt_3313", "supported_capabilities": { /* what host supports */ } } ``` -The `context` is natural language - the brand agent parses the user's intent. The `offer_id` references a campaign promotion (like free upgrades on eligible flights) that the brand knows how to apply. +The `context` is a conversation handoff - the host tells the brand agent what the user needs, and the brand agent responds naturally. The `offer_id` references a campaign promotion (like free upgrades on eligible flights) that the brand knows how to apply. **Frequent flyer and loyalty data**: The brand looks this up from the user's email - hosts don't store loyalty numbers. Delta recognizes `jane@example.com` and retrieves her SkyMiles status automatically. diff --git a/docs/sponsored-intelligence/specification.mdx b/docs/sponsored-intelligence/specification.mdx new file mode 100644 index 0000000000..a57b969528 --- /dev/null +++ b/docs/sponsored-intelligence/specification.mdx @@ -0,0 +1,415 @@ +--- +sidebar_position: 2 +title: Specification +--- + +This document defines the Sponsored Intelligence (SI) Protocol specification. The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119). + +## Protocol Overview + +The SI Protocol defines how AI assistants (hosts) invoke and interact with brand agent endpoints to enable conversational brand experiences. The protocol consists of: + +1. **Discovery** - How hosts discover brand agents and their capabilities +2. **Availability** - Anonymous pre-flight checks before session handoff +3. **Session Management** - Initiation, messaging, and termination +4. **Capability Negotiation** - Determining supported features +5. **UI Components** - Standard visual elements for rendering + +## Transport Requirements + +### Supported Transports + +Brand agents MUST support at least one of the following transports: + +| Transport | Protocol | Description | +|-----------|----------|-------------| +| MCP | Model Context Protocol | Tool-based interaction via JSON-RPC | +| A2A | Agent-to-Agent | Message-based interaction | + +Brand agents SHOULD support MCP as the preferred transport. + +### Transport Declaration + +The SI manifest MUST declare supported transports: + +```json +{ + "endpoint": { + "transports": [ + { "type": "mcp", "url": "https://brand.example/mcp" } + ], + "preferred": "mcp" + } +} +``` + +If multiple transports are declared, the manifest SHOULD include a `preferred` field. + +## Discovery + +### SI Manifest Location + +Brand agents MUST publish their SI manifest at one of the following locations: + +1. `/.well-known/si-manifest.json` (RECOMMENDED) +2. Referenced from `adagents.json` via the `si_manifest_url` field + +### SI Manifest Schema + +The SI manifest MUST conform to the `si-manifest.json` schema and MUST include: + +- `endpoint` - Transport configuration +- `capabilities` - Supported modalities and components + +The manifest SHOULD include: + +- `brand_manifest_url` - Reference to brand identity assets + +## Availability Check + +### Purpose + +The `si_check_availability` task provides an anonymous pre-flight check before session handoff. This allows hosts to verify offer/product availability without establishing a session. + +### Requirements + +Hosts MAY call `si_check_availability` before initiating a session. + +If a host calls `si_check_availability`: + +1. The request MUST NOT include user PII +2. The request MUST include at least one of: `offer_id` or `product_id` +3. Brand agents MUST return an `availability_token` if available +4. Brand agents SHOULD return a `ttl_seconds` indicating validity duration + +### Availability Token Flow + +If a host receives an `availability_token`: + +1. The host SHOULD include this token in the subsequent `si_initiate_session` request +2. The brand agent MAY use the token to correlate pre-flight checks with sessions +3. The token MUST be treated as opaque by the host + +```json +{ + "availability": { + "token": "avail_abc123xyz", + "checked_at": "2025-01-19T10:00:00Z" + } +} +``` + +## Session Lifecycle + +### Session States + +SI sessions have the following states: + +| State | Description | +|-------|-------------| +| `active` | Session is in progress | +| `pending_handoff` | Brand is requesting handoff to commerce flow | +| `complete` | Session has ended normally | + +### Initiate Session + +The `si_initiate_session` task establishes a new SI session. + +#### Request Requirements + +Hosts MUST include: + +- `context` - Natural language description of user intent +- `identity` - User identity with consent status + +Hosts SHOULD include: + +- `supported_capabilities` - Host's capability set for negotiation +- `availability` - Token from pre-flight check if performed + +Hosts MAY include: + +- `media_buy_id` - AdCP media buy ID if triggered by advertising +- `offer_id` - Brand-specific offer to apply +- `placement` - Where this session was triggered + +#### Response Requirements + +Brand agents MUST return: + +- `session_id` - Unique identifier for this session + +Brand agents SHOULD return: + +- `response.message` - Initial conversational message +- `negotiated_capabilities` - Intersection of brand and host capabilities + +### Send Message + +The `si_send_message` task exchanges messages within an active session. + +#### Request Requirements + +Hosts MUST include: + +- `session_id` - Active session identifier + +Hosts MUST include one of: + +- `message` - User's text message +- `action_response` - Response to a UI action + +#### Response Requirements + +Brand agents MUST return: + +- `session_id` - The session identifier +- `session_status` - Current session state (`active`, `pending_handoff`, or `complete`) + +Brand agents SHOULD return: + +- `response.message` - Conversational response + +If `session_status` is `pending_handoff`, the response MUST include: + +- `handoff` - Handoff configuration for commerce flow + +### Terminate Session + +The `si_terminate_session` task ends an SI session. + +#### Request Requirements + +Hosts MUST include: + +- `session_id` - Session to terminate +- `reason` - Termination reason + +#### Termination Reasons + +| Reason | Description | +|--------|-------------| +| `handoff_transaction` | User proceeding to purchase | +| `handoff_complete` | Conversation completed successfully | +| `user_exit` | User ended the session | +| `session_timeout` | Session timed out due to inactivity | +| `host_terminated` | Host ended the session (policy/error) | + +## Capability Negotiation + +### Negotiation Process + +1. Brand declares capabilities in SI manifest +2. Host sends supported capabilities in session initiation +3. Brand returns negotiated (intersection) capabilities in response +4. Session uses only negotiated capabilities + +### Capability Categories + +#### Modalities + +Modalities define interaction modes: + +| Modality | Description | Required Support | +|----------|-------------|------------------| +| `conversational` | Text exchange | REQUIRED for all implementations | +| `voice` | Audio-based interaction | OPTIONAL | +| `video` | Video content playback | OPTIONAL | +| `avatar` | Animated video presence | OPTIONAL | + +All SI implementations MUST support `conversational` modality. + +#### Standard Components + +The following components MUST be renderable by all compliant hosts: + +| Component | Purpose | +|-----------|---------| +| `text` | Conversational message | +| `link` | URL with label | +| `image` | Single image | +| `product_card` | Product display with CTA | +| `carousel` | Array of cards/images | +| `action_button` | CTA that triggers callback | + +#### Extension Components + +Hosts MAY support additional components: + +| Component | Purpose | +|-----------|---------| +| `app_handoff` | Platform-specific app handoff | +| `integration_actions` | MCP/A2A installation prompts | + +Brand agents MUST NOT rely on extension components for core functionality. + +## UI Element Requirements + +### Standard Component Data + +Each standard component MUST include the required fields as defined in `si-ui-element.json`: + +**text**: `message` (required) + +**link**: `url`, `label` (required); `preview` (optional) + +**image**: `url`, `alt` (required); `caption` (optional) + +**product_card**: `title`, `price` (required); `subtitle`, `image_url`, `description`, `badge`, `cta` (optional) + +**carousel**: `items` (required); `title` (optional) + +**action_button**: `label`, `action` (required); `payload` (optional) + +### Action Handling + +When a user interacts with an `action_button`: + +1. The host MUST send an `action_response` via `si_send_message` +2. The `action_response` MUST include the `action` identifier +3. The `action_response` SHOULD include the `payload` if provided + +### Integration Actions + +The `integration_actions` component allows brand agents to offer persistent connections: + +```json +{ + "type": "integration_actions", + "data": { + "actions": [ + { "type": "mcp", "label": "Add as MCP Tool", "highlighted": true }, + { "type": "a2a", "label": "Connect via A2A" } + ] + } +} +``` + +Hosts MAY render integration actions if they support the integration type. + +## Identity and Privacy + +### Consent Requirements + +Hosts MUST obtain explicit user consent before sharing identity with brand agents. + +The consent flow MUST: + +1. Clearly identify what data will be shared +2. Reference the brand's privacy policy +3. Allow the user to decline + +### Identity Object + +When consent is granted, the `identity` object MUST include: + +- `consent_granted: true` +- `consent_timestamp` - When consent was obtained +- `consent_scope` - Array of data types consented to +- `privacy_policy_acknowledged.brand_policy_url` + +The `user` object MAY include: + +- `email` +- `name` +- `locale` +- `shipping_address` + +### Anonymous Sessions + +If consent is not granted: + +- `identity.consent_granted` MUST be `false` +- `identity.anonymous_session_id` SHOULD be provided +- No PII MUST be transmitted + +## Commerce Integration + +### ACP Handoff + +When `session_status` is `pending_handoff` with `handoff.type: "transaction"`: + +1. The host SHOULD initiate ACP checkout flow +2. The `handoff.intent` MUST describe the purchase intent +3. The `handoff.context_for_checkout` MAY include conversation context + +### Commerce Actions + +The `action_button` component MAY include commerce actions: + +| Action | Description | +|--------|-------------| +| `acp_checkout` | Initiate ACP checkout | +| `add_to_cart` | Add item to persistent cart | + +## Error Handling + +### Error Response + +Brand agents MUST return errors in the `errors` array using the standard error schema: + +```json +{ + "errors": [ + { + "code": "session_not_found", + "message": "Session has expired or does not exist" + } + ] +} +``` + +### Error Codes + +| Code | Description | +|------|-------------| +| `session_not_found` | Session ID is invalid or expired | +| `offer_unavailable` | Referenced offer is no longer available | +| `capability_unsupported` | Required capability not available | +| `rate_limited` | Too many requests | + +## Security Considerations + +### Transport Security + +All SI communications MUST use HTTPS with TLS 1.2 or higher. + +### Token Security + +- Availability tokens MUST be opaque and unpredictable +- Session IDs MUST be unique and unpredictable +- Tokens SHOULD expire within a reasonable timeframe + +### Data Minimization + +- Hosts MUST NOT send PII without consent +- Brand agents SHOULD minimize data collection +- Session data SHOULD be deleted after termination + +## Conformance + +### Host Conformance + +A conformant SI host MUST: + +1. Support MCP transport +2. Render all standard components +3. Implement session lifecycle (initiate, send, terminate) +4. Obtain consent before sharing identity +5. Support capability negotiation + +### Brand Agent Conformance + +A conformant SI brand agent MUST: + +1. Publish an SI manifest +2. Support at least one specified transport +3. Support conversational modality +4. Return valid session IDs +5. Handle all termination reasons + +## Version History + +| Version | Date | Changes | +|---------|------|---------| +| 1.0.0 | 2025-01 | Initial specification | diff --git a/docs/sponsored-intelligence/tasks/index.mdx b/docs/sponsored-intelligence/tasks/index.mdx new file mode 100644 index 0000000000..d5fa4dfc73 --- /dev/null +++ b/docs/sponsored-intelligence/tasks/index.mdx @@ -0,0 +1,109 @@ +--- +sidebar_position: 1 +title: Task Reference +--- + +The Sponsored Intelligence Protocol defines four tasks for managing conversational brand experiences: + +## Session Lifecycle + +```mermaid +flowchart LR + P[si_check_availability] -.-> A[si_initiate_session] + A --> B[si_send_message] + B --> B + B --> C[si_terminate_session] + A --> C +``` + +## Tasks + +| Task | Description | Initiator | +|------|-------------|-----------| +| [`si_check_availability`](./si_check_availability) | Check offer/product availability (anonymous) | Host | +| [`si_initiate_session`](./si_initiate_session) | Start a conversation with a brand agent | Host | +| [`si_send_message`](./si_send_message) | Exchange messages within an active session | Host | +| [`si_terminate_session`](./si_terminate_session) | End the session with appropriate handoff | Either | + +## Transport Options + +SI tasks work over both MCP and A2A protocols: + +### MCP Transport + +```json +{ + "method": "tools/call", + "params": { + "name": "si_initiate_session", + "arguments": { + "context": "User wants to fly to Boston next Tuesday morning", + "identity": { /* ... */ } + } + } +} +``` + +### A2A Transport + +```json +{ + "task": "si_initiate_session", + "payload": { + "context": "User wants to fly to Boston next Tuesday morning", + "identity": { /* ... */ } + } +} +``` + +## Common Patterns + +### Minimal Session (No Identity) + +For anonymous browsing without personalization: + +```json +{ + "context": "User interested in product information", + "identity": { + "consent_granted": false, + "anonymous_session_id": "anon_xyz789" + } +} +``` + +### Full Identity Session + +For personalized experiences with consented PII: + +```json +{ + "context": "User wants to book a flight", + "identity": { + "consent_granted": true, + "consent_timestamp": "2026-01-18T10:30:00Z", + "consent_scope": ["name", "email", "shipping_address"], + "user": { + "email": "jane@example.com", + "name": "Jane Smith" + } + } +} +``` + +### Campaign-Triggered Session + +When SI is invoked as part of a media buy: + +```json +{ + "context": "User searching for flights to Boston", + "media_buy_id": "media_buy_q1_promo", + "placement": "chatgpt_search", + "offer_id": "premium_upgrade_offer", + "identity": { + "consent_granted": true, + "user": { "email": "jane@example.com" } + } +} +``` diff --git a/docs/sponsored-intelligence/tasks/si_check_availability.mdx b/docs/sponsored-intelligence/tasks/si_check_availability.mdx new file mode 100644 index 0000000000..976de6db7c --- /dev/null +++ b/docs/sponsored-intelligence/tasks/si_check_availability.mdx @@ -0,0 +1,147 @@ +--- +sidebar_position: 1 +title: si_check_availability +--- + +Check offer or product availability before initiating a session. This anonymous pre-flight check allows hosts to verify availability without sharing user data. + +## Purpose + +The availability check serves two purposes: + +1. **Validate offers** - Confirm promotions are still active before showing them to users +2. **Provide correlation** - The returned token enables brand agents to correlate pre-flight checks with sessions + +## Request + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `offer_id` | string | Conditional | Brand-specific offer identifier to check | +| `product_id` | string | Conditional | Product identifier to check | +| `context` | string | No | Natural language context (no PII) | + +At least one of `offer_id` or `product_id` must be provided. + +### Privacy + +This request must not include any personally identifiable information. The `context` field may include intent description but must be anonymous. + +## Response + +| Field | Type | Description | +|-------|------|-------------| +| `available` | boolean | Whether the offer/product is currently available | +| `availability_token` | string | Token to pass to `si_initiate_session` | +| `ttl_seconds` | integer | How long this availability is valid | +| `checked_at` | string | ISO 8601 timestamp of the check | +| `offer_details` | object | Optional details about the offer | +| `unavailable_reason` | string | Why offer is unavailable (if not available) | +| `alternative_offer_ids` | array | Alternative offers to check | + +### Offer Details Object + +| Field | Type | Description | +|-------|------|-------------| +| `title` | string | Offer title | +| `summary` | string | Brief description | +| `expires_at` | string | When the offer expires | +| `price_hint` | string | Price indication (e.g., "from $199") | + +### Unavailable Reasons + +| Reason | Description | +|--------|-------------| +| `sold_out` | Product/offer inventory exhausted | +| `expired` | Offer past its end date | +| `region_restricted` | Not available in user's region | +| `inactive` | Campaign paused or ended | + +## Example + +### Request + +```json +{ + "offer_id": "expedia_delta_bos_328", + "product_id": "flight_dl632_jan25", + "context": "Looking for Tuesday morning flight to Boston" +} +``` + +### Response (Available) + +```json +{ + "available": true, + "availability_token": "avail_abc123xyz", + "ttl_seconds": 3600, + "checked_at": "2025-01-19T10:00:00Z", + "offer_details": { + "title": "Boston Flight Deal", + "summary": "Direct flights from $199 with free upgrade", + "expires_at": "2025-01-31T23:59:59Z", + "price_hint": "from $199" + } +} +``` + +### Response (Unavailable) + +```json +{ + "available": false, + "checked_at": "2025-01-19T10:00:00Z", + "unavailable_reason": "sold_out", + "alternative_offer_ids": [ + "expedia_delta_bos_alt_329", + "expedia_united_bos_330" + ] +} +``` + +## Using the Availability Token + +When initiating a session after an availability check, include the token: + +```json +{ + "context": "User wants Tuesday morning flight to Boston", + "offer_id": "expedia_delta_bos_328", + "availability": { + "token": "avail_abc123xyz", + "checked_at": "2025-01-19T10:00:00Z" + }, + "identity": { + "consent_granted": true, + "user": { ... } + } +} +``` + +## Key Points + +1. **Anonymous by design** - No user data is sent with availability checks. This protects user privacy while enabling hosts to verify offers. + +2. **Token correlation** - The availability token allows brand agents to correlate pre-flight checks with subsequent sessions, enabling analytics without PII. + +3. **Caching** - Hosts may cache availability responses for up to `ttl_seconds`. This reduces load on brand agents for frequently checked offers. + +4. **Graceful degradation** - If availability check fails or times out, hosts may still initiate sessions directly. The availability check is optional. + +5. **Alternative suggestions** - When offers are unavailable, brand agents may suggest alternatives via `alternative_offer_ids`. + +## Best Practices + +### For Hosts + +- Check availability before showing sponsored results to users +- Respect TTL for caching to avoid stale data +- Handle unavailable gracefully - don't show expired offers +- Include availability token in session initiation when available + +### For Brand Agents + +- Return meaningful `offer_details` to help hosts display accurate information +- Use reasonable TTL values (e.g., 5-60 minutes depending on volatility) +- Provide helpful `unavailable_reason` for debugging +- Suggest alternatives when primary offer is unavailable diff --git a/docs/sponsored-intelligence/tasks/si_initiate_session.mdx b/docs/sponsored-intelligence/tasks/si_initiate_session.mdx new file mode 100644 index 0000000000..b4406729b6 --- /dev/null +++ b/docs/sponsored-intelligence/tasks/si_initiate_session.mdx @@ -0,0 +1,181 @@ +--- +sidebar_position: 2 +title: si_initiate_session +--- + +Start a conversational session with a brand agent. The host platform invokes this task when a user expresses interest in engaging with a brand. + +## Request + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `context` | string | Yes | Natural language description of user intent | +| `identity` | object | Yes | User identity with consent status | +| `media_buy_id` | string | No | AdCP media buy ID if triggered by advertising | +| `placement` | string | No | Where the session was triggered (e.g., "chatgpt_search") | +| `offer_id` | string | No | Brand-specific offer reference to apply | +| `supported_capabilities` | object | No | What the host platform supports | +| `availability` | object | No | Token from pre-flight availability check | + +### Availability Object + +If a host performed a [`si_check_availability`](./si_check_availability) check before initiating, include the result: + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `token` | string | Yes | Availability token from pre-flight check | +| `checked_at` | string | No | ISO 8601 timestamp of when availability was checked | + +```json +{ + "availability": { + "token": "avail_abc123xyz", + "checked_at": "2025-01-19T10:00:00Z" + } +} +``` + +### Identity Object + +When `consent_granted` is `true`: + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `consent_granted` | boolean | Yes | Must be `true` | +| `consent_timestamp` | string | Yes | ISO 8601 timestamp of consent | +| `consent_scope` | array | Yes | Fields the user agreed to share | +| `privacy_policy_acknowledged` | object | No | Brand policy user accepted | +| `user` | object | Yes | User's PII | + +When `consent_granted` is `false`: + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `consent_granted` | boolean | Yes | Must be `false` | +| `anonymous_session_id` | string | Yes | Unique ID for this anonymous session | + +### Supported Capabilities Object + +Declares what the host platform can render: + +```json +{ + "modalities": { + "conversational": true, + "voice": { "providers": ["elevenlabs", "openai"] }, + "video": false, + "avatar": false + }, + "components": { + "standard": ["text", "link", "image", "product_card", "carousel", "action_button"], + "extensions": { + "chatgpt_apps_sdk": "1.0" + } + }, + "commerce": { + "acp_checkout": true + } +} +``` + +## Response + +| Field | Type | Description | +|-------|------|-------------| +| `session_id` | string | Unique identifier for this session | +| `response` | object | Brand agent's initial response | +| `negotiated_capabilities` | object | Intersection of brand and host capabilities | + +### Response Object + +| Field | Type | Description | +|-------|------|-------------| +| `message` | string | Text response from brand agent | +| `ui_elements` | array | Visual components to render | + +## Example + +### Request + +```json +{ + "context": "User wants to fly to Boston next Tuesday morning on flight 632 at 6 AM.", + "media_buy_id": "delta_q1_premium_upgrade", + "placement": "chatgpt_search", + "offer_id": "delta_chatgpt_3313", + "identity": { + "consent_granted": true, + "consent_timestamp": "2026-01-18T10:30:00Z", + "consent_scope": ["name", "email"], + "privacy_policy_acknowledged": { + "brand_policy_url": "https://delta.com/privacy", + "brand_policy_version": "2026-01" + }, + "user": { + "email": "jane@example.com", + "name": "Jane Smith", + "locale": "en-US" + } + }, + "supported_capabilities": { + "modalities": { + "conversational": true, + "voice": true + }, + "components": { + "standard": ["text", "link", "image", "product_card", "carousel", "action_button"] + }, + "commerce": { + "acp_checkout": true + } + } +} +``` + +### Response + +```json +{ + "session_id": "sess_abc123", + "response": { + "message": "Hi Jane! I found DL632 departing at 6:15 AM next Tuesday. Great news—as a SkyMiles Gold member, you qualify for our free Premium Economy upgrade on this flight.", + "ui_elements": [ + { + "type": "product_card", + "data": { + "title": "DL632 to Boston - Tue Jan 27", + "subtitle": "6:15 AM → 9:42 AM (3h 27m)", + "price": "$199", + "badge": "Free Premium Economy Upgrade", + "image_url": "https://delta.com/images/premium-economy.jpg", + "cta": { "label": "Book with Upgrade", "action": "checkout" } + } + } + ] + }, + "negotiated_capabilities": { + "modalities": { + "conversational": true, + "voice": true + }, + "components": { + "standard": ["text", "link", "image", "product_card", "carousel", "action_button"] + }, + "commerce": { + "acp_checkout": true + } + } +} +``` + +## Key Points + +1. **Context is a conversation handoff** - The host tells the brand agent what the user needs. The brand agent responds naturally, continuing the conversation. + +2. **Brand looks up loyalty data** - If Jane's email is recognized, Delta retrieves her SkyMiles status automatically. Hosts don't store loyalty numbers. + +3. **offer_id is brand-specific** - The brand interprets this reference to apply promotions, discounts, or loyalty rewards. Hosts pass it through without needing to understand offer semantics. + +4. **Capability negotiation** - The response includes `negotiated_capabilities` showing what features this session can use (intersection of brand and host capabilities). + +5. **Clear PII with explicit consent** - When `consent_granted` is true, actual email/name are passed (not hashed). This is a direct, consented handoff. diff --git a/docs/sponsored-intelligence/tasks/si_send_message.mdx b/docs/sponsored-intelligence/tasks/si_send_message.mdx new file mode 100644 index 0000000000..52db8518bb --- /dev/null +++ b/docs/sponsored-intelligence/tasks/si_send_message.mdx @@ -0,0 +1,209 @@ +--- +sidebar_position: 3 +title: si_send_message +--- + +Send a message within an active SI session. The host invokes this task to relay user messages and action responses to the brand agent. + +## Request + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `session_id` | string | Yes | Session ID from `si_initiate_session` | +| `message` | string | No | User's text message | +| `action_response` | object | No | Response to a UI action (button click, form submit) | + +At least one of `message` or `action_response` must be provided. + +### Action Response Object + +When the user interacts with a UI element: + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `action` | string | Yes | The action identifier from the UI element | +| `element_id` | string | No | ID of the specific UI element | +| `payload` | object | No | Additional data from the interaction | + +## Response + +| Field | Type | Description | +|-------|------|-------------| +| `session_id` | string | Confirms the active session | +| `response` | object | Brand agent's response | +| `session_status` | string | Current session state | +| `handoff` | object | Present when session_status is "pending_handoff" | + +### Session Status Values + +| Status | Description | +|--------|-------------| +| `active` | Session continues normally | +| `pending_handoff` | Brand agent signals readiness to hand off | +| `complete` | Conversation is done | + +### Handoff Object + +When `session_status` is `pending_handoff`: + +| Field | Type | Description | +|-------|------|-------------| +| `type` | string | "transaction" or "complete" | +| `intent` | object | For transactions: what the user wants to buy | +| `context_for_checkout` | object | Summary for ACP handoff | + +## Examples + +### Simple Message Exchange + +**Request:** + +```json +{ + "session_id": "sess_abc123", + "message": "Do you have any earlier flights?" +} +``` + +**Response:** + +```json +{ + "session_id": "sess_abc123", + "response": { + "message": "Yes! There's DL628 departing at 5:30 AM. It's a bit earlier but also qualifies for the Premium Economy upgrade.", + "ui_elements": [ + { + "type": "carousel", + "data": { + "items": [ + { + "title": "DL628 - 5:30 AM", + "subtitle": "Arrives 8:57 AM", + "price": "$199", + "badge": "Free Upgrade" + }, + { + "title": "DL632 - 6:15 AM", + "subtitle": "Arrives 9:42 AM", + "price": "$199", + "badge": "Free Upgrade" + } + ] + } + } + ] + }, + "session_status": "active" +} +``` + +### Action Response (Button Click) + +**Request:** + +```json +{ + "session_id": "sess_abc123", + "action_response": { + "action": "select_flight", + "payload": { + "flight_number": "DL628", + "departure_time": "05:30" + } + } +} +``` + +**Response:** + +```json +{ + "session_id": "sess_abc123", + "response": { + "message": "Great choice! DL628 is confirmed with your Premium Economy upgrade. Ready to book?", + "ui_elements": [ + { + "type": "product_card", + "data": { + "title": "DL628 to Boston", + "subtitle": "Tue Jan 27, 5:30 AM → 8:57 AM", + "price": "$199", + "badge": "Premium Economy", + "cta": { "label": "Book Now", "action": "checkout" } + } + } + ] + }, + "session_status": "active" +} +``` + +### Transaction Handoff + +When the user is ready to purchase: + +**Request:** + +```json +{ + "session_id": "sess_abc123", + "action_response": { + "action": "checkout" + } +} +``` + +**Response:** + +```json +{ + "session_id": "sess_abc123", + "response": { + "message": "Perfect! I'll hand you back to complete the booking." + }, + "session_status": "pending_handoff", + "handoff": { + "type": "transaction", + "intent": { + "action": "purchase", + "product": { + "type": "flight", + "flight_number": "DL628", + "departure": "2026-01-27T05:30:00-05:00", + "arrival": "2026-01-27T08:57:00-05:00", + "origin": "JFK", + "destination": "BOS", + "class": "premium_economy" + }, + "price": { + "amount": 199, + "currency": "USD" + } + }, + "context_for_checkout": { + "conversation_summary": "Jane selected DL628 JFK→BOS on Jan 27 with free Premium Economy upgrade via campaign offer", + "applied_offers": ["delta_chatgpt_3313"] + } + } +} +``` + +## Handling Handoffs + +When you receive `session_status: "pending_handoff"`: + +1. **For `type: "transaction"`** - Initiate ACP checkout with the provided intent and context +2. **For `type: "complete"`** - The conversation is done; return to normal chat + +The host should call `si_terminate_session` after handling the handoff to properly close the session. + +## Key Points + +1. **Message or action_response** - Each request needs at least one. Users can type messages or interact with UI elements. + +2. **Session status drives flow** - Check `session_status` on every response to know if the conversation continues or needs handoff. + +3. **Handoff preserves context** - The `context_for_checkout` object gives ACP everything needed for a seamless purchase experience. + +4. **UI elements are optional** - Brand agent decides when to include cards, carousels, etc. based on the conversation. diff --git a/docs/sponsored-intelligence/tasks/si_terminate_session.mdx b/docs/sponsored-intelligence/tasks/si_terminate_session.mdx new file mode 100644 index 0000000000..4d6644ab53 --- /dev/null +++ b/docs/sponsored-intelligence/tasks/si_terminate_session.mdx @@ -0,0 +1,282 @@ +--- +sidebar_position: 4 +title: si_terminate_session +--- + +End an SI session. Either the host or brand agent can initiate termination, with different reasons indicating how the session concluded. + +## Request + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `session_id` | string | Yes | Session ID to terminate | +| `reason` | string | Yes | Why the session is ending | +| `termination_context` | object | No | Additional context for the termination | + +### Termination Reasons + +| Reason | Meaning | Typical Initiator | +|--------|---------|-------------------| +| `handoff_transaction` | User wants to complete a purchase | Brand agent (via pending_handoff) | +| `handoff_complete` | Conversation naturally concluded | Brand agent | +| `user_exit` | User explicitly ended the conversation | Host | +| `session_timeout` | Inactivity timeout reached | Host | +| `host_terminated` | Host ended for policy/error reasons | Host | + +### Termination Context Object + +Additional details vary by reason: + +**For `handoff_transaction`:** +```json +{ + "intent": { /* purchase intent from handoff */ }, + "context_for_checkout": { /* ACP context */ } +} +``` + +**For `user_exit`:** +```json +{ + "user_signal": "changed_topic", + "partial_context": { /* what was discussed */ } +} +``` + +**For `session_timeout`:** +```json +{ + "last_activity": "2026-01-18T10:30:00Z", + "timeout_seconds": 300 +} +``` + +## Response + +| Field | Type | Description | +|-------|------|-------------| +| `session_id` | string | Confirms which session was terminated | +| `terminated` | boolean | Always `true` on success | +| `acp_handoff` | object | Present for transaction handoffs | +| `follow_up` | object | Optional actions for future engagement | + +### ACP Handoff Object + +For transaction terminations, includes data needed for ACP checkout: + +| Field | Type | Description | +|-------|------|-------------| +| `checkout_url` | string | Brand's ACP checkout endpoint | +| `payload` | object | Data to pass to ACP | +| `expires_at` | string | ISO 8601 expiration for the checkout context | + +### Follow-Up Object + +Suggestions for future engagement: + +| Field | Type | Description | +|-------|------|-------------| +| `suggested_action` | string | What the host might do next | +| `data` | object | Relevant data for the action | +| `message` | string | Optional message to display | + +## Examples + +### Transaction Handoff + +After receiving `pending_handoff` with `type: "transaction"`: + +**Request:** + +```json +{ + "session_id": "sess_abc123", + "reason": "handoff_transaction", + "termination_context": { + "intent": { + "action": "purchase", + "product": { + "type": "flight", + "flight_number": "DL628" + } + } + } +} +``` + +**Response:** + +```json +{ + "session_id": "sess_abc123", + "terminated": true, + "acp_handoff": { + "checkout_url": "https://delta.com/acp/checkout", + "payload": { + "session_id": "sess_abc123", + "flight": "DL628", + "passenger": { + "email": "jane@example.com", + "name": "Jane Smith" + }, + "applied_offers": ["delta_chatgpt_3313"], + "price": { + "amount": 199, + "currency": "USD" + } + }, + "expires_at": "2026-01-18T11:00:00Z" + } +} +``` + +### Conversation Complete (No Purchase) + +When the conversation naturally ends without a transaction: + +**Request:** + +```json +{ + "session_id": "sess_abc123", + "reason": "handoff_complete" +} +``` + +**Response:** + +```json +{ + "session_id": "sess_abc123", + "terminated": true, + "follow_up": { + "suggested_action": "save_for_later", + "data": { + "flights_discussed": ["DL628", "DL632"], + "destination": "BOS", + "travel_date": "2026-01-27" + }, + "message": "Let me know if you'd like to revisit Boston flights later!" + } +} +``` + +### User Exit + +When the user changes topic or explicitly leaves: + +**Request:** + +```json +{ + "session_id": "sess_abc123", + "reason": "user_exit", + "termination_context": { + "user_signal": "changed_topic", + "partial_context": { + "flights_viewed": ["DL628"], + "last_topic": "seat selection" + } + } +} +``` + +**Response:** + +```json +{ + "session_id": "sess_abc123", + "terminated": true, + "follow_up": { + "suggested_action": "remind_later", + "data": { + "incomplete_booking": { + "flight": "DL628", + "step": "seat_selection" + } + } + } +} +``` + +### Session Timeout + +When the session times out due to inactivity: + +**Request:** + +```json +{ + "session_id": "sess_abc123", + "reason": "session_timeout", + "termination_context": { + "last_activity": "2026-01-18T10:25:00Z", + "timeout_seconds": 300 + } +} +``` + +**Response:** + +```json +{ + "session_id": "sess_abc123", + "terminated": true +} +``` + +### Host Terminated + +When the host ends the session for policy or error reasons: + +**Request:** + +```json +{ + "session_id": "sess_abc123", + "reason": "host_terminated", + "termination_context": { + "cause": "user_left_app" + } +} +``` + +**Response:** + +```json +{ + "session_id": "sess_abc123", + "terminated": true +} +``` + +## ACP Integration Flow + +When the reason is `handoff_transaction`: + +```mermaid +sequenceDiagram + participant H as Host + participant B as Brand Agent + participant A as ACP + + H->>B: si_terminate_session(handoff_transaction) + B->>H: { acp_handoff: { checkout_url, payload } } + H->>A: Initiate checkout with payload + A->>H: Checkout flow +``` + +1. Host receives `acp_handoff` in the termination response +2. Host initiates ACP checkout using the provided `checkout_url` and `payload` +3. ACP handles the transaction while maintaining the user's trust with the host +4. Brand is not the merchant of record - ACP handles payment + +## Key Points + +1. **Always terminate sessions** - Even if the conversation seems done, call terminate to clean up resources and get follow-up suggestions. + +2. **ACP handoff data has expiration** - The `expires_at` field indicates how long the checkout context is valid. + +3. **Follow-up enables re-engagement** - Even non-transaction terminations can include suggestions for future engagement. + +4. **Host maintains trust** - Transactions go through ACP, keeping the user's relationship with the host intact. diff --git a/server/public/chat.html b/server/public/chat.html index fb5db3f105..fed128d555 100644 --- a/server/public/chat.html +++ b/server/public/chat.html @@ -7,6 +7,7 @@ + @@ -1309,6 +1963,43 @@
+ +
+
+
+
+ 🏢 +
+
+

Brand Agent

+

+
+ Sponsored + +
+
+ +
+
+ + +
+
+
+