world2agent-protocol

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

World2Agent Protocol Skill

World2Agent 协议 Skill

Skill by ara.so — AI Agent Skills collection.
ara.so提供的Skill — AI Agent技能合集。

What is World2Agent?

什么是World2Agent?

World2Agent (W2A) is an open protocol that standardizes how AI agents perceive the real world. Sensors watch data sources (news feeds, production alerts, market data, etc.) and emit structured signals following the W2A schema. Your agent receives these signals and decides what to do.
Architecture: World → Sensor → Agent
  • Sensors are npm packages that watch external data sources
  • Signals are structured JSON events following the W2A protocol
  • Agents consume signals via runtime plugins or direct SDK integration
World2Agent(W2A)是一个开放协议,用于规范AI Agent如何感知现实世界。传感器会监控数据源(新闻推送、生产警报、市场数据等),并遵循W2A schema生成结构化信号。你的Agent接收这些信号后,再决定后续操作。
架构: 现实世界 → 传感器 → Agent
  • 传感器是监控外部数据源的npm包
  • 信号是遵循W2A协议的结构化JSON事件
  • Agent通过运行时插件或直接SDK集成来消费信号

Installation

安装

For Claude Code

适用于Claude Code

bash
/plugin marketplace add machinepulse-ai/world2agent-plugins
/plugin install world2agent@world2agent-plugins
/reload-plugins
Add a sensor:
bash
/world2agent:sensor-add @world2agent/sensor-hackernews
Restart with plugin channel:
bash
claude --dangerously-load-development-channels plugin:world2agent@world2agent-plugins
bash
/plugin marketplace add machinepulse-ai/world2agent-plugins
/plugin install world2agent@world2agent-plugins
/reload-plugins
添加传感器:
bash
/world2agent:sensor-add @world2agent/sensor-hackernews
通过插件通道重启:
bash
claude --dangerously-load-development-channels plugin:world2agent@world2agent-plugins

For Hermes

适用于Hermes

bash
npm install -g @world2agent/hermes-sensor-bridge
hermes skills install machinepulse-ai/world2agent-plugins/hermes-sensor-bridge/skills/world2agent-manage
In Hermes session:
bash
/world2agent-manage add @world2agent/sensor-hackernews
bash
npm install -g @world2agent/hermes-sensor-bridge
hermes skills install machinepulse-ai/world2agent-plugins/hermes-sensor-bridge/skills/world2agent-manage
在Hermes会话中:
bash
/world2agent-manage add @world2agent/sensor-hackernews

For OpenClaw

适用于OpenClaw

bash
npm install -g @world2agent/openclaw-sensor-bridge
openclaw skills install world2agent-manage
Then in chat:
Use world2agent-manage skill install @quill-io/sensor-frontier-ai-news
bash
npm install -g @world2agent/openclaw-sensor-bridge
openclaw skills install world2agent-manage
然后在聊天中:
Use world2agent-manage skill install @quill-io/sensor-frontier-ai-news

Direct SDK Integration (TypeScript/Node.js)

直接SDK集成(TypeScript/Node.js)

bash
npm install @world2agent/core
npm install @world2agent/sensor-hackernews
bash
npm install @world2agent/core
npm install @world2agent/sensor-hackernews

Core Concepts

核心概念

Signal Format

信号格式

Every W2A signal follows this schema:
typescript
{
  "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"
  }
}
每个W2A信号都遵循以下schema:
typescript
{
  "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"
  }
}

Key Fields

关键字段

  • signal_id
    : Unique identifier for deduplication
  • sensor_id
    : npm package name of the sensor
  • type
    : Hierarchical type (category.source.event)
  • priority
    :
    critical
    |
    high
    |
    medium
    |
    low
  • data
    : Sensor-specific payload
  • metadata.ttl
    : Signal lifetime in seconds
  • signal_id
    : 用于去重的唯一标识符
  • sensor_id
    : 传感器的npm包名称
  • type
    : 层级类型(分类.来源.事件)
  • priority
    :
    critical
    |
    high
    |
    medium
    |
    low
  • data
    : 传感器特定的负载数据
  • metadata.ttl
    : 信号的生命周期(秒)

Using the SDK

使用SDK

Basic Signal Consumption

基础信号消费

