xai-org/x-algorithmPublic

Algorithm powering the For You feed on X

AI summary: The core recommendation system algorithm powering the 'For You' feed on X.

Stars
33.5K
+20 today
Forks
5.4K
Watchers
304
Open issues
36
Open PRs
78
Contributors
~3
Commits
37
Branches
1

RustApache-2.0Created Jan 19, 2026Last push 1d ago+92 stars this week+923 this month

Quick answers

What is x-algorithm?
The core recommendation system algorithm powering the 'For You' feed on X.
What does x-algorithm do?
This repository contains the open-sourced core recommendation system used by X (formerly Twitter) to generate the 'For You' feed. It provides a comprehensive look into how in-network and out-of-network content is retrieved, scored, and ranked using a Grok-based transformer model. The code includes the end-to-end inference pipeline, showcasing the journey from candidate sourcing to final filtering. It serves as a rare, practical example of a production-scale recommendation engine operating on massive, real-time social data. It demonstrates advanced techniques for graph-based user affinity scoring and real-time candidate generation.
Who is x-algorithm for?
This repository is highly technical and intended for machine learning engineers, data scientists, and systems architects interested in large-scale recommendation engines. A strong background in ML and Rust/Python is required to fully comprehend the code.
How do I get started with x-algorithm?
git clone https://github.com/xai-org/x-algorithm.git
How popular is x-algorithm on GitHub?
xai-org/x-algorithm has 33,488 stars and 5,431 forks on GitHub, and gained 92 stars in the last 7 days.
What license does x-algorithm use?
xai-org/x-algorithm is released under the Apache-2.0 license.

Star history

since Jul 29, 2026
010K20K30KJul 2026Aug 2026Sep 2026Oct 2026
33.5K stars as of Oct 3, 2026. Measured daily since Jul 29, 2026; GitHub no longer exposes earlier star timestamps.

Contribution activity

