Loading...
Loading...
Install and use World2Agent (W2A) sensors to give AI agents structured, real-time perception of the real world
npx skill4agent add aradotso/ai-agent-skills world2agent-protocolSkill by ara.so — AI Agent Skills collection.
/plugin marketplace add machinepulse-ai/world2agent-plugins
/plugin install world2agent@world2agent-plugins
/reload-plugins/world2agent:sensor-add @world2agent/sensor-hackernewsclaude --dangerously-load-development-channels plugin:world2agent@world2agent-pluginsnpm install -g @world2agent/hermes-sensor-bridge
hermes skills install machinepulse-ai/world2agent-plugins/hermes-sensor-bridge/skills/world2agent-manage/world2agent-manage add @world2agent/sensor-hackernewsnpm install -g @world2agent/openclaw-sensor-bridge
openclaw skills install world2agent-manageUse world2agent-manage skill install @quill-io/sensor-frontier-ai-newsnpm install @world2agent/core
npm install @world2agent/sensor-hackernews{
"signal_id": "uuid-v4",
"sensor_id": "@world2agent/sensor-hackernews",
"timestamp": "2026-05-17T10:30:00Z",
"type": "news.hackernews.story",
"priority": "medium",
"data": {
"title": "Show HN: World2Agent Protocol",
"url": "https://news.ycombinator.com/item?id=123456",
"score": 340,
"author": "machinepulse"
},
"metadata": {
"ttl": 3600,
"schema_version": "1.0"
}
}signal_idsensor_idtypeprioritycriticalhighmediumlowdatametadata.ttlimport { W2AClient } from '@world2agent/core';
import HackerNewsSensor from '@world2agent/sensor-hackernews';
const client = new W2AClient();
// Register sensor
await client.registerSensor(new HackerNewsSensor({
minScore: 100,
keywords: ['AI', 'agents', 'protocol']
}));
// Listen for signals
client.on('signal', (signal) => {
console.log(`[${signal.priority}] ${signal.type}`);
console.log(signal.data);
// Your agent logic here
if (signal.priority === 'high') {
handleUrgentSignal(signal);
}
});
// Start receiving signals
await client.start();import { W2AClient, SignalFilter } from '@world2agent/core';
const client = new W2AClient();
// Filter by type pattern
const newsFilter = new SignalFilter({
typePattern: /^news\./,
minPriority: 'medium'
});
client.on('signal', newsFilter.apply((signal) => {
// Only news signals with medium+ priority
processNewsSignal(signal);
}));import { W2AClient } from '@world2agent/core';
import HackerNewsSensor from '@world2agent/sensor-hackernews';
import FrontierAISensor from '@quill-io/sensor-frontier-ai-news';
import WeatherSensor from '@world2agent/sensor-weather';
const client = new W2AClient();
// Register multiple sensors
await client.registerSensor(new HackerNewsSensor({ minScore: 200 }));
await client.registerSensor(new FrontierAISensor({ labs: ['openai', 'anthropic'] }));
await client.registerSensor(new WeatherSensor({
location: 'San Francisco',
alerts: true
}));
// Route by type
client.on('signal', (signal) => {
if (signal.type.startsWith('news.')) {
routeToNewsHandler(signal);
} else if (signal.type.startsWith('weather.')) {
routeToWeatherHandler(signal);
}
});
await client.start();// my-sensor/src/index.ts
import { BaseSensor, Signal } from '@world2agent/core';
export default class MySensor extends BaseSensor {
constructor(config: { apiKey?: string } = {}) {
super({
id: '@myorg/sensor-example',
name: 'Example Sensor',
version: '1.0.0'
});
this.apiKey = config.apiKey || process.env.EXAMPLE_API_KEY;
}
async start() {
// Poll every 60 seconds
this.interval = setInterval(() => this.poll(), 60000);
await this.poll();
}
async stop() {
if (this.interval) clearInterval(this.interval);
}
private async poll() {
const data = await this.fetchData();
for (const item of data) {
const signal: Signal = {
signal_id: crypto.randomUUID(),
sensor_id: this.config.id,
timestamp: new Date().toISOString(),
type: 'example.data.update',
priority: item.urgent ? 'high' : 'medium',
data: {
title: item.title,
value: item.value
},
metadata: {
ttl: 3600,
schema_version: '1.0'
}
};
this.emit(signal);
}
}
private async fetchData() {
const response = await fetch('https://api.example.com/data', {
headers: { 'Authorization': `Bearer ${this.apiKey}` }
});
return response.json();
}
}{
"name": "@myorg/sensor-example",
"version": "1.0.0",
"description": "W2A sensor for Example API",
"keywords": ["w2a-sensor", "world2agent", "example"],
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"build": "tsc",
"prepublishOnly": "npm run build"
},
"dependencies": {
"@world2agent/core": "^1.0.0"
},
"devDependencies": {
"typescript": "^5.0.0"
}
}# Setup Questions
## API Key
**prompt:** What is your Example API key?
**env:** EXAMPLE_API_KEY
**required:** true
## Update Interval
**prompt:** Poll interval in seconds (default: 60)?
**env:** EXAMPLE_POLL_INTERVAL
**default:** 60# .env
EXAMPLE_API_KEY=sk-xxxxxxxxxxxx
HACKERNEWS_MIN_SCORE=150
WEATHER_LOCATION=Londonimport { W2AClient } from '@world2agent/core';
import { config } from 'dotenv';
config(); // Load .env
const client = new W2AClient();
await client.registerSensor(new HackerNewsSensor({
minScore: parseInt(process.env.HACKERNEWS_MIN_SCORE || '100')
}));import { W2AClient } from '@world2agent/core';
const client = new W2AClient({
maxSignalsPerSecond: 10,
deduplication: true,
persistSignals: './signals.log'
});
// Update sensor config at runtime
await client.updateSensorConfig('@world2agent/sensor-hackernews', {
minScore: 250,
keywords: ['AI', 'machine learning']
});import { W2AClient, Deduplicator } from '@world2agent/core';
const client = new W2AClient();
const dedup = new Deduplicator({ windowMs: 60000 }); // 1 minute window
client.on('signal', (signal) => {
if (dedup.isNew(signal.signal_id)) {
processSignal(signal);
}
});client.on('signal', async (signal) => {
switch (signal.priority) {
case 'critical':
await notifyPagerDuty(signal);
await handleImmediate(signal);
break;
case 'high':
await queueForProcessing(signal);
break;
default:
await logSignal(signal);
}
});import express from 'express';
import { W2AClient } from '@world2agent/core';
const app = express();
const client = new W2AClient();
app.post('/webhook/w2a', express.json(), (req, res) => {
const signal = req.body;
// Validate signature
if (!client.validateSignature(signal, req.headers['x-w2a-signature'])) {
return res.status(401).send('Invalid signature');
}
// Process signal
client.ingestSignal(signal);
res.status(200).send('OK');
});
app.listen(3000);import fs from 'fs/promises';
import { W2AClient } from '@world2agent/core';
const client = new W2AClient();
const logPath = './signals.jsonl';
client.on('signal', async (signal) => {
// Append to newline-delimited JSON log
await fs.appendFile(logPath, JSON.stringify(signal) + '\n');
// Your processing logic
await processSignal(signal);
});npm search w2a-sensor@world2agent/sensor-hackernews@quill-io/sensor-frontier-ai-news@world2agent/sensor-weather@world2agent/sensor-github@world2agent/sensor-redditconst status = client.getSensorStatus('@world2agent/sensor-hackernews');
console.log(status); // { running: true, lastSignal: '2026-05-17T10:30:00Z' }const client = new W2AClient({ logLevel: 'debug' });await client.start(); // Starts all registered sensorsconst client = new W2AClient({ deduplication: true });const seen = new Set<string>();
client.on('signal', (signal) => {
if (seen.has(signal.signal_id)) return;
seen.add(signal.signal_id);
processSignal(signal);
});import pThrottle from 'p-throttle';
const throttle = pThrottle({ limit: 5, interval: 1000 }); // 5/sec
const throttledProcess = throttle(async (signal) => {
await processSignal(signal);
});
client.on('signal', throttledProcess);try {
await client.registerSensor(new MySensor({ apiKey: process.env.API_KEY }));
} catch (error) {
console.error('Sensor registration failed:', error);
// Fall back or retry
}
client.on('sensor-error', (sensorId, error) => {
console.error(`Sensor ${sensorId} error:`, error);
// Implement restart logic
});const requiredEnv = ['EXAMPLE_API_KEY', 'HACKERNEWS_MIN_SCORE'];
for (const key of requiredEnv) {
if (!process.env[key]) {
throw new Error(`Missing required environment variable: ${key}`);
}
}import { W2AGraph } from '@world2agent/graph';
const graph = new W2AGraph();
// Merge HN and Reddit signals about the same topic
graph.addRule({
inputs: ['news.hackernews.*', 'news.reddit.*'],
merge: (signals) => ({
type: 'news.aggregated.topic',
data: {
sources: signals.map(s => s.sensor_id),
combined_score: signals.reduce((sum, s) => sum + s.data.score, 0)
}
}),
window: 300 // 5 minutes
});
graph.on('enriched-signal', (signal) => {
// Receives merged signals
});