Version: 1.1 Date: April 14, 2026 Protocol: v2.2
Welcome to AURA! This tutorial will guide you through creating and running your first Beacon—an intelligent selling agent that responds to purchase intents from Scout buyers. By the end, you’ll have a working Beacon that can register with AURA Core, listen for buyer sessions, and submit competitive offers in real-time.
Estimated Time: ~15 minutes
In the AURA ecosystem, a Beacon is a selling agent that represents your business. When a Scout (a buyer’s agent) searches for products or services, your Beacon can respond with offers. Think of it as your automated sales representative that:
Beacons are the foundation of the AURA marketplace—they’re how suppliers connect with buyers at scale.
Create a new directory for your Beacon and initialize Node.js:
mkdir my-first-beacon
cd my-first-beacon
npm init -y
npm install @aura-labs-ai/beacon
Create a new file called beacon.js:
import { createBeacon } from '@aura-labs-ai/beacon';
const beacon = createBeacon({
externalId: 'acme-widgets-001',
name: 'ACME Widget Co.',
description: 'Premium industrial widgets and components',
capabilities: {
products: ['industrial-widgets', 'components'],
maxOrder: 10000,
deliveryDays: 3
},
metadata: {
rating: 4.8,
reviewCount: 247,
certifications: ['ISO-9001', 'ISO-14001']
}
});
console.log('Beacon created:', beacon.name);
This configuration tells AURA about your business:
After creating your Beacon, register it with AURA Core:
const registered = await beacon.register();
console.log('Registration successful!');
console.log('Beacon ID:', registered.beaconId);
console.log('Status:', registered.status);
Registration returns:
beaconId: Your unique identifier in AURA (used for all transactions)externalId: Your original IDname: Your registered namestatus: Typically “active” after successful registrationSessions are purchase opportunities. When a Scout finds a matching buyer, it creates a session and sends it to your Beacon:
beacon.onSession(async (session) => {
console.log('New session received!');
console.log('Intent:', session.intent.raw);
console.log('Region:', session.region);
console.log('Session ID:', session.sessionId);
});
The session.intent.raw contains the buyer’s natural language request—e.g., “I need 500 industrial widgets for automotive manufacturing.”
When you receive a session, use interpretIntent() to match the buyer’s intent against your product catalog and submit an offer:
// Define your product catalog
const catalog = [
{
name: 'Industrial Widget Pro',
sku: 'WDG-500-PRO',
category: 'industrial-components',
tags: ['widget', 'industrial', 'precision'],
price: 85.00
},
{
name: 'Standard Widget',
sku: 'WDG-100-STD',
category: 'industrial-components',
tags: ['widget', 'standard', 'bulk'],
price: 45.00
}
];
beacon.onSession(async (session) => {
// Use NLP-powered catalog matching instead of simple string matching
const result = await beacon.interpretIntent(session.intent.raw, catalog);
if (result.matches.length > 0) {
const topMatch = result.matches[0];
const offer = {
product: {
name: topMatch.item.name,
sku: topMatch.item.sku,
description: 'High-precision industrial widget, 500-pack',
category: topMatch.item.category
},
unitPrice: topMatch.item.price,
quantity: 500,
currency: 'USD',
deliveryDate: '2026-03-10',
terms: {
warranty: '12-month manufacturer warranty',
returnPolicy: '30-day full refund guarantee'
}
};
try {
await beacon.submitOffer(session.sessionId, offer);
console.log('Offer submitted successfully!');
console.log(` Matched: ${topMatch.item.name} (score: ${topMatch.score})`);
console.log(` Confidence: ${result.confidence}`);
} catch (error) {
console.error('Failed to submit offer:', error.message);
}
}
});
Begin polling AURA Core for new sessions. Polling checks periodically (default: every 5 seconds) for incoming opportunities:
await beacon.startPolling();
console.log('Beacon is now listening for opportunities!');
The Beacon will now:
onSession handler when sessions arrivebeacon.stopPolling()Here’s how a transaction flows through AURA:
┌──────────────┐
│ Scout Intent │ "I need 500 widgets"
└──────┬───────┘
│
▼
┌──────────────────┐
│ Session Created │ Scout creates session, routes to Beacons
└──────┬───────────┘
│
▼
┌──────────────────┐
│ Beacon Polls │ Your beacon checks for new sessions
└──────┬───────────┘
│
▼
┌──────────────────┐
│ Offer Submitted │ Your beacon evaluates & submits offer
└──────┬───────────┘
│
▼
┌──────────────────┐
│ Scout Evaluates │ Scout compares offers from all Beacons
└──────┬───────────┘
│
▼
┌──────────────────┐
│ Transaction │ Winner is selected, order confirmed
└──────────────────┘
Here’s a complete, runnable Beacon that you can start with:
import { createBeacon } from '@aura-labs-ai/beacon';
// Define your product catalog
const catalog = [
{ name: 'Industrial Widget Pro', sku: 'WDG-500-PRO', category: 'widgets', tags: ['industrial', 'precision'], price: 85.00 },
{ name: 'Standard Widget', sku: 'WDG-100-STD', category: 'widgets', tags: ['standard', 'bulk'], price: 45.00 },
{ name: 'Micro Widget', sku: 'WDG-010-MIC', category: 'widgets', tags: ['micro', 'electronics'], price: 12.00 },
];
const beacon = createBeacon({
externalId: 'acme-widgets-001',
name: 'ACME Widget Co.',
description: 'Premium industrial widgets and components',
capabilities: {
products: ['industrial-widgets', 'components'],
maxOrder: 10000,
deliveryDays: 3
},
metadata: {
rating: 4.8,
reviewCount: 247,
certifications: ['ISO-9001', 'ISO-14001']
}
});
// Register with AURA Core
console.log('Registering Beacon...');
const registered = await beacon.register();
console.log(`Registered as "${registered.name}" (ID: ${registered.beaconId})`);
// Listen for buyer sessions
beacon.onSession(async (session) => {
console.log(`\nNew session from Scout!`);
console.log(` Intent: "${session.intent.raw}"`);
// Use NLP-powered catalog matching
const result = await beacon.interpretIntent(session.intent.raw, catalog);
if (result.matches.length > 0) {
const topMatch = result.matches[0];
console.log(` Matched: ${topMatch.item.name} (score: ${topMatch.score})`);
const offer = {
product: {
name: topMatch.item.name,
sku: topMatch.item.sku,
description: `${topMatch.item.name} — matched via NLP`,
category: topMatch.item.category
},
unitPrice: topMatch.item.price,
quantity: 500,
currency: 'USD',
deliveryDate: '2026-03-10',
terms: {
warranty: '12-month manufacturer warranty',
returnPolicy: '30-day full refund guarantee'
}
};
try {
await beacon.submitOffer(session.sessionId, offer);
console.log(` Offer submitted: 500 units @ $${topMatch.item.price} each`);
} catch (error) {
console.error(` Failed to submit offer: ${error.message}`);
}
} else {
console.log(` No catalog match — skipping session`);
}
});
// Handle accepted offers
beacon.onOfferAccepted((transaction) => {
console.log(`\nOffer accepted!`);
console.log(` Transaction ID: ${transaction.transactionId}`);
});
// Start listening for opportunities
console.log('Starting to listen for opportunities...');
await beacon.startPolling();
console.log('Beacon is ready! Listening for buyer intents...\n');
// Keep the process running
process.on('SIGINT', () => {
console.log('\nShutting down Beacon...');
beacon.stopPolling();
process.exit(0);
});
To run this example:
node beacon.js
Your Beacon will now register and start listening for opportunities. When a Scout sends a matching session, your Beacon will submit an offer.
beacon.onSession(async (session) => {
// Use NLP-powered catalog matching for accurate results
const result = await beacon.interpretIntent(session.intent.raw, catalog);
if (result.matches.length > 0 && result.matches[0].score > 20) {
await beacon.submitOffer(session.sessionId, buildOffer(result.matches[0]));
}
});
// Bad: Submitting offers you can't fulfill
beacon.onSession(async (session) => {
await beacon.submitOffer(session.sessionId, offer); // Always submit!
});
const beacon = createBeacon({
externalId: 'acme-widgets-001', // Include company + instance ID
// ...
});
// Bad: Configuration is hardcoded
const beacon = createBeacon({
externalId: 'beacon-123',
// ...
});
try {
await beacon.submitOffer(session.sessionId, offer);
} catch (error) {
console.error('Failed to submit offer:', error.message);
// Log error, alert team, or retry later
}
// Bad: Silent failures
await beacon.submitOffer(session.sessionId, offer);
Solution: Ensure externalId is a non-empty string and unique to your Beacon. Try including your company name and an instance identifier.
externalId: 'my-company-beacon-001'
Solution:
externalId hasn’t changed (it must be consistent)metadata to ensure it shows credibilitySolution: Always call beacon.register() and wait for it to complete before calling other methods:
const registered = await beacon.register();
// Now safe to use other methods
await beacon.startPolling();
Solution: AURA Core is at https://aura-labsai-production.up.railway.app. Verify:
Solution: Ensure your handler is registered before calling startPolling():
beacon.onSession(async (session) => { /* ... */ }); // Register first
await beacon.startPolling(); // Then start polling
You now have a working Beacon! Here’s what to learn next:
We’re here to help! Reach out to hello@aura-labs.ai with questions, feedback, or feature requests.
Happy selling! 🚀