commits per day, last 52 weeks
OctNovDecJanFebMarAprMayJunJulAugSepMonWedFri2025-10-04: 0 commits2025-10-05: 0 commits2025-10-06: 0 commits2025-10-07: 0 commits2025-10-08: 0 commits2025-10-09: 0 commits2025-10-10: 0 commits2025-10-11: 0 commits2025-10-12: 0 commits2025-10-13: 0 commits2025-10-14: 0 commits2025-10-15: 0 commits2025-10-16: 0 commits2025-10-17: 0 commits2025-10-18: 0 commits2025-10-19: 0 commits2025-10-20: 0 commits2025-10-21: 0 commits2025-10-22: 0 commits2025-10-23: 0 commits2025-10-24: 0 commits2025-10-25: 0 commits2025-10-26: 0 commits2025-10-27: 0 commits2025-10-28: 0 commits2025-10-29: 0 commits2025-10-30: 0 commits2025-10-31: 0 commits2025-11-01: 0 commits2025-11-02: 0 commits2025-11-03: 0 commits2025-11-04: 0 commits2025-11-05: 0 commits2025-11-06: 0 commits2025-11-07: 0 commits2025-11-09: 0 commits2025-11-10: 0 commits2025-11-11: 0 commits2025-11-12: 0 commits2025-11-13: 0 commits2025-11-14: 0 commits2025-11-15: 0 commits2025-11-16: 0 commits2025-11-17: 0 commits2025-11-18: 0 commits2025-11-19: 0 commits2025-11-20: 0 commits2025-11-21: 0 commits2025-11-22: 0 commits2025-11-23: 0 commits2025-11-24: 0 commits2025-11-25: 0 commits2025-11-26: 0 commits2025-11-27: 0 commits2025-11-28: 0 commits2025-11-29: 0 commits2025-11-30: 0 commits2025-12-01: 0 commits2025-12-02: 0 commits2025-12-03: 0 commits2025-12-04: 0 commits2025-12-05: 0 commits2025-12-06: 0 commits2025-12-07: 0 commits2025-12-08: 0 commits2025-12-09: 0 commits2025-12-10: 0 commits2025-12-11: 0 commits2025-12-12: 0 commits2025-12-13: 0 commits2025-12-14: 0 commits2025-12-15: 0 commits2025-12-16: 0 commits2025-12-17: 0 commits2025-12-18: 0 commits2025-12-19: 0 commits2025-12-20: 0 commits2025-12-21: 0 commits2025-12-22: 0 commits2025-12-23: 0 commits2025-12-24: 0 commits2025-12-25: 0 commits2025-12-26: 0 commits2025-12-27: 0 commits2025-12-28: 0 commits2025-12-29: 0 commits2025-12-30: 0 commits2025-12-31: 0 commits2026-01-01: 0 commits2026-01-02: 0 commits2026-01-03: 0 commits2026-01-04: 0 commits2026-01-05: 0 commits2026-01-06: 0 commits2026-01-07: 0 commits2026-01-08: 0 commits2026-01-09: 0 commits2026-01-10: 0 commits2026-01-11: 0 commits2026-01-12: 0 commits2026-01-13: 0 commits2026-01-14: 0 commits2026-01-15: 0 commits2026-01-16: 0 commits2026-01-17: 0 commits2026-01-18: 0 commits2026-01-19: 0 commits2026-01-20: 1 commit2026-01-21: 0 commits2026-01-22: 0 commits2026-01-23: 0 commits2026-01-24: 0 commits2026-01-25: 0 commits2026-01-26: 0 commits2026-01-27: 0 commits2026-01-28: 0 commits2026-01-29: 0 commits2026-01-30: 0 commits2026-01-31: 0 commits2026-02-01: 0 commits2026-02-02: 0 commits2026-02-03: 0 commits2026-02-04: 0 commits2026-02-05: 0 commits2026-02-06: 0 commits2026-02-07: 0 commits2026-02-08: 0 commits2026-02-09: 0 commits2026-02-10: 0 commits2026-02-11: 0 commits2026-02-12: 0 commits2026-02-13: 0 commits2026-02-14: 0 commits2026-02-15: 0 commits2026-02-16: 0 commits2026-02-17: 0 commits2026-02-18: 0 commits2026-02-19: 0 commits2026-02-20: 0 commits2026-02-21: 0 commits2026-02-22: 0 commits2026-02-23: 0 commits2026-02-24: 0 commits2026-02-25: 0 commits2026-02-26: 0 commits2026-02-27: 0 commits2026-02-28: 0 commits2026-03-01: 0 commits2026-03-02: 0 commits2026-03-03: 0 commits2026-03-04: 0 commits2026-03-05: 0 commits2026-03-06: 0 commits2026-03-07: 0 commits2026-03-08: 0 commits2026-03-09: 0 commits2026-03-10: 0 commits2026-03-11: 0 commits2026-03-12: 0 commits2026-03-13: 0 commits2026-03-14: 0 commits2026-03-15: 0 commits2026-03-16: 0 commits2026-03-17: 0 commits2026-03-18: 0 commits2026-03-19: 0 commits2026-03-20: 0 commits2026-03-21: 0 commits2026-03-22: 0 commits2026-03-23: 0 commits2026-03-24: 0 commits2026-03-25: 0 commits2026-03-26: 0 commits2026-03-27: 0 commits2026-03-28: 0 commits2026-03-29: 0 commits2026-03-30: 0 commits2026-03-31: 0 commits2026-04-01: 0 commits2026-04-02: 0 commits2026-04-03: 0 commits2026-04-04: 0 commits2026-04-05: 0 commits2026-04-06: 0 commits2026-04-07: 0 commits2026-04-08: 0 commits2026-04-09: 0 commits2026-04-10: 0 commits2026-04-11: 0 commits2026-04-12: 0 commits2026-04-13: 0 commits2026-04-14: 0 commits2026-04-15: 0 commits2026-04-16: 0 commits2026-04-17: 0 commits2026-04-18: 0 commits2026-04-19: 0 commits2026-04-20: 0 commits2026-04-21: 0 commits2026-04-22: 0 commits2026-04-23: 0 commits2026-04-24: 0 commits2026-04-25: 0 commits2026-04-26: 0 commits2026-04-27: 0 commits2026-04-28: 0 commits2026-04-29: 0 commits2026-04-30: 0 commits2026-05-01: 0 commits2026-05-02: 0 commits2026-05-03: 0 commits2026-05-04: 0 commits2026-05-05: 0 commits2026-05-06: 0 commits2026-05-07: 0 commits2026-05-08: 0 commits2026-05-09: 0 commits2026-05-10: 0 commits2026-05-11: 0 commits2026-05-12: 0 commits2026-05-13: 0 commits2026-05-14: 0 commits2026-05-15: 2 commits2026-05-16: 0 commits2026-05-17: 0 commits2026-05-18: 0 commits2026-05-19: 0 commits2026-05-20: 0 commits2026-05-21: 0 commits2026-05-22: 0 commits2026-05-23: 0 commits2026-05-24: 0 commits2026-05-25: 0 commits2026-05-26: 0 commits2026-05-27: 0 commits2026-05-28: 0 commits2026-05-29: 0 commits2026-05-30: 0 commits2026-05-31: 0 commits2026-06-01: 0 commits2026-06-02: 0 commits2026-06-03: 0 commits2026-06-04: 0 commits2026-06-05: 0 commits2026-06-06: 0 commits2026-06-07: 0 commits2026-06-08: 0 commits2026-06-09: 0 commits2026-06-10: 0 commits2026-06-11: 0 commits2026-06-12: 0 commits2026-06-13: 0 commits2026-06-14: 0 commits2026-06-15: 0 commits2026-06-16: 0 commits2026-06-17: 0 commits2026-06-18: 0 commits2026-06-19: 0 commits2026-06-20: 0 commits2026-06-21: 0 commits2026-06-22: 0 commits2026-06-23: 0 commits2026-06-24: 0 commits2026-06-25: 0 commits2026-06-26: 0 commits2026-06-27: 0 commits2026-06-28: 0 commits2026-06-29: 0 commits2026-06-30: 0 commits2026-07-01: 0 commits2026-07-02: 0 commits2026-07-03: 0 commits2026-07-04: 0 commits2026-07-05: 0 commits2026-07-06: 0 commits2026-07-07: 0 commits2026-07-08: 0 commits2026-07-09: 0 commits2026-07-10: 0 commits2026-07-11: 0 commits2026-07-12: 0 commits2026-07-13: 0 commits2026-07-14: 0 commits2026-07-15: 0 commits2026-07-16: 0 commits2026-07-17: 0 commits2026-07-18: 0 commits2026-07-19: 0 commits2026-07-20: 0 commits2026-07-21: 0 commits2026-07-22: 0 commits2026-07-23: 0 commits2026-07-24: 0 commits2026-07-25: 0 commits2026-07-26: 0 commits2026-07-27: 0 commits2026-07-28: 0 commits2026-07-29: 0 commits2026-07-30: 0 commits2026-07-31: 0 commits2026-08-01: 0 commits2026-08-02: 0 commits2026-08-03: 0 commits2026-08-04: 0 commits2026-08-05: 0 commits2026-08-06: 0 commits2026-08-07: 0 commits2026-08-08: 0 commits2026-08-09: 0 commits2026-08-10: 0 commits2026-08-11: 0 commits2026-08-12: 0 commits2026-08-13: 2 commits2026-08-14: 1 commit2026-08-15: 0 commits2026-08-16: 0 commits2026-08-17: 1 commit2026-08-18: 1 commit2026-08-19: 1 commit2026-08-20: 1 commit2026-08-21: 1 commit2026-08-22: 0 commits2026-08-23: 0 commits2026-08-24: 1 commit2026-08-25: 1 commit2026-08-26: 1 commit2026-08-27: 0 commits2026-08-28: 2 commits2026-08-29: 0 commits2026-08-30: 0 commits2026-08-31: 0 commits2026-09-01: 3 commits2026-09-02: 1 commit2026-09-03: 0 commits2026-09-04: 2 commits2026-09-05: 0 commits2026-09-06: 0 commits2026-09-07: 0 commits2026-09-08: 1 commit2026-09-09: 1 commit2026-09-10: 1 commit2026-09-11: 0 commits2026-09-12: 1 commit2026-09-13: 0 commits2026-09-14: 0 commits2026-09-15: 1 commit2026-09-16: 1 commit2026-09-17: 1 commit2026-09-18: 2 commits2026-09-19: 0 commits2026-09-20: 0 commits2026-09-21: 0 commits2026-09-22: 1 commit2026-09-23: 1 commit2026-09-24: 1 commit2026-09-25: 1 commit2026-09-26: 1 commit2026-09-27: 0 commits2026-09-28: 0 commits2026-09-29: 0 commits2026-09-30: 0 commits2026-10-01: 0 commits2026-10-02: 0 commits2026-10-03: 0 commits
36 commits in the last yearLessMore

