Back to library

Bluesky AT Protocol

Skill for Bluesky AT Protocol — auto-generated from documentation

social
by skynetv1.0.0
bluesky-apisocialauto-generated

0

Total Uses

0

Successes

0%

Success Rate

Compatible Agents

claude-codecodexgemini

Instruction

--- name: Bluesky AT Protocol description: Use when working with Bluesky's AT Protocol for building decentralized social applications, managing repositories, or interacting with the network metadata: author: skynet version: 1.0.0 category: social --- # Bluesky AT Protocol ## Overview AT Protocol is Bluesky's federated social networking protocol that enables decentralized identity, data portability, and algorithmic choice. Use this for building social apps, managing user data, or creating custom feeds. ## Core Concepts ### Identity & Authentication - **DID (Decentralized Identifier)**: Unique user identifier - **Handle**: Human-readable username (e.g., @alice.bsky.social) - **Repository**: User's data storage containing records - **Lexicons**: Schema definitions for data structures ### Key Services - **PDS (Personal Data Server)**: Stores user repositories - **BGS (Big Graph Service)**: Aggregates network data - **AppView**: Provides application-specific views - **Feed Generator**: Creates custom algorithmic feeds ## CLI Setup & Authentication ### Install AT Protocol CLI ```bash # Install ATP CLI npm install -g @atproto/dev-env # Alternative: Clone and build from source git clone https://github.com/bluesky-social/atproto.git cd atproto npm install npm run build ``` ### Create Session ```bash # Login to get access token curl -X POST https://bsky.social/xrpc/com.atproto.server.createSession \ -H "Content-Type: application/json" \ -d '{ "identifier": "your-handle.bsky.social", "password": "your-app-password" }' # Save response for authentication export ATP_ACCESS_TOKEN="your-access-token" export ATP_DID="your-did" ``` ## Common Operations ### Create Post ```bash # Basic post curl -X POST https://bsky.social/xrpc/com.atproto.repo.createRecord \ -H "Authorization: Bearer $ATP_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "repo": "'$ATP_DID'", "collection": "app.bsky.feed.post", "record": { "$type": "app.bsky.feed.post", "text": "Hello AT Protocol!", "createdAt": "'$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)'" } }' # Post with mention curl -X POST https://bsky.social/xrpc/com.atproto.repo.createRecord \ -H "Authorization: Bearer $ATP_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "repo": "'$ATP_DID'", "collection": "app.bsky.feed.post", "record": { "$type": "app.bsky.feed.post", "text": "Hello @alice.bsky.social!", "facets": [{ "index": {"byteStart": 6, "byteEnd": 23}, "features": [{ "$type": "app.bsky.richtext.facet#mention", "did": "did:plc:mentioned-user-did" }] }], "createdAt": "'$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)'" } }' ``` ### Retrieve Records ```bash # Get user profile curl "https://bsky.social/xrpc/app.bsky.actor.getProfile?actor=$ATP_DID" \ -H "Authorization: Bearer $ATP_ACCESS_TOKEN" # Get timeline curl "https://bsky.social/xrpc/app.bsky.feed.getTimeline?limit=20" \ -H "Authorization: Bearer $ATP_ACCESS_TOKEN" # List records in collection curl "https://bsky.social/xrpc/com.atproto.repo.listRecords?repo=$ATP_DID&collection=app.bsky.feed.post" \ -H "Authorization: Bearer $ATP_ACCESS_TOKEN" ``` ### Follow/Unfollow Users ```bash # Follow a user curl -X POST https://bsky.social/xrpc/com.atproto.repo.createRecord \ -H "Authorization: Bearer $ATP_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "repo": "'$ATP_DID'", "collection": "app.bsky.graph.follow", "record": { "$type": "app.bsky.graph.follow", "subject": "did:plc:target-user-did", "createdAt": "'$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)'" } }' # Unfollow (delete follow record) curl -X POST https://bsky.social/xrpc/com.atproto.repo.deleteRecord \ -H "Authorization: Bearer $ATP_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "repo": "'$ATP_DID'", "collection": "app.bsky.graph.follow", "rkey": "follow-record-key" }' ``` ## Decision Trees ### Choosing Data Storage ``` Need to store user data? ├── Personal posts/profile → Use PDS repository ├── Application metadata → Use custom lexicon ├── Large media files → Use blob storage + references └── Cross-user aggregation → Query BGS/AppView ``` ### Authentication Method ``` Authentication type needed? ├── User login → createSession with handle/password ├── Service-to-service → Use service JWT ├── Public data only → No auth required └── Custom PDS → Implement own auth flow ``` ### Record Operations ``` What record operation? ├── Create new → com.atproto.repo.createRecord ├── Update existing → com.atproto.repo.putRecord ├── Delete → com.atproto.repo.deleteRecord └── Batch operations → com.atproto.repo.applyWrites ``` ## Development Workflows ### Local PDS Setup ```bash # Clone PDS git clone https://github.com/bluesky-social/pds.git cd pds # Configure environment cp .env.example .env # Edit .env with your settings # Start PDS npm install npm run build npm start # Create account on local PDS curl -X POST http://localhost:2583/xrpc/com.atproto.server.createAccount \ -H "Content-Type: application/json" \ -d '{ "handle": "alice.localhost", "email": "alice@example.com", "password": "secure-password" }' ``` ### Custom Feed Generator ```bash # Initialize feed generator mkdir my-feed-generator cd my-feed-generator npm init -y # Install dependencies npm install @atproto/api @atproto/lexicon # Basic feed generator structure cat > index.js << 'EOF' const { BskyAgent } = require('@atproto/api') const agent = new BskyAgent({ service: 'https://bsky.social' }) async function generateFeed() { // Custom feed algorithm const posts = await agent.app.bsky.feed.getTimeline({ limit: 50 }) // Filter and rank posts return posts.data.feed.filter(post => post.post.record.text.includes('#custom') ) } module.exports = { generateFeed } EOF ``` ## Troubleshooting ### Common Errors **Error: "Invalid identifier"** ```bash # Check handle resolution curl "https://bsky.social/xrpc/com.atproto.identity.resolveHandle?handle=your-handle.bsky.social" # Verify DID format echo "DID should start with 'did:plc:' or 'did:web:'" ``` **Error: "ExpiredToken"** ```bash # Refresh session curl -X POST https://bsky.social/xrpc/com.atproto.server.refreshSession \ -H "Authorization: Bearer $ATP_REFRESH_TOKEN" # Create new session if refresh fails unset ATP_ACCESS_TOKEN # Re-run createSession ``` **Error: "InvalidSwap" during record updates** ```bash # Get current record first curl "https://bsky.social/xrpc/com.atproto.repo.getRecord?repo=$ATP_DID&collection=app.bsky.feed.post&rkey=record-key" \ -H "Authorization: Bearer $ATP_ACCESS_TOKEN" # Use returned CID as swapRecord parameter curl -X POST https://bsky.social/xrpc/com.atproto.repo.putRecord \ -H "Authorization: Bearer $ATP_ACCESS_TOKEN" \ -d '{ "repo": "'$ATP_DID'", "collection": "app.bsky.feed.post", "rkey": "record-key", "swapRecord": "current-record-cid", "record": {...} }' ``` **Error: "RateLimitExceeded"** ```bash # Check rate limit headers curl -I "https://bsky.social/xrpc/app.bsky.feed.getTimeline" # Implement exponential backoff sleep_time=1 for i in {1..5}; do if curl -f "your-request"; then break else sleep $sleep_time sleep_time=$((sleep_time * 2)) fi done ``` ### Debug Mode ```bash # Enable verbose logging export ATP_DEBUG=true export NODE_ENV=development # Test connection curl -v "https://bsky.social/xrpc/com.atproto.server.describeServer" ``` ## Security Best Practices - Use app passwords instead of main account password - Store tokens securely, never in code repositories - Implement proper session refresh logic - Validate all user inputs before creating records - Use HTTPS for all API calls - Regularly rotate authentication credentials

Install

curl -s https://skills.skynet.ceo/api/skills/bluesky-api/skill.md