Skip to main content

What is AT Protocol?

The Authenticated Transfer Protocol (ATP or atproto) is a decentralized social media protocol developed by Bluesky. It provides the foundational infrastructure for building federated social applications with user sovereignty at its core.

Core Architecture

AT Protocol is built on several key architectural components that work together to create a decentralized, authenticated, and performant social network:

Identity

Decentralized identifiers (DIDs) and human-readable handles

Repositories

User data storage using Merkle Search Trees (MST)

Lexicons

Schema definition language for API and data validation

Authentication

Session management with JWT tokens

Why AT Protocol Matters

User Ownership

Users own their data and identity. Your account isn’t tied to a single server - you can move between providers while keeping your identity, content, and social graph.

Federation & Interoperability

Multiple providers can participate in the network. Services interoperate using standardized schemas (Lexicons), ensuring compatibility across implementations.

Cryptographic Verification

All data is cryptographically signed and stored in authenticated data structures (repositories), making tampering detectable and ensuring data integrity.

Algorithmic Choice

The protocol separates content hosting from content discovery, allowing users to choose their own algorithms and feed experiences.

Key Components

Personal Data Server (PDS)

The PDS hosts user repositories containing their posts, likes, follows, and other records. Each user has an account on a PDS, but can migrate to a different provider.
import { AtpAgent } from '@atproto/api'

// Connect to a PDS
const agent = new AtpAgent({
  service: 'https://bsky.social'
})

// Create a session
await agent.login({
  identifier: 'alice.bsky.social',
  password: 'hunter2'
})

// Create a post (stored in user's repository)
await agent.post({
  text: 'Hello AT Protocol!',
  createdAt: new Date().toISOString()
})

Application View (AppView)

The AppView aggregates data from multiple repositories to provide queryable views of the network. It indexes content and serves feeds, notifications, and search results.

Big Graph Service (BGS)

The BGS collects repository updates from PDSes and redistributes them as a “firehose” event stream that AppViews can subscribe to.

Protocol Layers

AT Protocol is organized into distinct layers:

1. Identity Layer

  • DIDs: Persistent, cryptographic identifiers (e.g., did:plc:ewvi7nxzyoun6zhxrhs64oiz)
  • Handles: Human-readable names (e.g., alice.bsky.social)
  • DID Documents: Contain service endpoints and public keys

2. Data Layer

  • Repositories: Signed, authenticated data stores
  • MST: Merkle Search Tree for efficient data organization
  • Records: Individual data items (posts, profiles, likes, etc.)
  • Lexicons: Schema definitions for record types

3. Network Layer

  • XRPC: HTTP-based RPC protocol
  • Repository Sync: CAR file format for repo distribution
  • Event Streams: Real-time updates via websockets

Data Model

Every piece of content in AT Protocol is a record stored in a repository:
import { Repo } from '@atproto/repo'
import { Keypair } from '@atproto/crypto'

// Records are identified by:
// - DID (user identifier)
// - Collection (record type, e.g., "app.bsky.feed.post")
// - Record key (unique within collection)

// Full identifier: at://did:plc:abc123/app.bsky.feed.post/3jzxvpqr2bc2a
Records are organized by collection type and validated against Lexicon schemas.

Self-Authenticating Data

All repositories are cryptographically signed Merkle trees. This provides several benefits:
  • Tamper Detection: Any modification to data changes the root hash
  • Efficient Sync: Only changed portions need to be transferred
  • Proof Generation: Can prove specific records exist without sending entire repo
  • Portability: Users can export their signed repository and import elsewhere
import { MemoryBlockstore } from '@atproto/repo'
import { Repo } from '@atproto/repo'

// Create a repository
const storage = new MemoryBlockstore()
const keypair = await Keypair.create({ exportable: true })

const repo = await Repo.create(
  storage,
  'did:plc:user123',
  keypair,
  [
    {
      action: 'create',
      collection: 'app.bsky.feed.post',
      rkey: '3jzxvpqr2bc2a',
      record: {
        $type: 'app.bsky.feed.post',
        text: 'Hello world!',
        createdAt: new Date().toISOString()
      }
    }
  ]
)

// Repository is cryptographically signed
console.log('Root CID:', repo.cid)

Next Steps

Explore the core concepts in detail:

Additional Resources

Protocol Specifications

Official AT Protocol specifications

Lexicon Documentation

Lexicon schema language reference

GitHub Repository

AT Protocol TypeScript implementation

Developer Guide

Getting started with AT Protocol development

Build docs developers (and LLMs) love