Signals and awards

derived from tracked data
  • Widely adopted

    33,488 stars

  • Actively maintained

    Pushed within 48 hours

  • Permissive license

    Apache-2.0

  • Continuous integration

    Automated checks passing

  • Repeat trending

    17 trending appearances

What x-algorithm does

This repository contains the open-sourced core recommendation system used by X (formerly Twitter) to generate the 'For You' feed. It provides a comprehensive look into how in-network and out-of-network content is retrieved, scored, and ranked using a Grok-based transformer model. The code includes the end-to-end inference pipeline, showcasing the journey from candidate sourcing to final filtering. It serves as a rare, practical example of a production-scale recommendation engine operating on massive, real-time social data. It demonstrates advanced techniques for graph-based user affinity scoring and real-time candidate generation.

This repository is highly technical and intended for machine learning engineers, data scientists, and systems architects interested in large-scale recommendation engines. A strong background in ML and Rust/Python is required to fully comprehend the code.

  • End-to-End Pipeline: Includes runnable code for the entire retrieval and ranking process.
  • Grok Integration: Demonstrates how the Grok-1 transformer model is adapted for recommendation ranking.
  • Candidate Sourcing: Details the mechanisms for finding relevant tweets both within and outside a user's network.
  • Scoring Mechanisms: Exposes the specific heuristics and machine learning models used to evaluate tweet relevance.
  • Real-World Architecture: Offers architectural insights into handling extreme scale and low-latency requirements.

Where teams use it

Machine Learning Engineers

Study production-grade recommendation systems to improve algorithms in other domains.

Researchers

Analyze the biases and mechanics of one of the world's most influential social media feeds.

System Architects

Learn patterns for scaling complex retrieval and ranking pipelines to millions of concurrent users.

Data Scientists

Examine the feature engineering and scoring logic used to determine content engagement probabilities.

Getting started: git clone https://github.com/xai-org/x-algorithm.git

README

main branch

X For You Feed Algorithm

This repository contains the core code that determines which posts a viewer sees in the For You feed on X. It combines in-network content (from accounts the viewer follows) with out-of-network content (discovered through ML-based retrieval and other mechanisms), filters content based on a variety of inputs, and ranks posts using a transformer model.

Table of Contents


Notable Updates

September 18th, 2026

  • Under the Hood. Reports now include information about whether one's account or posts have had their visibility limited because of required compliance with law(s). For example, you'll be able to see if any of your posts were withheld from showing in a country following a legal demand — and which country.

August 14th, 2026

Notable updates:

  • How weights work. There's a common misconception about how weights related to actions (e.g. Like, Share, Block, Report, etc) work in ranking. The weights scale the predicted probabilities of such actions (or predicted continuous values, e.g. dwell time) — they do not scale the raw engagement counts, so e.g. it'd be incorrect to see that a report has 468 times higher weight than a like and conclude that e.g. "1 report cancels out 468 likes". The weights are a multiple on your own predicted probability of Liking, Reporting, etc, which is substantially driven by your own behavior. We've added comments to the code so that LLMs or people reading it are more likely to understand it correctly.
  • Brazil 2026 Elections. As announced by X, in accordance with Brazilian electoral law, For You now runs Brazil2026ElectionFilter, which removes posts from accounts reported to Brazil's Electoral Court for the 2026 election, unless the viewer explicitly follows the account. (Account list updated August 27, 2026.) A benefit of open-source is that you can see that changes like this exist, and exactly how they work — take a look at the code.

August 13th, 2026

This release:

  • Adds key configuration parameters (including weights used to blend predicted action values into a score for a post)
  • Adds code for systems that impact whether a post is filtered from the For You feed
  • Replaces the Phoenix demonstration model with the code used to train the models the feed uses, as well as synthetic data generation code so one can run a proof-of-concept training run of Phoenix.

Among new systems included are:

  1. Visibility filtering: visibility-filtering/ determines whether to show a post, drop it, or show it behind an interstitial.
  2. The systems that produce labels that drive visibility filtering's responses: rules that apply labels (botmaker/, botmaker-rules/, scarecrow/), models that score accounts on various dimensions (agatha/, bdsm/, user-cred-v2/), models that examine images and video (media-model-proxy/, clip/), and enforcement (abuse-enforcement-service/).
  3. Phoenix model code: phoenix/ now contains code that trains and runs the model, plus synthetic data generation.
  4. SimClusters: simclusters/, an additional source of posts from accounts the viewer does not follow that is called in retrieval alongside Thunder and Phoenix retrieval.

This update is also paired with a new Under the Hood transparency tool that allows people to see aggregate statistics about the labels on their account and posts that can limit visibility.


Overview

The For You feed is assembled per request. Posts come from two places:

  1. In-Network — thunder/ keeps recent posts from the accounts a viewer follows in memory
  2. Out-of-Network — phoenix/ retrieval and simclusters/ find posts from accounts the viewer does not follow

Both are ranked together by the same model. Phoenix reads the viewer's recent engagement history and predicts, for each post, how likely the viewer is to take each action on it. Those predictions are combined into one score using weights held in the code — see Scoring and Ranking.

Two pipelines do the work. The Post Pipeline finds, ranks and filters posts. The Blending Pipeline wraps it and adds what the model does not rank: ads, Who to Follow recommendations, prompts.

Ranking sets the order. Whether a post can be shown at all is decided separately, by visibility-filtering/, from the viewer's own actions such as blocks and mutes and from labels that other systems here attach to posts and accounts.


System Architecture

Request Path

┌──────────────────────────────────────────────────────────────────────────────────────────┐
│                                   FOR YOU FEED REQUEST                                   │
└──────────────────────────────────────────────────────────────────────────────────────────┘
                                             ▼
