observing-atproto

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Observing ATProtocol

ATProtocol网络观测

Firehose Access

Firehose接入

Jetstream endpoint:
wss://jetstream2.us-east.bsky.network/subscribe
Simplified JSON stream (~50 posts/sec on Bluesky). Easier than raw CAR files.
Jetstream端点
wss://jetstream2.us-east.bsky.network/subscribe
简化的JSON流(Bluesky平台约50条帖子/秒)。比原始CAR文件更易用。

Quick Pulse

快速脉冲采集

python
import asyncio
import json
import websockets
from datetime import datetime, timezone

async def pulse(duration_seconds=15):
    uri = 'wss://jetstream2.us-east.bsky.network/subscribe'
    posts, likes, follows = 0, 0, 0
    hashtags = {}
    
    start = datetime.now(timezone.utc)
    
    async with websockets.connect(uri) as ws:
        while (datetime.now(timezone.utc) - start).seconds < duration_seconds:
            try:
                msg = await asyncio.wait_for(ws.recv(), timeout=1)
                data = json.loads(msg)
                
                commit = data.get('commit', {})
                collection = commit.get('collection', '')
                
                if collection == 'app.bsky.feed.post':
                    posts += 1
                    # Extract hashtags
                    text = commit.get('record', {}).get('text', '')
                    for word in text.split():
                        if word.startswith('#'):
                            tag = word[1:].lower().rstrip('.,!?')
                            hashtags[tag] = hashtags.get(tag, 0) + 1
                elif collection == 'app.bsky.feed.like':
                    likes += 1
                elif collection == 'app.bsky.graph.follow':
                    follows += 1
            except asyncio.TimeoutError:
                continue
    
    return {
        'duration': duration_seconds,
        'posts': posts,
        'likes': likes,
        'follows': follows,
        'posts_per_min': posts * 60 // duration_seconds,
        'top_hashtags': sorted(hashtags.items(), key=lambda x: -x[1])[:5]
    }
python
import asyncio
import json
import websockets
from datetime import datetime, timezone

async def pulse(duration_seconds=15):
    uri = 'wss://jetstream2.us-east.bsky.network/subscribe'
    posts, likes, follows = 0, 0, 0
    hashtags = {}
    
    start = datetime.now(timezone.utc)
    
    async with websockets.connect(uri) as ws:
        while (datetime.now(timezone.utc) - start).seconds < duration_seconds:
            try:
                msg = await asyncio.wait_for(ws.recv(), timeout=1)
                data = json.loads(msg)
                
                commit = data.get('commit', {})
                collection = commit.get('collection', '')
                
                if collection == 'app.bsky.feed.post':
                    posts += 1
                    # Extract hashtags
                    text = commit.get('record', {}).get('text', '')
                    for word in text.split():
                        if word.startswith('#'):
                            tag = word[1:].lower().rstrip('.,!?')
                            hashtags[tag] = hashtags.get(tag, 0) + 1
                elif collection == 'app.bsky.feed.like':
                    likes += 1
                elif collection == 'app.bsky.graph.follow':
                    follows += 1
            except asyncio.TimeoutError:
                continue
    
    return {
        'duration': duration_seconds,
        'posts': posts,
        'likes': likes,
        'follows': follows,
        'posts_per_min': posts * 60 // duration_seconds,
        'top_hashtags': sorted(hashtags.items(), key=lambda x: -x[1])[:5]
    }

Using tools/firehose.py

使用tools/firehose.py

bash
undefined
bash
undefined

Quick network sample

Quick network sample

uv run python -m tools.firehose sample 30
uv run python -m tools.firehose sample 30

Network analysis

Network analysis

uv run python -m tools.firehose analyze 60
undefined
uv run python -m tools.firehose analyze 60
undefined

Monitoring Feeds

信息流监控

The Atmosphere Feed

Atmosphere信息流

Cameron's curated ATProtocol discussion feed:
python
feed_uri = 'at://did:plc:gfrmhdmjvxn2sjedzboeudef/app.bsky.feed.generator/the-atmosphere'

async with httpx.AsyncClient() as client:
    resp = await client.get(
        'https://public.api.bsky.app/xrpc/app.bsky.feed.getFeed',
        params={'feed': feed_uri, 'limit': 20}
    )
    posts = resp.json().get('feed', [])
Cameron策划的ATProtocol讨论信息流:
python
feed_uri = 'at://did:plc:gfrmhdmjvxn2sjedzboeudef/app.bsky.feed.generator/the-atmosphere'

async with httpx.AsyncClient() as client:
    resp = await client.get(
        'https://public.api.bsky.app/xrpc/app.bsky.feed.getFeed',
        params={'feed': feed_uri, 'limit': 20}
    )
    posts = resp.json().get('feed', [])

Recording Observations

记录观测结果

bash
undefined
bash
undefined

Record observation as a cognition thought

Record observation as a cognition thought

uv run python -m tools.cognition thought "Network pulse: {posts_per_min} posts/min, {likes_per_min} likes/min. Top tags: #atproto, #bluesky"
undefined
uv run python -m tools.cognition thought "Network pulse: {posts_per_min} posts/min, {likes_per_min} likes/min. Top tags: #atproto, #bluesky"
undefined

Network Statistics (typical)

典型网络统计数据

  • ~50 posts/sec (~3000/min)
  • ~250 events/sec total
  • ~65% of events are likes
  • Engagement ratio (likes:posts) typically 4-6:1
  • Higher engagement ratio = healthy interaction patterns
  • ~50条帖子/秒(约3000条/分钟)
  • 总计~250个事件/秒
  • 约65%的事件为点赞
  • 互动率(点赞数:帖子数)通常为4-6:1
  • 互动率越高,代表互动模式越健康

Best Practices

最佳实践

  1. Sample for at least 15 seconds for meaningful data
  2. Note time of day - activity varies
  3. Cultural events drive spikes (e.g., BBB26, sports)
  4. Record observations as
    network.comind.observation
    records
  5. Compare pulses over time to identify patterns
  1. 采样时间至少15秒以获取有意义的数据
  2. 记录采样时间——活跃度随时段变化
  3. 文化活动会引发流量峰值(如BBB26、体育赛事)
  4. 将观测结果记录为
    network.comind.observation
    记录
  5. 对比不同时段的脉冲数据以识别模式