typescript
import { 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();
typescript
import { W2AClient } from '@world2agent/core';
import HackerNewsSensor from '@world2agent/sensor-hackernews';

const client = new W2AClient();

// 注册传感器
await client.registerSensor(new HackerNewsSensor({
  minScore: 100,
  keywords: ['AI', 'agents', 'protocol']
}));

// 监听信号
client.on('signal', (signal) => {
  console.log(`[${signal.priority}] ${signal.type}`);
  console.log(signal.data);
  
  // 此处添加你的Agent逻辑
  if (signal.priority === 'high') {
    handleUrgentSignal(signal);
  }
});

// 开始接收信号
await client.start();

Signal Filtering

信号过滤

typescript
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);
}));
typescript
import { W2AClient, SignalFilter } from '@world2agent/core';

const client = new W2AClient();

// 按类型模式过滤
const newsFilter = new SignalFilter({
  typePattern: /^news\./,
  minPriority: 'medium'
});

client.on('signal', newsFilter.apply((signal) => {
  // 仅处理中等及以上优先级的新闻信号
  processNewsSignal(signal);
}));

Multi-Sensor Setup

多传感器配置

typescript
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();
typescript
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();

// 注册多个传感器
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 
}));

// 按类型路由
client.on('signal', (signal) => {
  if (signal.type.startsWith('news.')) {
    routeToNewsHandler(signal);
  } else if (signal.type.startsWith('weather.')) {
    routeToWeatherHandler(signal);
  }
});

await client.start();

Building a Custom Sensor

构建自定义传感器

Minimal Sensor Structure

最小传感器结构

typescript
// 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();
  }
}
typescript
// 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() {
    // 每60秒轮询一次
    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();
  }
}

Package.json for Sensors

传感器的Package.json

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"
  }
}
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.md for Interactive Configuration

用于交互式配置的SETUP.md

markdown
undefined
markdown
undefined

Setup Questions

设置问题

API Key

API密钥

prompt: What is your Example API key? env: EXAMPLE_API_KEY required: true
提示: 你的Example API密钥是什么? 环境变量: EXAMPLE_API_KEY 必填: true

Update Interval

更新间隔

prompt: Poll interval in seconds (default: 60)? env: EXAMPLE_POLL_INTERVAL default: 60
undefined
提示: 轮询间隔(秒,默认值:60)? 环境变量: EXAMPLE_POLL_INTERVAL 默认值: 60
undefined

Configuration Patterns

配置模式

Environment Variables

环境变量

bash
undefined
bash
undefined

.env

.env

EXAMPLE_API_KEY=sk-xxxxxxxxxxxx HACKERNEWS_MIN_SCORE=150 WEATHER_LOCATION=London

```typescript
import { 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')
}));
EXAMPLE_API_KEY=sk-xxxxxxxxxxxx HACKERNEWS_MIN_SCORE=150 WEATHER_LOCATION=London

```typescript
import { W2AClient } from '@world2agent/core';
import { config } from 'dotenv';

config(); // 加载.env文件

const client = new W2AClient();

await client.registerSensor(new HackerNewsSensor({
  minScore: parseInt(process.env.HACKERNEWS_MIN_SCORE || '100')
}));

Runtime Configuration

运行时配置

typescript
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']
});
typescript
import { W2AClient } from '@world2agent/core';

const client = new W2AClient({
  maxSignalsPerSecond: 10,
  deduplication: true,
  persistSignals: './signals.log'
});

// 在运行时更新传感器配置
await client.updateSensorConfig('@world2agent/sensor-hackernews', {
  minScore: 250,
  keywords: ['AI', 'machine learning']
});

Common Patterns

常见模式

Signal Deduplication

信号去重

typescript
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);
  }
});
typescript
import { W2AClient, Deduplicator } from '@world2agent/core';

const client = new W2AClient();
const dedup = new Deduplicator({ windowMs: 60000 }); // 1分钟窗口

client.on('signal', (signal) => {
  if (dedup.isNew(signal.signal_id)) {
    processSignal(signal);
  }
});

Priority-Based Routing

基于优先级的路由

typescript
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);
  }
});
typescript
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);
  }
});

Webhook Integration

Webhook集成

typescript
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);
typescript
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;
  
  // 验证签名
  if (!client.validateSignature(signal, req.headers['x-w2a-signature'])) {
    return res.status(401).send('无效签名');
  }
  
  // 处理信号
  client.ingestSignal(signal);
  res.status(200).send('OK');
});

app.listen(3000);

Persistent Signal Log

持久化信号日志

typescript
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);
});
typescript
import fs from 'fs/promises';
import { W2AClient } from '@world2agent/core';

const client = new W2AClient();
const logPath = './signals.jsonl';

client.on('signal', async (signal) => {
  // 追加到换行分隔的JSON日志
  await fs.appendFile(logPath, JSON.stringify(signal) + '\n');
  
  // 你的处理逻辑
  await processSignal(signal);
});