┌──────────────────────────────── HOME MIXER   home-mixer/ ────────────────────────────────┐
│                                                                                          │
├───────────────────────  POST PIPELINE   PhoenixCandidatePipeline  ───────────────────────┤
│                                                                                          │
│  ┌────────────────────────────────────────────────────────────────────────────────────┐  │
│  │ 1. QUERY HYDRATION                                                                 │  │
│  │    user action sequence — the viewer's recent engagements, and the                 │  │
│  │    main input to the model · following list · blocks and mutes · muted             │  │
│  │    keywords · posts already seen and served · followed topics, etc.                │  │
│  └────────────────────────────────────────────────────────────────────────────────────┘  │
│                                            ▼                                             │
│  ┌────────────────────────────────────────────────────────────────────────────────────┐  │
│  │ 2. CANDIDATE SOURCES — queried in parallel                                         │  │
│  │    ┌───────────────────────────────┐ ┌────────────────────────────────────────┐    │  │
│  │    │ IN-NETWORK                    │ │ OUT-OF-NETWORK                         │    │  │
│  │    │ Thunder                       │ │ Phoenix retrieval   retrieval model    │    │  │
│  │    │   recent posts from the       │ │ SimClusters         cluster similarity │    │  │
│  │    │   accounts the viewer follows │ │                                        │    │  │
│  │    └───────────────────────────────┘ └────────────────────────────────────────┘    │  │
│  └────────────────────────────────────────────────────────────────────────────────────┘  │
│                                            ▼                                             │
│  ┌────────────────────────────────────────────────────────────────────────────────────┐  │
│  │ 3. CANDIDATE HYDRATION                                                             │  │
│  │    post text and media · author details and account labels · quoted post ·         │  │
│  │    language · engagement counts · subscription status, etc.                        │  │
│  └────────────────────────────────────────────────────────────────────────────────────┘  │
│                                            ▼                                             │
│  ┌────────────────────────────────────────────────────────────────────────────────────┐  │
│  │ 4. PRE-SCORING FILTERS                                                             │  │
│  │    duplicates across sources · older than 48 hours · the viewer's own              │  │
│  │    posts · blocked and muted accounts · muted keywords · already seen              │  │
│  │    or served · subscriber-only posts the viewer cannot access, etc.                │  │
│  └────────────────────────────────────────────────────────────────────────────────────┘  │
│                                            ▼                                             │
│  ┌────────────────────────────────────────────────────────────────────────────────────┐  │
│  │ 5. SCORING                                                                         │  │
│  │    PhoenixScorer   a probability for each action the viewer might take             │  │
│  │    RankingScorer   weighted sum, then repeated-author decay, an                    │  │
│  │                    out-of-network discount, a new-author boost                     │  │
│  │    VMRanker        calls the reranking service in vm-ranker/                       │  │
│  └────────────────────────────────────────────────────────────────────────────────────┘  │
│                                            ▼                                             │
│  ┌────────────────────────────────────────────────────────────────────────────────────┐  │
│  │ 6. SELECTION — TopKScoreSelector                                                   │  │
│  │    sort by final score, keep the top K                                             │  │
│  └────────────────────────────────────────────────────────────────────────────────────┘  │
│                                            ▼                                             │
│  ┌────────────────────────────────────────────────────────────────────────────────────┐  │
│  │ 7. POST-SELECTION FILTERS — after the order is fixed                               │  │
│  │    VFCandidateHydrator  asks visibility-filtering/ per post and viewer             │  │
│  │    VFFilter             removes the posts it said to drop                          │  │
│  │    DedupConversationFilter  collapses branches of one conversation                 │  │
│  │                         ◄── these labels come from the Labeling Path               │  │
│  └────────────────────────────────────────────────────────────────────────────────────┘  │
│                                                                                          │
├─────────────────────  BLENDING PIPELINE   ForYouCandidatePipeline  ──────────────────────┤
│                                                                                          │
│  ┌────────────────────────────────────────────────────────────────────────────────────┐  │
│  │ the ranked posts are one source here; the others add non-post items:               │  │
│  │    ads · Who to Follow · prompts · push-to-home, etc.                              │  │
│  │                                                                                    │  │
│  │ BlenderSelector interleaves them. The default ads blender reorders                 │  │
│  │ posts for ad adjacency. Who to Follow and prompts go at fixed positions.           │  │
│  └────────────────────────────────────────────────────────────────────────────────────┘  │
│                                            ▼                                             │
│  ┌────────────────────────────────────────────────────────────────────────────────────┐  │
│  │ SIDE EFFECTS — after the response is sent                                          │  │
│  │    record which posts were served · refresh the post cache · log ad                │  │
│  │    and client events, etc.                                                         │  │
│  └────────────────────────────────────────────────────────────────────────────────────┘  │
│                                                                                          │
└──────────────────────────────────────────────────────────────────────────────────────────┘
                                             ▼
┌──────────────────────────────────────────────────────────────────────────────────────────┐
│                                 RANKED FOR YOU TIMELINE                                  │
└──────────────────────────────────────────────────────────────────────────────────────────┘

Stages can be switched on and off individually, with defaults in home-mixer/params/param.rs — see Experiments and Configuration for how those defaults relate to what runs in production.

Labeling Path

┌───────  1. CONTENT UNDERSTANDING — happens continuously, not on the request path  ───────┐
│                                                                                          │
│    POSTS AND MEDIA                    ACCOUNTS                                           │
│    grox/          classifiers for     agatha/        blocks and reports                  │
│                   text and media                     relative to favorites               │
│    media-model-   image and video     bdsm/          inauthentic behavior                │
│      proxy/       models              user-cred-v2/  PageRank over follow                │
│    clip/          image and text                     and engagement edges                │
│                   embeddings the                                                         │
│                   media models use                                                       │
│                                                                                          │
└──────────────────────────────────────────────────────────────────────────────────────────┘
                                             ▼
┌──────────────────────────────────  2. LABELING RULES  ───────────────────────────────────┐
│                                                                                          │
│    scarecrow/  reacts to events as they happen. Embeds botmaker/ as its                  │
│       rule engine and loads rules from botmaker-rules/scarecrow/. A rule                 │
│       reads: on this event, if these conditions hold, apply this label.                  │
│                                                                                          │
│    abuse-enforcement-service/  reads model scores about an account. Its                  │
│       rules label the account or its posts, challenge it, or suspend it.                 │
│                                                                                          │
│    safety-label-user-agg/  labels an account for what its posts collected.               │
│                                                                                          │
└──────────────────────────────────────────────────────────────────────────────────────────┘
                                             ▼
┌──────────────────────────────────────  3. STORAGE  ──────────────────────────────────────┐
│             labels are written to storage, and read back on the request path             │
└──────────────────────────────────────────────────────────────────────────────────────────┘
                                             ▼
