Module: Commerce Protocol (Sections 5–9) Parent: AURA Protocol Specification v2.2 Version: 2.2 Date: April 14, 2026 Covers: Scout Request Protocol, Interpretation, Beacon Requests, Beacon Responses, Offer Ranking & Delivery
Scout initiates a commerce session by expressing intent in natural language:
POST /v1/sessions
Request:
{
"intent": "I need wireless headphones for my daily commute. Noise cancellation is important because the train is loud. Budget around $300-400.",
"constraints": {
"maxBudget": 400,
"deliveryBy": "2026-02-01",
"categories": ["electronics", "headphones"]
},
"completeness": {
"complete": true,
"missing": [],
"confidence": 0.92,
"rounds": 2
},
"profile_id": "prf_retail_consumer_v1",
"settlement_preference": {
"preferred_methods": ["stablecoin_usdc", "rtp"],
"networks": ["ethereum"]
},
"risk_tolerance": {
"max_reserve_margin_pct": 0.05,
"max_dispute_window_days": 30
}
}
| Field | Type | Required | Description |
|---|---|---|---|
intent |
string | Yes | Natural language expression of need (max 2000 chars) |
constraints |
object | No | Structured constraints (max 10KB JSON) |
completeness |
object | No | Scout SDK completeness attestation (informational only — see Note) |
sub_intents |
array|null | No | Reserved (Section 5.4). Sub-intent array for compound sessions. Do not send until compound intent is supported. |
profile_id |
string | No | (DEC-044) Market Profile identifier. If omitted, the Core instance’s default profile applies. The session binds to the profile version active at creation time — profile revisions do not affect in-flight sessions. See MARKET_PROFILES.md. |
settlement_preference |
object | No | (Phase 7) Scout’s preferred settlement methods and networks. Used by Core to filter Beacons and pre-compute clearing compatibility. |
risk_tolerance |
object | No | (Phase 7) Scout’s acceptable risk parameters. max_reserve_margin_pct filters offers whose estimated margin exceeds tolerance. max_dispute_window_days filters offers with longer windows than desired. |
parent_session_id |
string|null | No | Reserved (Section 5.4). Parent session UUID for sub-sessions. Do not send until compound intent is supported. |
budget |
object|null | No | Reserved (Section 5.4). Aggregate budget tracking: { "total", "currency", "allocated", "remaining" }. |
Note on Completeness Attestation: The
completenessfield is an optional attestation from the Scout SDK’sIntentSessionclass. It is informational, not authoritative — Core always parses intent independently (ref: NEUTRAL_BROKER.md Property 1). The attestation is stored in session context for observability and diagnostics. Thecompletefield indicates whether the Scout SDK’s local completeness check passed;missinglists any categories the Scout SDK could not detect;confidenceis the average detection confidence (0-1);roundsis the number ofIntentSession.submit()calls that occurred.
Response (201 Created):
{
"sessionId": "uuid-...",
"status": "collecting_offers",
"intent": { "raw": "I need wireless headphones...", "parsed": { "..." } },
"matchedBeacons": [],
"created_at": "2026-01-14T10:00:00Z",
"_links": {
"self": "/v1/sessions/uuid-...",
"offers": "/v1/sessions/uuid-.../offers"
}
}
Scout can poll for session updates:
GET /v1/sessions/{session_id}
Response (200 OK):
{
"session_id": "ses_01HXYZ...",
"status": "offers_ready",
"created_at": "2026-01-14T10:00:00Z",
"updated_at": "2026-01-14T10:00:35Z",
"interpreted_request": {
"structured_requirements": {
"category": "electronics.headphones.over_ear",
"hard_constraints": {
"price_max_usd": 400,
"in_stock": true,
"ships_to": "US"
},
"soft_preferences": {
"brands": ["Sony"],
"features": ["noise_cancellation", "wireless"],
"price_range_usd": {"min": 300, "max": 400}
}
},
"natural_language_context": {
"content": "User commutes daily by train, needs noise cancellation. Previously satisfied with Sony products. Looking for quality audio experience for music during commute.",
"language": "en",
"sanitized": true
}
},
"offers_count": 8,
"offers_url": "/v1/sessions/ses_01HXYZ.../offers"
}
For real-time updates, connect via WebSocket:
wss://aura.example.com/ws/sessions/{session_id}
Authentication: Include bearer token as query parameter:
wss://aura.example.com/ws/sessions/ses_01HXYZ...?token=sk_example_...
Server Messages:
{
"event": "status_changed",
"session_id": "ses_01HXYZ...",
"status": "collecting_offers",
"timestamp": "2026-01-14T10:00:15Z"
}
{
"event": "offer_received",
"session_id": "ses_01HXYZ...",
"offer_id": "ofr_01HXYZ...",
"rank": 3,
"beacon_id": "bcn_01HXYZ...",
"preview": {
"product_name": "Sony WH-1000XM5",
"price_usd": 349.99,
"beacon_score": 87.5
},
"timestamp": "2026-01-14T10:00:20Z"
}
{
"event": "offers_ready",
"session_id": "ses_01HXYZ...",
"total_offers": 8,
"timestamp": "2026-01-14T10:00:35Z"
}
Status: Schema reserved. Not yet enforced by Core API. Integrators SHOULD NOT send these fields until Core announces compound intent support. Fields are documented here to reserve schema space and prevent breaking changes when compound intent is implemented.
A compound intent arises when a single Scout utterance decomposes into multiple independent sub-intents, each routed to a different Beacon cohort. The canonical example is a travel request — “I want to take my family to Tuscany this October for $8,000” — which decomposes into sub-intents for accommodation, flights, activities, and transfers, each fulfilled by independent suppliers.
Scout utterance
│
▼
┌─────────────────────────────────────────────────┐
│ AURA Core — Intent Decomposition │
│ "Family trip to Tuscany, $8k budget" │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
│ │ Sub- │ │ Sub- │ │ Sub- │ │
│ │ intent 1 │ │ intent 2 │ │ intent N │ │
│ │ Flights │ │ Villa │ │ Day trips │ │
│ │ 4 pax │ │ sleeps 4 │ │ family-friendly │ │
│ └─────┬─────┘ └─────┬─────┘ └────────┬────────┘ │
└────────│─────────────│───────────────│───────────┘
▼ ▼ ▼
Beacon cohort Beacon cohort Beacon cohort
(airlines) (villas) (tour operators)
In the compound model:
The following fields are reserved on the session object. They are nullable and MUST NOT be sent by integrators until compound intent is formally supported.
| Field | Type | Description |
|---|---|---|
sub_intents |
array|null | Array of SubIntent objects decomposed from the parent intent. Null for simple (non-compound) sessions. |
parent_session_id |
string|null | UUID of the parent session, when this session represents a single sub-intent in a compound flow. Null for top-level sessions. |
budget |
object|null | Aggregate budget tracking: { "total": number, "currency": string, "allocated": number, "remaining": number }. |
Each element in the sub_intents array has the following shape:
{
"id": "sub_01HXYZ...",
"type": "accommodation",
"domain": "travel.lodging",
"structured_requirements": {
"category": "travel.lodging.villa",
"hard_constraints": {
"sleeps_min": 4,
"kitchen": true,
"location": "Tuscany, Italy",
"check_in": "2026-10-05",
"check_out": "2026-10-12"
},
"soft_preferences": {
"features": ["pool", "garden", "rural"]
}
},
"completeness": {
"complete": true,
"missing": [],
"confidence": 0.91
},
"status": "collecting_offers",
"excluded": false,
"exclusion_reason": null,
"budget_allocation": {
"suggested": 2500,
"currency": "USD"
}
}
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | Unique sub-intent identifier |
type |
string | Yes | Human-readable sub-intent category (e.g., “accommodation”, “flights”, “activities”) |
domain |
string | Yes | Machine-readable domain classification (e.g., “travel.lodging”) |
structured_requirements |
object | Yes | Requirements for this sub-intent, same schema as top-level interpreted_request.structured_requirements |
completeness |
object | No | Per-sub-intent completeness attestation |
status |
string | Yes | Sub-intent lifecycle state (uses the same state enumeration as sessions — see Section 4.5.1) |
excluded |
boolean | Yes | true if Scout explicitly declined this sub-intent |
exclusion_reason |
string|null | No | Why the sub-intent was excluded (e.g., “Scout declined travel insurance”) |
budget_allocation |
object|null | No | Suggested budget for this sub-intent: { "suggested": number, "currency": string } |
The following fields are reserved on the offer request payload sent to Beacons (Section 7.1). They enable Beacons to understand which sub-intent they are bidding on and how much budget remains.
| Field | Type | Description |
|---|---|---|
sub_intent_id |
string|null | The sub-intent this offer request targets. Null for simple sessions. |
budget_remaining |
object|null | Aggregate remaining budget across all sub-intents: { "amount": number, "currency": string }. Individual supplier pricing is never disclosed — only the aggregate. |
Information sovereignty: A Beacon receiving an offer request for “accommodation” with
budget_remaining: { "amount": 4950, "currency": "USD" }knows the total trip budget is being consumed by other suppliers, but cannot determine what any individual supplier charged. This prevents price anchoring while enabling budget-aware offers.
The following fields are reserved on the commit request and transaction response (Section 10.2).
| Field | Type | Description |
|---|---|---|
sub_intent_id |
string|null | The sub-intent this transaction settles. Null for simple sessions. |
When compound intent is active, each sub-intent produces its own independent transaction. The parent session tracks aggregate transaction status across all sub-intents.
1. Scout submits utterance → Parent session created
2. Core decomposes intent → sub_intents[] populated
3. Per sub-intent:
a. Core routes to Beacon cohort → Offer requests include sub_intent_id
b. Beacons submit offers → Offers tagged with sub_intent_id
c. Scout commits per sub-intent → Transaction per sub-intent
d. Budget updated → budget.remaining decremented
4. All sub-intents committed → Parent session → completed
(or some excluded/cancelled)
Relationship to state machine (Section 4.5): Each sub-intent follows the same state transition table as a simple session. The parent session transitions to
completedonly when all non-excluded sub-intents have reached a terminal state.
Intent interpretation in AURA follows a three-layer architecture (ref: ADR-002). Each layer operates independently with graceful degradation, and Core retains exclusive semantic authority over the final parsed intent.
┌─────────────────────────────────────────────────┐
│ Layer 1: @aura-labs-ai/nlp (Shared Module) │
│ - 8-category tiered completeness detection │
│ - Regex + LLM hybrid detection │
│ - Clarification question generation │
│ - LLM provider abstraction (Mock/Together/FW) │
│ Used by: Scout SDK, Core intent-svc, Beacon SDK│
├─────────────────────────────────────────────────┤
│ Layer 2: Scout SDK + Core Intent Service │
│ - Scout IntentSession: local completeness gate │
│ - Core intent-svc: LLM-powered parsing │
│ - Core parseIntentWithFallback: tries intent- │
│ svc, falls back to local regex parser │
│ - Completeness attestation → session context │
├─────────────────────────────────────────────────┤
│ Layer 3: Beacon SDK Catalog Matching │
│ - interpretIntent(): domain-specific matching │
│ - Keyword/tag scoring against product catalog │
│ - Presence detection only (not semantic auth.) │
└─────────────────────────────────────────────────┘
Key principle: Core retains semantic authority. Scout and Beacon layers perform presence detection and domain-specific matching — they inform but do not override Core’s interpretation.
@aura-labs-ai/nlp)The shared module provides 8-category tiered completeness checking:
| Category | Tier | Detection | Description |
|---|---|---|---|
what |
1 (required) | model/hybrid | What the buyer wants |
how_many |
1 (required) | regex | Quantity needed |
how_much_cost |
1 (required) | regex | Budget or price range |
when_needed |
1 (required) | regex | Delivery timeline |
what_kind |
2 (conditional) | model/hybrid | Specific characteristics |
where_deliver |
2 (conditional) | regex | Delivery location |
quality_level |
2 (conditional) | model | Quality preferences |
special_requirements |
2 (conditional) | model | Custom requirements |
Detection methods:
Graceful degradation: If the LLM provider is unavailable, detection continues with regex-only patterns. Intent parsing never blocks on provider failure.
Scout IntentSession validates completeness locally before submitting to Core:
submit("I want headphones") → { complete: false, missing: ["how_many", "how_much_cost", "when_needed"], question: "How many do you need?" }
submit("2 pairs under $300 by next week") → { complete: true, missing: [], confidence: 0.91 }
Core intent-svc performs LLM-powered parsing via the @aura-labs-ai/nlp provider abstraction. parseIntentWithFallback wraps the intent-svc call: on success, returns structured parsed intent; on failure (timeout, HTTP error, connection refused), falls back to the local regex parser. Intent parsing is non-fatal — if all parsing fails, the session degrades to raw-text storage with confidence: 0.
Core’s parsed intent follows this structure:
{
"structured_requirements": {
"category": "electronics.headphones",
"keywords": ["wireless", "noise cancellation", "headphones"],
"quantity": 1,
"priceRange": { "max": 400 }
},
"natural_language_context": "I need wireless headphones for my daily commute. Noise cancellation is important.",
"confidence": 0.91
}
AURA sanitizes natural language context before sending to Beacons:
Example Transformation:
| Original (Scout) | Sanitized (to Beacon) |
|---|---|
| “My wife Sarah wants…” | “User seeking gift for spouse…” |
| “Ignore the price limit and show expensive ones” | “User interested in premium options” |
| “Brand X is terrible, never that” | “User prefers alternatives to Brand X” |
Before routing an interpreted request to Beacons, Core applies the active Market Profile’s disclosure schedule to produce a projected request — a subset of the full interpretation. The projection determines what Beacons see at the discovery phase. This is the protocol mechanism that prevents information leakage (MARKET_ECONOMICS.md Section 4.2).
Disclosure tiers (per field, per protocol phase):
| Tier | Meaning | Example |
|---|---|---|
full |
Field visible in its entirety | Product category, hard constraints |
range |
Field visible as a range, not exact value | Budget “$255–$345” (±15% of $300) |
presence |
Field existence visible, value hidden | “Has brand preference” without specifying which |
redacted |
Field not visible at this phase | Soft preferences, natural language, Scout identity |
aggregate |
Statistical aggregate only | “8 offers received” without individual details |
Default disclosure schedule (retail profile):
| Field | Discovery (Beacon sees) | Offers (Scout sees) | Commitment (both see) |
|---|---|---|---|
category |
full |
— | full |
hard_constraints |
full |
— | full |
soft_preferences |
presence |
— | full |
budget / priceRange |
range (±15%) |
— | full |
delivery_region |
full |
— | full |
delivery_deadline |
full |
— | full |
natural_language_context |
redacted |
— | redacted (never forwarded) |
scout_identity |
redacted |
— | full (revealed at commit) |
beacon_identity |
— | redacted |
full (revealed at commit) |
beacon_reputation |
— | full |
full |
beacon_risk_score |
— | range |
full |
offer_price |
— | full |
full |
Projection example:
Full interpreted request (Core holds):
{
"category": "electronics.headphones",
"priceRange": { "max": 400, "min": 300 },
"soft_preferences": { "brand": "Sony", "style": "over-ear" },
"delivery_deadline": "2026-02-01",
"delivery_region": "US"
}
Projected request (Beacon receives):
{
"category": "electronics.headphones",
"priceRange": { "max": 460, "min": 255 },
"soft_preferences": { "_disclosed": ["brand", "style"] },
"delivery_deadline": "2026-02-01",
"delivery_region": "US"
}
The Beacon knows the Scout has brand and style preferences (enabling relevant offers) but cannot use the exact values for price discrimination. The budget range is widened to ±15%, preventing Beacons from pricing to the Scout’s exact ceiling.
Monotonic disclosure guarantee (Principle 2.16): Fields can only become MORE visible as commitment increases. A field visible as range at discovery cannot become redacted at offers. Profiles that violate monotonicity are rejected at validation.
Profile override: Non-default profiles may adjust disclosure schedules. A B2B procurement profile may set soft_preferences to full at discovery (procurement agents need detailed specs for accurate quoting). The protocol enforces the tier model and monotonicity; the profile sets the per-field values.
When Core interprets a Scout’s natural language intent into structured requirements, it MUST produce a signed attestation binding the input to the output. This attestation provides an auditable chain from the consumer’s original declaration through to the structured interpretation that drives Beacon matching and offer generation.
Attestation Structure:
{
"type": "interpretation_attestation",
"session_id": "ses_01HXYZ...",
"original_input": {
"raw_text": "I need two pairs of white running shoes under £150, delivered by Friday",
"language": "en",
"received_at": "2026-03-26T14:30:00Z"
},
"structured_output": {
"category": "footwear.running_shoes",
"keywords": ["white", "running shoes"],
"quantity": 2,
"priceRange": { "max": 15000, "currency": "GBP" },
"delivery_deadline": "2026-03-28T23:59:59Z"
},
"interpretation_metadata": {
"model_id": "aura-intent-v2.1",
"model_version": "2026-03-15",
"confidence": 0.94,
"interpretation_method": "model",
"fallback_used": false
},
"attestation_signature": "Ed25519 signature by Core's signing key",
"core_key_id": "core_01HXYZ..."
}
Requirements:
original_input.raw_text field MUST contain the Scout’s unmodified natural language input as received by Core. This field is NEVER forwarded to Beacons.structured_output field MUST contain the interpreted requirements that are used for Beacon matching and forwarded in offer requests.interpretation_metadata.model_id and model_version fields MUST identify the specific interpretation model and version used.attestation_signature MUST be an Ed25519 signature over the canonical JSON of the attestation body (excluding the signature field itself), signed with Core’s private key.GET /v1/sessions/:id/attestation.Rationale: This attestation creates a verifiable chain from spoken intent through structured interpretation. If the interpretation was incorrect — the consumer said “running shoes” but the structured output matched “hiking boots” — the divergence is visible, attributable to a specific model version, and available to all parties. See MARKET_ECONOMICS.md Section 9 for the economic rationale.
AURA sends offer requests to qualified Beacons via webhook:
POST {beacon_webhook_url}
Request from AURA to Beacon:
{
"request_type": "offer_request",
"request_id": "req_01HXYZ...",
"session_id": "ses_01HXYZ...",
"timestamp": "2026-01-14T10:00:12Z",
"respond_by": "2026-01-14T10:00:42Z",
"response_url": "https://aura.example.com/v1/sessions/ses_01HXYZ.../offers",
"interpreted_request": {
"structured_requirements": {
"category": "electronics.headphones.over_ear",
"hard_constraints": {
"price_max_usd": 400,
"in_stock": true,
"ships_to": "US"
},
"soft_preferences": {
"brands": {"preferred": ["Sony"], "acceptable": ["Bose", "Apple"]},
"features": {"required": ["noise_cancellation", "wireless"]}
}
},
"natural_language_context": {
"content": "Daily train commuter seeking premium audio experience. Values previous positive experience with Sony. Noise cancellation essential due to noisy environment.",
"language": "en",
"sanitized": true
}
},
"beacon_context": {
"your_categories": ["electronics", "audio"],
"matching_reason": "category_match",
"recommended_products": ["electronics.headphones.*"]
},
"signature": "sig_aura_..."
}
| Field | Type | Description |
|---|---|---|
request_id |
string | Unique identifier for this request |
session_id |
string | Session ID (for response correlation) |
respond_by |
timestamp | Deadline for offer submission |
response_url |
string | URL to submit offers |
interpreted_request |
object | Scout’s interpreted requirements |
beacon_context |
object | Context about why this Beacon was selected |
signature |
string | AURA’s signature for request authenticity |
sub_intent_id |
string|null | Reserved (Section 5.4.4). Sub-intent this request targets. Null for simple sessions. |
budget_remaining |
object|null | Reserved (Section 5.4.4). Aggregate remaining budget: { "amount", "currency" }. Individual supplier pricing never disclosed. |
Before generating offers, Beacons can use interpretIntent() to match the incoming intent against their product catalog. This is Layer 3 of the three-layer NLP architecture (ref: ADR-002).
const result = await beacon.interpretIntent(session.intent.raw, catalog);
// result: { matches, confidence, categories, suggestions }
Catalog matching algorithm:
| Field | Weight | Description |
|---|---|---|
name |
+20 per word overlap | Product name keyword matching |
category |
+15 per word overlap | Category keyword matching |
tags |
+10 per word overlap | Tag keyword matching |
InterpretResult schema:
{
"matches": [
{ "item": { "name": "Wireless NC Headphones", "sku": "HP-001" }, "score": 55, "matchedOn": ["name", "category"] }
],
"confidence": 0.87,
"categories": { "what": { "present": true, "confidence": 0.9 }, "how_many": { "present": true, "confidence": 0.9 } },
"suggestions": ["What price range are you looking for?"]
}
Design constraint: Beacon interpretation is presence detection only, not semantic authority. Core retains exclusive authority over intent parsing (ref: NEUTRAL_BROKER.md Property 1).
Graceful degradation: If the LLM provider is unavailable, interpretIntent() continues with regex-only detection. If all detection fails, returns { matches: [], confidence: 0, categories: {}, suggestions: [] }.
AURA selects Beacons based on:
settlement_preference.preferred_methods. If no overlap, Beacon is excluded.Beacon submits offers to the provided response URL:
POST /v1/sessions/{session_id}/offers
Request:
{
"request_id": "req_01HXYZ...",
"beacon_id": "bcn_01HXYZ...",
"offers": [
{
"offer_id": "ofr_01HABC...",
"product": {
"product_id": "prod_sony_wh1000xm5",
"name": "Sony WH-1000XM5 Wireless Noise Canceling Headphones",
"category": "electronics.headphones.over_ear",
"structured_attributes": {
"brand": "Sony",
"model": "WH-1000XM5",
"color": "black",
"connectivity": "bluetooth_5.2",
"features": ["noise_cancellation", "wireless", "foldable", "multipoint", "speak_to_chat"],
"battery_hours": 30,
"weight_grams": 250,
"driver_size_mm": 30
},
"natural_language_description": {
"content": "Our flagship noise-canceling headphones, perfect for commuters who demand the best. Industry-leading noise cancellation automatically optimizes based on your environment. 30-hour battery life gets you through the longest trips. Premium comfort with soft-fit leather and lightweight design at only 250g. Seamless switching between devices with multipoint connection. Speak-to-Chat pauses music when you talk. Ideal for the discerning audio enthusiast who won't compromise on quality.",
"language": "en"
}
},
"pricing": {
"currency": "USD",
"list_price": 399.99,
"offer_price": 349.99,
"discount_percentage": 12.5,
"price_valid_until": "2026-01-14T22:00:00Z",
"price_rationale": "Loyal customer appreciation pricing"
},
"availability": {
"in_stock": true,
"quantity_available": 45,
"estimated_ship_date": "2026-01-15",
"delivery_estimate_days": {"min": 2, "max": 5},
"shipping_options": [
{"method": "standard", "days": "3-5", "price_usd": 0},
{"method": "express", "days": "1-2", "price_usd": 14.99}
]
},
"terms": {
"return_policy": "30-day free returns, no questions asked",
"warranty": "1-year manufacturer warranty, extendable",
"price_match": true
},
"valid_until": "2026-01-14T22:00:00Z"
}
],
"beacon_metadata": {
"merchant_name": "Acme Electronics",
"merchant_url": "https://acme-electronics.example.com",
"support_email": "support@acme-electronics.example.com",
"certifications": ["bbb_accredited", "google_trusted_store"]
},
"signature": "sig_beacon_..."
}
Beacons MUST sign offers to ensure authenticity and prevent tampering.
The signature payload is formed by joining fields with a newline (\n)
delimiter. Field order is normative — implementations MUST use exactly
this sequence:
signature_payload = offer_id + "\n"
+ beacon_id + "\n"
+ product_id + "\n"
+ offer_price + "\n"
+ currency + "\n"
+ valid_until + "\n"
+ payment_terms_hash
signature = Ed25519.sign(signature_payload, beacon_private_key)
(Phase 7) The payment_terms_hash is a SHA-256 hash of the canonical JSON representation of the payment_terms object. This ensures the Beacon cannot retroactively claim it offered different terms. If no payment_terms are present (pre-Phase 7 offers), the field is omitted and valid_until remains the last field.
payment_terms_hash = SHA256(JSON.stringify(payment_terms, Object.keys(payment_terms).sort()))
All fields are serialised as UTF-8 strings. Numeric fields (offer_price)
use their decimal string representation with no trailing zeros beyond two
decimal places (e.g., "349.99", not "349.990").
Why newline-delimited? The v1.0 spec used bare concatenation (
offer_id + beacon_id + ...) which is ambiguous — there is no way to distinguish where one field ends and the next begins. For example,offer_id="ofr_ab"+beacon_id="cd"produces the same payload asoffer_id="ofr_a"+beacon_id="bcd". Newline delimiters eliminate this class of collision.
Worked example:
# Fields
offer_id = "ofr_01HABC"
beacon_id = "bcn_02HXYZ"
product_id = "prod_WH1000XM5"
offer_price = "349.99"
currency = "USD"
valid_until = "2026-01-14T10:30:00Z"
# Payload (32 bytes of field data + 5 newline delimiters)
"ofr_01HABC\nbcn_02HXYZ\nprod_WH1000XM5\n349.99\nUSD\n2026-01-14T10:30:00Z"
# Signature
Ed25519.sign(payload, beacon_private_key) → "sig_MEUCIQDx..."
AURA Core verifies Beacon signatures before presenting offers to Scouts. The Beacon’s Ed25519 public key (registered during Beacon onboarding) is used for verification.
AURA Core does not currently counter-sign offers before presenting them to Scouts. This means a Beacon could theoretically claim it submitted an offer that Core never received, since only the Beacon’s signature exists.
A future protocol version will add a Core counter-signature: after verifying the Beacon’s signature, Core appends its own Ed25519 signature over the Beacon-signed payload plus a Core-assigned receipt timestamp. This provides non-repudiation — the Scout can verify that Core received and relayed the offer, and the Beacon can verify that Core presented its offer unmodified.
# Future: Core counter-signature (reserved, not yet implemented)
core_payload = beacon_signature + "\n" + core_receipt_timestamp
core_counter_signature = Ed25519.sign(core_payload, core_private_key)
Beacons MAY submit multiple offers per request (e.g., different product variants, pricing tiers):
{
"offers": [
{ "offer_id": "ofr_01HABC...", "product": {...}, "pricing": {"offer_price": 349.99} },
{ "offer_id": "ofr_01HDEF...", "product": {...}, "pricing": {"offer_price": 279.99} },
{ "offer_id": "ofr_01HGHI...", "product": {...}, "pricing": {"offer_price": 199.99} }
]
}
Maximum offers per Beacon per session: 5 (configurable).
Beacons receive notifications from AURA Core via webhooks. This mechanism enables semi-autonomous Beacon behavior, including proactive notifications and event-driven responses.
Beacons specify their webhook URL during registration. AURA sends HTTP POST requests to this URL for all events.
Webhook Security:
X-AURA-Signature header| Event Type | Description | Beacon Action Required |
|---|---|---|
offer_request |
New offer request from Scout | Generate and submit offers |
offer_accepted |
Scout committed to Beacon’s offer | Prepare for fulfillment |
transaction_confirmed |
Payment successfully processed | Begin fulfillment |
transaction_cancelled |
Transaction cancelled by Scout | Cancel pending fulfillment |
transaction_completed |
Order delivered, transaction closed | Update records |
policy_violation |
Beacon offer violated Scout/AURA policy | Review and adjust offers |
reputation_updated |
Beacon reputation score changed | Informational |
All webhooks follow a standard envelope:
{
"event_id": "evt_01HXYZ...",
"event_type": "offer_accepted",
"timestamp": "2026-01-14T10:35:00Z",
"beacon_id": "bcn_01HXYZ...",
"payload": {
// Event-specific data
},
"signature": "sig_aura_..."
}
Sent when AURA routes a Scout request to this Beacon:
{
"event_type": "offer_request",
"payload": {
"request_id": "req_01HXYZ...",
"session_id": "ses_01HXYZ...",
"respond_by": "2026-01-14T10:00:42Z",
"response_url": "https://api.aura.example.com/v1/sessions/ses_01HXYZ.../offers",
"interpreted_request": {
"structured_requirements": {...},
"natural_language_context": {...}
}
}
}
Sent when Scout commits to this Beacon’s offer:
{
"event_type": "offer_accepted",
"payload": {
"offer_id": "ofr_01HABC...",
"session_id": "ses_01HXYZ...",
"transaction_id": "txn_01HXYZ...",
"quantity": 1,
"buyer_identity": {
"name": "Jane Doe",
"email": "jane.doe@example.com"
},
"shipping_address": {...},
"payment_pending": true
}
}
The webhook mechanism is designed to support future proactive Beacon behaviors:
These extensions will be defined in future protocol versions.
AURA ranks offers using CWR, which balances base reputation with Scout-specific compatibility, adjusted by clearinghouse risk assessment (Phase 7):
CWR = ((Base_Reputation × 0.6) + (Compatibility_Score × 0.4)) × Risk_Adjustment
Where:
Base_Reputation (0-100):
Compatibility_Score (0-100):
Compatibility_Score = (Structured_Match × 0.5) + (Semantic_Similarity × 0.5)
Structured_Match: How well the offer’s structured attributes match Scout’s requirements Semantic_Similarity: LLM-computed similarity between Scout’s context and offer description
Risk_Adjustment (0.0–1.0) — Phase 7:
The risk adjustment factor penalizes offers from Beacons with elevated clearing risk. It is computed from the Beacon’s bilateral risk profile (Section 10.7.1) and ensures that risk costs are reflected in ranking, not just in margin:
Risk_Adjustment = 1.0 - (Beacon_Risk_Score × Risk_Weight)
Where:
Beacon_Risk_Score (0.0–1.0) — the seller-side risk component from the clearinghouse risk engine (dispute rate, fulfillment reliability, time-in-network)Risk_Weight — configurable parameter (default: 0.3). Bounds: [0.1, 0.5]. Published in operational documentation per the hybrid approach (Section 10.7.1).A Beacon with a perfect risk score (0.0) receives Risk_Adjustment = 1.0 (no penalty). A Beacon at the maximum risk score (1.0) with default weight receives Risk_Adjustment = 0.7 (30% CWR reduction).
Pre-Phase 7 behavior: When clearinghouse risk assessment is not active, Risk_Adjustment = 1.0 (identity multiplier). The formula degrades gracefully to the original CWR calculation.
Before CWR ranking, offers that fail either the Beacon’s business rules (Section 3.1.5) or the Scout’s acceptance criteria are excluded from the ranked set. These offers are not ranked lower — they are removed entirely.
Excluded offers are available via a separate query parameter:
GET /v1/sessions/{session_id}/offers?include_excluded=true
Excluded offers include a structured exclusion_reason:
{
"offer_id": "ofr_01HABC...",
"excluded": true,
"exclusion_reason": {
"code": "BUSINESS_RULE_VIOLATION",
"rule_type": "min_trust_level",
"rejected_by": "beacon",
"message": "Beacon requires entity_verified for transactions over $1,000"
}
}
Scout seeking: wireless headphones for train commute, Sony preference, $300-400
Beacon A Offer: Sony WH-1000XM5, $349.99, Base_Reputation: 87
Structured_Match: 95% (all features, right price range, preferred brand)
Semantic_Similarity: 92% (commute-focused description, noise emphasis)
Compatibility_Score: (0.95 × 0.5) + (0.92 × 0.5) = 93.5
Beacon_Risk_Score: 0.10 (low risk — established Beacon, low dispute rate)
Risk_Adjustment: 1.0 - (0.10 × 0.3) = 0.97
CWR = ((87 × 0.6) + (93.5 × 0.4)) × 0.97 = 89.6 × 0.97 = 86.9
Beacon B Offer: Bose QuietComfort, $299.99, Base_Reputation: 92
Structured_Match: 80% (all features, good price, acceptable brand)
Semantic_Similarity: 78% (general description, less commute-specific)
Compatibility_Score: (0.80 × 0.5) + (0.78 × 0.5) = 79.0
Beacon_Risk_Score: 0.05 (very low risk — long history, near-zero disputes)
Risk_Adjustment: 1.0 - (0.05 × 0.3) = 0.985
CWR = ((92 × 0.6) + (79 × 0.4)) × 0.985 = 86.8 × 0.985 = 85.5
Beacon C Offer: Audio-Technica ATH-M50x, $299.99, Base_Reputation: 78
Structured_Match: 70% (some features, acceptable price, non-preferred brand)
Semantic_Similarity: 65% (studio-focused, less commute relevance)
Compatibility_Score: (0.70 × 0.5) + (0.65 × 0.5) = 67.5
Beacon_Risk_Score: 0.45 (elevated — new Beacon, limited history, recent dispute)
Risk_Adjustment: 1.0 - (0.45 × 0.3) = 0.865
CWR = ((78 × 0.6) + (67.5 × 0.4)) × 0.865 = 73.8 × 0.865 = 63.8
Result: Beacon A ranked highest. Beacon C's elevated risk score compounds its
lower compatibility, pushing it further down. Risk adjustment prevents high-risk
Beacons from competing on reputation alone.
Scout retrieves ranked offers:
GET /v1/sessions/{session_id}/offers
Response (200 OK):
{
"session_id": "ses_01HXYZ...",
"status": "offers_ready",
"total_offers": 8,
"offers": [
{
"rank": 1,
"offer_id": "ofr_01HABC...",
"cwr_score": 86.9,
"cwr_components": {
"base_reputation": 87,
"compatibility_score": 93.5,
"risk_adjustment": 0.97,
"beacon_risk_score": 0.10
},
"beacon_id": "bcn_01HXYZ...",
"product": {
"name": "Sony WH-1000XM5",
"category": "electronics.headphones.over_ear"
},
"pricing": {
"currency": "USD",
"offer_price": 349.99,
"list_price": 399.99
},
"availability": {
"in_stock": true,
"delivery_estimate_days": {"min": 2, "max": 5}
},
"merchant": {
"name": "Acme Electronics",
"reputation_score": 87
},
"match_explanation": {
"summary": "Top match: preferred brand Sony, excellent noise cancellation, within budget, commuter-friendly features",
"structured_match_score": 95,
"semantic_similarity_score": 92
},
"detail_url": "/v1/offers/ofr_01HABC..."
},
{
"rank": 2,
"offer_id": "ofr_01HDEF...",
"cwr_score": 86.8,
"beacon_id": "bcn_02HXYZ...",
"product": {
"name": "Bose QuietComfort Ultra",
"category": "electronics.headphones.over_ear"
},
"pricing": {
"currency": "USD",
"offer_price": 299.99,
"list_price": 379.99
},
"match_explanation": {
"summary": "Strong alternative: excellent noise cancellation, better price point, highly-rated merchant",
"structured_match_score": 80,
"semantic_similarity_score": 78
},
"detail_url": "/v1/offers/ofr_01HDEF..."
}
],
"ranking_metadata": {
"algorithm_version": "cwr_v2",
"computed_at": "2026-01-14T10:00:35Z"
}
}
Scout can retrieve full offer details:
GET /v1/offers/{offer_id}
Returns the complete Offer object (see Section 4.4).