Finding Sensors

查找传感器

Browse SensorHub

浏览SensorHub

Visit https://world2agent.ai/hub to browse the full catalog.
访问https://world2agent.ai/hub浏览完整的传感器目录。

CLI Search

CLI搜索

bash
npm search w2a-sensor
bash
npm search w2a-sensor

Popular Sensors

热门传感器

  • @world2agent/sensor-hackernews
    — Hacker News top stories
  • @quill-io/sensor-frontier-ai-news
    — AI lab announcements (OpenAI, Anthropic, etc.)
  • @world2agent/sensor-weather
    — Weather alerts and forecasts
  • @world2agent/sensor-github
    — Repository events and releases
  • @world2agent/sensor-reddit
    — Subreddit posts and trends
  • @world2agent/sensor-hackernews
    — Hacker News热门故事
  • @quill-io/sensor-frontier-ai-news
    — AI实验室公告(OpenAI、Anthropic等)
  • @world2agent/sensor-weather
    — 天气警报和预报
  • @world2agent/sensor-github
    — 仓库事件和版本发布
  • @world2agent/sensor-reddit
    — 子版块帖子和趋势

Troubleshooting

故障排除

Signals Not Flowing

信号无法传输

Check sensor status:
typescript
const status = client.getSensorStatus('@world2agent/sensor-hackernews');
console.log(status); // { running: true, lastSignal: '2026-05-17T10:30:00Z' }
Enable debug logging:
typescript
const client = new W2AClient({ logLevel: 'debug' });
Verify sensor is started:
typescript
await client.start(); // Starts all registered sensors
检查传感器状态:
typescript
const status = client.getSensorStatus('@world2agent/sensor-hackernews');
console.log(status); // { running: true, lastSignal: '2026-05-17T10:30:00Z' }
启用调试日志:
typescript
const client = new W2AClient({ logLevel: 'debug' });
验证传感器已启动:
typescript
await client.start(); // 启动所有已注册的传感器

Duplicate Signals

重复信号

Enable built-in deduplication:
typescript
const client = new W2AClient({ deduplication: true });
Or implement custom logic:
typescript
const seen = new Set<string>();

client.on('signal', (signal) => {
  if (seen.has(signal.signal_id)) return;
  seen.add(signal.signal_id);
  
  processSignal(signal);
});
启用内置去重功能:
typescript
const client = new W2AClient({ deduplication: true });
或实现自定义逻辑:
typescript
const seen = new Set<string>();

client.on('signal', (signal) => {
  if (seen.has(signal.signal_id)) return;
  seen.add(signal.signal_id);
  
  processSignal(signal);
});

Rate Limiting

速率限制

Throttle signal processing:
typescript
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);
限制信号处理速率:
typescript
import pThrottle from 'p-throttle';

const throttle = pThrottle({ limit: 5, interval: 1000 }); // 每秒5个

const throttledProcess = throttle(async (signal) => {
  await processSignal(signal);
});

client.on('signal', throttledProcess);

Sensor Crashes

传感器崩溃

Wrap sensor registration with error handling:
typescript
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
});
用错误处理包裹传感器注册:
typescript
try {
  await client.registerSensor(new MySensor({ apiKey: process.env.API_KEY }));
} catch (error) {
  console.error('传感器注册失败:', error);
  // 回退或重试
}

client.on('sensor-error', (sensorId, error) => {
  console.error(`传感器 ${sensorId} 错误:`, error);
  // 实现重启逻辑
});

Missing Environment Variables

缺少环境变量

Validate before sensor initialization:
typescript
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}`);
  }
}
在传感器初始化前验证:
typescript
const requiredEnv = ['EXAMPLE_API_KEY', 'HACKERNEWS_MIN_SCORE'];

for (const key of requiredEnv) {
  if (!process.env[key]) {
    throw new Error(`缺少必填环境变量: ${key}`);
  }
}

Advanced: Graph Layer (Experimental)

进阶:图层(实验性)

Compose and enrich signals from multiple sensors before they reach your agent:
typescript
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
});
See RFC for details.
在信号到达Agent之前,组合并丰富来自多个传感器的信号:
typescript
import { W2AGraph } from '@world2agent/graph';

const graph = new W2AGraph();

// 合并关于同一主题的HN和Reddit信号
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分钟
});

graph.on('enriched-signal', (signal) => {
  // 接收合并后的信号
});
详情请查看RFC

Resources

资源

License

许可证

Apache 2.0
Apache 2.0