┌───────────────────  4. VISIBILITY FILTERING   visibility-filtering/  ────────────────────┐
│                                                                                          │
│    for each post and viewer, one of three answers:                                       │
│                                                                                          │
│       ALLOW          show the post normally                                              │
│       INTERSTITIAL   show it behind an interstitial the viewer can tap                   │
│                      through, e.g. for adult or graphic media                            │
│       DROP           do not show it                                                      │
│                                                                                          │
│    the rules read the labels above, plus whether the viewer blocks, mutes                │
│    or follows the author, whether that account is protected, suspended or                │
│    deactivated, subscriber-only status, and the viewer's settings and                    │
│    country. Some rules drop a post only when it is a recommendation from                 │
│    an account the viewer does not follow — spam caught at high recall, for               │
│    instance. The same post is allowed to a follower.                                     │
│                                                                                          │
└──────────────────────────────────────────────────────────────────────────────────────────┘
                                             ▼
┌───────────────  5. POST-SELECTION FILTERS   VFFilter, AncillaryVFFilter  ────────────────┐
│                                                                                          │
│    drop  ──►  the post is removed after ranking, and so is any post whose                │
│               ancestor in the thread, quoted post or reposted post was                   │
│               itself dropped                                                             │
│    interstitial  ──►  the post stays in the feed; nothing in this                        │
│               repository draws the interstitial                                          │
│                                                                                          │
└──────────────────────────────────────────────────────────────────────────────────────────┘

Components

Home Mixer and Candidate Pipeline

Component What it does
home-mixer/ Builds the For You feed: the pipeline stages, the scoring weights, and calls other systems on the request path.
candidate-pipeline/ The framework home-mixer is built on. Defines the stage types — source, hydrator, filter, scorer, selector, side effect — and runs them, in parallel where it can.

Candidate Sources

Component What it does
thunder/ Holds recent posts in memory as they are published, and returns those from the accounts a viewer follows.
phoenix/ retrieval Embeds the viewer and each post as vectors, and returns the posts nearest the viewer.
simclusters/ Clusters accounts and posts by who engages with what, then uses the clusters to find candidates.

Retrieval Index

Component What it does
phoenix-rankall/ Maintains the index of posts Phoenix retrieval queries, updating it as events arrive.
phoenix-rankall-strato/ The event layer that determines which index a post belongs in, consulting visibility filtering first.

Ranking

Component What it does
phoenix/ ranking Predicts how likely the viewer is to take each action on each post. Training and serving code, in JAX with a Rust serving layer.
vm-ranker/ The service VMRanker calls once posts are scored. It reorders them with a determinantal point process over their embeddings, giving up a little score for less similarity between neighbours.

Content Understanding

These produce the scores and labels that Visibility Filtering reads.

Component What it does
grox/ Runs as posts are published. Classifiers for categories such as spam, adult content and violent media, plus numeric representations of a post's text and images.
media-model-proxy/ Serves the image and video models: adult content, violence and gore, hateful symbols, subject matter, and matching against known media.
clip/ Trains the image and text embedding model whose media embeddings the classifiers above take as input.
agatha/ Offline batch jobs that label an account from how others respond to its posts: blocks, reports and spam reports relative to favorites, plus spam-suspension and adult-content labels.
bdsm/ Reads the sequence of actions an account takes over time to identify signs of inauthentic or abusive behavior.
user-cred-v2/ Runs PageRank over the follow graph and engagement edges, and turns the resulting mass into a per-account score.
adult-content/ Trains and calibrates a classifier for adult media.
pnsfwmedia/ An adult-media classifier that combines CLIP media embeddings with account-level scores, including the calibrated score from agatha.

Visibility Filtering

Component What it does
visibility-filtering/ Determines whether a post is shown to a viewer. Rules in rules/registry.rs.
scarecrow/ Applies label rules to events as they happen. Embeds botmaker as its rule engine.
botmaker/ That rule engine: the language rules are written in, its compiler, and its runtime.
botmaker-rules/ The rules scarecrow loads. To reduce the risk of gaming to circumvent these systems, some rules aren't currently in this repository.
abuse-enforcement-service/ Acts on model scores about an account rather than on events: labels it or its posts, challenges it, or suspends it.
safety-label-user-agg/ Labels an account for what its posts collected.
visibility-filtering-client/ The client callers use to reach visibility filtering, and the post safety-label types it answers with.
under-the-hood/ Builds the per-account Under the Hood report: daily jobs collect the labels applied to an account and its posts, which the serving layer aggregates over a period, and displays as a page or JSON file.
takedowns/ Produces the takedown-reason list that rules/context.rs applies: the tweet entity service merges a post's own reasons with its author's account-level ones.

How It Works

Scoring and Ranking

Phoenix predicts a probability for each action:

Engagement    favorite · reply · repost · quote · share · share via DM · share via copy link
Clicks        post · profile · link · photo expand · video open · quoted post
Attention     video quality view · dwell · dwell time · click dwell time · active seconds
Author        follow author
Negative      not interested · mute author · block author · report · not dwelled

RankingScorer combines them:

Final Score = Σ (weight_i × P(action_i))

Positive actions carry positive weights, negative actions negative ones. The weights are in home-mixer/params/param.rs; the arithmetic is in xai-value-model/scoring.rs.

There is a common misconception to be aware of about the weights: they scale the predicted probabilities (or predicted continuous values, e.g. dwell time) — they do not scale the raw engagement counts, so e.g. it'd be incorrect to see that a report has 468 times higher weight than a like and conclude that e.g. "1 report cancels out 468 likes". The weights are a multiple on your own predicted probability of Liking, Reporting, etc, which is substantially driven by your own behavior.

Three adjustments follow:

  • Author Diversity: each post after an author's first is multiplied by a decaying factor, down to a floor.
  • Out-of-Network Discount: posts from accounts the viewer does not follow are multiplied by a factor below 1, as are replies and reposts from accounts the viewer does follow.
  • New-Author Boost: posts from authors whose impressions are below a threshold are lifted toward a target position.

VMRanker then calls vm-ranker/, a separate service that reorders the result.

Filtering

Pre-Scoring Filters (home-mixer/filters/), in order:

Filter Removes
DropDuplicatesFilter The same post returned by more than one source
CoreDataHydrationFilter Posts whose text and metadata failed to load
AgeFilter Posts older than 48 hours
SelfTweetFilter The viewer's own posts
OONRetweetReplyFilter Reposts and replies from accounts the viewer does not follow, and replies whose parent is missing
OONNsfwSimclustersFilter SimClusters posts whose author is flagged for adult content, when the viewer does not follow them
RetweetDeduplicationFilter Repeated reposts of the same post
IneligibleSubscriptionFilter Subscriber-only posts the viewer cannot access
PreviouslySeenPostsFilter Posts the viewer has already been shown
PreviouslySeenPostsBackupFilter The same, from a second record of impressions
PreviouslyServedPostsFilter Posts already served earlier in the session
MutedKeywordFilter Posts matching the viewer's muted keywords
AuthorSocialgraphFilter Posts from accounts the viewer blocks or mutes
VideoFilter Video posts, when the request excludes video
TopicIdsFilter Posts outside the requested topics, and posts in excluded topics
NewUserMinEngagementFilter For new accounts, out-of-network posts below an engagement threshold
InventoryHoldoutFilter A configured percentage of posts, chosen deterministically per post and viewer

Already-seen posts are handled twice over: ThunderSource is passed the list and leaves them out, the other sources are not, so their repeats are caught by the filters above.

Post-Selection Filters:

Filter Removes
VFFilter Posts visibility-filtering/ answered drop for
AncillaryVFFilter Posts whose parent, quoted or reposted post was itself dropped
DedupConversationFilter Additional branches of the same conversation

Two things to know about how the rules run:

  • The first rule that answers drop ends the evaluation.
  • A further set of rules applies only when the post is a recommendation from an account the viewer does not follow, and those rules can only drop — spam caught at high recall, for instance. The same post is allowed to a follower. Both sets are listed in evaluation order in visibility-filtering/rules/registry.rs.

Experiments and Configuration

As we work to improve the algorithm we regularly run experiments on a small percentage of timeline traffic. Our aim is for experiments running at a notable share of traffic — e.g. 10% or more — to be visible in this repository.

To enable experimentation, many tunable values are read from a configuration system rather than written into the code. To help people understand the production defaults, we run cron scripts that set the defaults in this repository's code to be the primary production values, for example in home-mixer/params/param.rs.

docs/BIDIRECTIONAL_BOOST_CHANGE.md follows a widely-discussed timeline change, exemplifying what you would see as a param value changes over time.


What's not in this repo?

We believe transparency is important for trust, and our aim is for the public to be able to understand how posts are distributed on X, so they can audit, critique or even help improve the system.

One challenge with making code that impacts post distribution public is that people could use it to try to game the system. To reduce the risk of this, there are a limited set of files not currently published in the repository, e.g.:

  • Grox prompts. E.g. the j2 files with the specific LLM prompts used in Grox.
  • Some botmaker rules

However, we still want the public to have insight into these systems. To accomplish that, we're piloting a new transparency tool that will show people the visibility-impacting labels that have been applied to their account and posts. This approach has multiple benefits:

  • one can see the outcomes of these systems (and whether they affect their own account)
  • one can see whether labels have been manually applied outside of automated systems
  • one can match any labels present on their account to the code to understand if or how the visibility of their posts is affected, and critique it if desired

We believe the combination of code + transparent outputs is a powerful one for public transparency, and welcome feedback.

Deployment-related code

The focus of the repository is transparency into the code that affects post visibility in the For You timeline. All of the code here is inspectable, and some of the code is even designed to be runnable end-to-end — e.g. training and running the Phoenix scoring model. Where code is meant to be built and run, the relevant manifests are in the repo, e.g. phoenix/ ships a Cargo workspace, a pyproject.toml, a quickstart and synthetic data generation, so a small model can be trained and served end-to-end. Elsewhere, code may not necessarily include build- or deployment-related files or generally self-explanatory infrastructure imports (e.g. xai_service_runner or xai_kafka). If there's anything not here that you believe would help your understanding of the algorithm, please let us know.


Under the Hood Label Transparency Tool

We're piloting a new transparency tool that lets people see aggregate statistics about the visibility-impacting labels on their account and posts. Paired with the code in this repository, we believe this gives people valuable insight into the visibility of their posts.

The tool is available here — we'll be shaping it based on your feedback and expanding availability over time. The jobs and serving code that build the report are in under-the-hood/. The page that renders it is in under-the-hood/jetfuel/.


Key Design Decisions

1. Multi-Action Prediction

Rather than predicting a single "relevance" score, the model predicts probabilities for many actions. Combining them into one number is a separate, explicit step.

2. Candidate Isolation in Ranking

During transformer inference, candidates cannot attend to each other—only to the viewer context. This ensures the score for a post doesn't depend on which other posts are in the batch, making scores consistent and cacheable.

3. Hash-Based Embeddings

Both retrieval and ranking use multiple hash functions for embedding lookup, so there is no vocabulary to maintain and a new post is representable immediately.

4. Ranking and Visibility Are Separate

Ranking decides the order. Visibility filtering decides whether a post can be shown at all. Different services, different inputs, different rules.

5. Composable Pipeline Architecture

The candidate-pipeline crate provides a flexible framework for building recommendation pipelines with:

  • Separation of pipeline execution and monitoring from business logic
  • Parallel execution of independent stages and graceful error handling
  • Easy addition of new sources, hydrations, filters, and scorers

License

Licensed under the Apache License 2.0. See LICENSE.

View on GitHub

Recent activity

commits and pull requests

Code frequency

additions and deletions
+367.8K-367.8KWeek of 2026-01-18: +8,816 linesWeek of 2026-01-18: -0 linesWeek of 2026-01-25: +0 linesWeek of 2026-01-25: -0 linesWeek of 2026-02-01: +0 linesWeek of 2026-02-01: -0 linesWeek of 2026-02-08: +0 linesWeek of 2026-02-08: -0 linesWeek of 2026-02-15: +0 linesWeek of 2026-02-15: -0 linesWeek of 2026-02-22: +0 linesWeek of 2026-02-22: -0 linesWeek of 2026-03-01: +0 linesWeek of 2026-03-01: -0 linesWeek of 2026-03-08: +0 linesWeek of 2026-03-08: -0 linesWeek of 2026-03-15: +0 linesWeek of 2026-03-15: -0 linesWeek of 2026-03-22: +0 linesWeek of 2026-03-22: -0 linesWeek of 2026-03-29: +0 linesWeek of 2026-03-29: -0 linesWeek of 2026-04-05: +0 linesWeek of 2026-04-05: -0 linesWeek of 2026-04-12: +0 linesWeek of 2026-04-12: -0 linesWeek of 2026-04-19: +0 linesWeek of 2026-04-19: -0 linesWeek of 2026-04-26: +0 linesWeek of 2026-04-26: -0 linesWeek of 2026-05-03: +0 linesWeek of 2026-05-03: -0 linesWeek of 2026-05-10: +18,265 linesWeek of 2026-05-10: -928 linesWeek of 2026-05-17: +0 linesWeek of 2026-05-17: -0 linesWeek of 2026-05-24: +0 linesWeek of 2026-05-24: -0 linesWeek of 2026-05-31: +0 linesWeek of 2026-05-31: -0 linesWeek of 2026-06-07: +0 linesWeek of 2026-06-07: -0 linesWeek of 2026-06-14: +0 linesWeek of 2026-06-14: -0 linesWeek of 2026-06-21: +0 linesWeek of 2026-06-21: -0 linesWeek of 2026-06-28: +0 linesWeek of 2026-06-28: -0 linesWeek of 2026-07-05: +0 linesWeek of 2026-07-05: -0 linesWeek of 2026-07-12: +0 linesWeek of 2026-07-12: -0 linesWeek of 2026-07-19: +0 linesWeek of 2026-07-19: -0 linesWeek of 2026-07-26: +0 linesWeek of 2026-07-26: -0 linesWeek of 2026-08-02: +0 linesWeek of 2026-08-02: -0 linesWeek of 2026-08-09: +367,794 linesWeek of 2026-08-09: -13,951 linesWeek of 2026-08-16: +5,882 linesWeek of 2026-08-16: -1,520 linesWeek of 2026-08-23: +12,162 linesWeek of 2026-08-23: -2,668 linesWeek of 2026-08-30: +9,170 linesWeek of 2026-08-30: -6,668 linesWeek of 2026-09-06: +14,723 linesWeek of 2026-09-06: -1,963 linesWeek of 2026-09-13: +7,802 linesWeek of 2026-09-13: -5,851 linesWeek of 2026-09-20: +30,398 linesWeek of 2026-09-20: -16,739 linesWeek of 2026-09-27: +0 linesWeek of 2026-09-27: -0 linesJan 18, 2026Sep 27, 2026
+475K lines added, -50.3K removed over the last year.

Commits per week

last 52 weeks
60Week of 2025-10-04: 0 commitsWeek of 2025-10-11: 0 commitsWeek of 2025-10-18: 0 commitsWeek of 2025-10-25: 0 commitsWeek of 2025-11-01: 0 commitsWeek of 2025-11-09: 0 commitsWeek of 2025-11-16: 0 commitsWeek of 2025-11-23: 0 commitsWeek of 2025-11-30: 0 commitsWeek of 2025-12-07: 0 commitsWeek of 2025-12-14: 0 commitsWeek of 2025-12-21: 0 commitsWeek of 2025-12-28: 0 commitsWeek of 2026-01-04: 0 commitsWeek of 2026-01-11: 0 commitsWeek of 2026-01-18: 1 commitsWeek of 2026-01-25: 0 commitsWeek of 2026-02-01: 0 commitsWeek of 2026-02-08: 0 commitsWeek of 2026-02-15: 0 commitsWeek of 2026-02-22: 0 commitsWeek of 2026-03-01: 0 commitsWeek of 2026-03-08: 0 commitsWeek of 2026-03-15: 0 commitsWeek of 2026-03-22: 0 commitsWeek of 2026-03-29: 0 commitsWeek of 2026-04-05: 0 commitsWeek of 2026-04-12: 0 commitsWeek of 2026-04-19: 0 commitsWeek of 2026-04-26: 0 commitsWeek of 2026-05-03: 0 commitsWeek of 2026-05-10: 2 commitsWeek of 2026-05-17: 0 commitsWeek of 2026-05-24: 0 commitsWeek of 2026-05-31: 0 commitsWeek of 2026-06-07: 0 commitsWeek of 2026-06-14: 0 commitsWeek of 2026-06-21: 0 commitsWeek of 2026-06-28: 0 commitsWeek of 2026-07-05: 0 commitsWeek of 2026-07-12: 0 commitsWeek of 2026-07-19: 0 commitsWeek of 2026-07-26: 0 commitsWeek of 2026-08-02: 0 commitsWeek of 2026-08-09: 3 commitsWeek of 2026-08-16: 5 commitsWeek of 2026-08-23: 5 commitsWeek of 2026-08-30: 6 commitsWeek of 2026-09-06: 4 commitsWeek of 2026-09-13: 5 commitsWeek of 2026-09-20: 5 commitsWeek of 2026-09-27: 0 commitsOct 4, 2025Sep 27, 2026
36 commits in the last 52 weeks.

When work happens

weekday and hour
SunMonTueWedThuFriSat036912151821Sun 0:00 — 0 commitsSun 1:00 — 0 commitsSun 2:00 — 0 commitsSun 3:00 — 0 commitsSun 4:00 — 0 commitsSun 5:00 — 0 commitsSun 6:00 — 0 commitsSun 7:00 — 0 commitsSun 8:00 — 0 commitsSun 9:00 — 0 commitsSun 10:00 — 0 commitsSun 11:00 — 0 commitsSun 12:00 — 0 commitsSun 13:00 — 0 commitsSun 14:00 — 0 commitsSun 15:00 — 0 commitsSun 16:00 — 0 commitsSun 17:00 — 0 commitsSun 18:00 — 0 commitsSun 19:00 — 0 commitsSun 20:00 — 0 commitsSun 21:00 — 0 commitsSun 22:00 — 0 commitsSun 23:00 — 0 commitsMon 0:00 — 0 commitsMon 1:00 — 0 commitsMon 2:00 — 0 commitsMon 3:00 — 0 commitsMon 4:00 — 0 commitsMon 5:00 — 0 commitsMon 6:00 — 0 commitsMon 7:00 — 0 commitsMon 8:00 — 0 commitsMon 9:00 — 0 commitsMon 10:00 — 0 commitsMon 11:00 — 0 commitsMon 12:00 — 0 commitsMon 13:00 — 0 commitsMon 14:00 — 0 commitsMon 15:00 — 0 commitsMon 16:00 — 0 commitsMon 17:00 — 0 commitsMon 18:00 — 1 commitsMon 19:00 — 0 commitsMon 20:00 — 1 commitsMon 21:00 — 0 commitsMon 22:00 — 0 commitsMon 23:00 — 0 commitsTue 0:00 — 1 commitsTue 1:00 — 1 commitsTue 2:00 — 1 commitsTue 3:00 — 0 commitsTue 4:00 — 1 commitsTue 5:00 — 0 commitsTue 6:00 — 0 commitsTue 7:00 — 0 commitsTue 8:00 — 0 commitsTue 9:00 — 0 commitsTue 10:00 — 0 commitsTue 11:00 — 0 commitsTue 12:00 — 0 commitsTue 13:00 — 0 commitsTue 14:00 — 0 commitsTue 15:00 — 0 commitsTue 16:00 — 0 commitsTue 17:00 — 0 commitsTue 18:00 — 1 commitsTue 19:00 — 1 commitsTue 20:00 — 1 commitsTue 21:00 — 0 commitsTue 22:00 — 0 commitsTue 23:00 — 2 commitsWed 0:00 — 0 commitsWed 1:00 — 1 commitsWed 2:00 — 1 commitsWed 3:00 — 0 commitsWed 4:00 — 0 commitsWed 5:00 — 0 commitsWed 6:00 — 0 commitsWed 7:00 — 0 commitsWed 8:00 — 0 commitsWed 9:00 — 0 commitsWed 10:00 — 0 commitsWed 11:00 — 0 commitsWed 12:00 — 0 commitsWed 13:00 — 0 commitsWed 14:00 — 0 commitsWed 15:00 — 0 commitsWed 16:00 — 0 commitsWed 17:00 — 0 commitsWed 18:00 — 0 commitsWed 19:00 — 1 commitsWed 20:00 — 2 commitsWed 21:00 — 1 commitsWed 22:00 — 0 commitsWed 23:00 — 0 commitsThu 0:00 — 0 commitsThu 1:00 — 1 commitsThu 2:00 — 0 commitsThu 3:00 — 0 commitsThu 4:00 — 0 commitsThu 5:00 — 1 commitsThu 6:00 — 0 commitsThu 7:00 — 0 commitsThu 8:00 — 0 commitsThu 9:00 — 0 commitsThu 10:00 — 0 commitsThu 11:00 — 0 commitsThu 12:00 — 0 commitsThu 13:00 — 0 commitsThu 14:00 — 0 commitsThu 15:00 — 0 commitsThu 16:00 — 0 commitsThu 17:00 — 2 commitsThu 18:00 — 0 commitsThu 19:00 — 0 commitsThu 20:00 — 1 commitsThu 21:00 — 1 commitsThu 22:00 — 0 commitsThu 23:00 — 0 commitsFri 0:00 — 1 commitsFri 1:00 — 3 commitsFri 2:00 — 0 commitsFri 3:00 — 0 commitsFri 4:00 — 0 commitsFri 5:00 — 0 commitsFri 6:00 — 0 commitsFri 7:00 — 1 commitsFri 8:00 — 0 commitsFri 9:00 — 0 commitsFri 10:00 — 0 commitsFri 11:00 — 0 commitsFri 12:00 — 0 commitsFri 13:00 — 0 commitsFri 14:00 — 0 commitsFri 15:00 — 0 commitsFri 16:00 — 0 commitsFri 17:00 — 0 commitsFri 18:00 — 0 commitsFri 19:00 — 1 commitsFri 20:00 — 1 commitsFri 21:00 — 2 commitsFri 22:00 — 1 commitsFri 23:00 — 1 commitsSat 0:00 — 0 commitsSat 1:00 — 0 commitsSat 2:00 — 1 commitsSat 3:00 — 1 commitsSat 4:00 — 0 commitsSat 5:00 — 0 commitsSat 6:00 — 0 commitsSat 7:00 — 0 commitsSat 8:00 — 0 commitsSat 9:00 — 0 commitsSat 10:00 — 0 commitsSat 11:00 — 0 commitsSat 12:00 — 0 commitsSat 13:00 — 0 commitsSat 14:00 — 0 commitsSat 15:00 — 0 commitsSat 16:00 — 0 commitsSat 17:00 — 0 commitsSat 18:00 — 0 commitsSat 19:00 — 0 commitsSat 20:00 — 0 commitsSat 21:00 — 0 commitsSat 22:00 — 0 commitsSat 23:00 — 0 commits
Commit volume by weekday and hour (UTC). Larger dots mean more commits.
DateListRankStars gained
Sep 12, 2026monthly#10+6,248
Sep 11, 2026monthly#10+6,248
Sep 10, 2026monthly#7+6,170
Sep 9, 2026monthly#7+6,114
Sep 8, 2026monthly#7+6,041
Sep 7, 2026monthly#6+5,983
Sep 6, 2026monthly#9+5,935
Sep 5, 2026monthly#8+5,878
Sep 4, 2026monthly#8+5,828
May 18, 2026daily#4+99
May 17, 2026daily#6+205
May 16, 2026daily#1+438
May 15, 2026daily#8+106
Jan 23, 2026daily#8+374
Jan 22, 2026daily#3+475
  • ultraworkers/claw-code

    An agent-managed museum exhibit, built in Rust with Gajae-Code / LazyCodex — developed and maintained with no human intervention.

    195.2K stars · Rust

  • farion1231/cc-switch

    A cross-platform desktop All-in-One assistant for Claude Code, Codex, OpenCode, OpenClaw, Grok Build & Hermes Agent. Only official website: ccswitch.io

    140K stars · Rust

  • openai/codex

    Lightweight coding agent that runs in your terminal

    127.8K stars · Rust

  • denoland/deno

    A modern runtime for JavaScript and TypeScript.

    108.6K stars · Rust

  • ruvnet/RuView

    π RuView turns commodity WiFi signals into real-time spatial intelligence, vital sign monitoring, and presence detection — all without a single pixel of video.

    96.4K stars · Rust

  • oven-sh/bun

    Incredibly fast JavaScript runtime, bundler, test runner, and package manager – all in one

    96.1K stars · Rust