Aug 15, 2026

A Study of the 𝕏 For You Algorithm

A static source audit of xAI's open repository, covering candidate retrieval, multi-action scoring, author diversity, DPP reranking, and visibility filtering in X's For You timeline.

Source repository: x-algorithm.

This report is based on the public main branch. The README records the most recent public update as 2026-08-13. Scoring weights and enforcement-rule files are annotated as synced with production configuration on 2026-08-12.

The report is a static reading of the repository source and the official README. Numeric values are the committed defaults in param.rs, config.rs, and YAML. Experiment flags, GrowthBook or feature-switch overrides, and unpublished rules may cause production behavior to differ from the description below. This is not an observation of live traffic.


1. Overview

The For You timeline is assembled per request. Candidates come from two sources:

  1. In-network: recent posts from accounts the viewer follows, read from in-memory storage (Thunder).
  2. Out-of-network: posts from accounts the viewer does not follow, retrieved by vector search (Phoenix retrieval) and interest clustering (SimClusters).

Both sets of candidates are scored by the same Phoenix ranking model. The model predicts, for each candidate, the probability of several viewer actions. Explicit weights then combine those predictions into a single score. Author diversity, an out-of-network discount, a new-author lift, and DPP reranking are applied in that order.

After ranking, visibility filtering decides separately whether the post is shown normally to the current viewer, shown behind an interstitial, or dropped. Visibility filtering does not change the score.

Ranking optimizes predicted action value for the viewer and the candidate. It does not optimize accumulated engagement counts on the post.

The following constraints can be read directly from the code defaults:

  • The For You eligibility window is about 48 hours.
  • The default weight on share-via-copy-link is 40 times the like weight. The absolute default weight on report is 468 times the like weight.
  • Out-of-network posts, and in-network replies and reposts, are multiplied by 0.75 by default.
  • Within one request result, later posts by the same author are decayed by formula starting at the second post.
  • Subscriber-only or exclusive content does not enter For You for viewers who are not subscribers.
  • Out-of-network recommendations apply an additional set of drop rules that do not apply in-network.

2. Scope and method

2.1 What the repository covers

The official README states that the purpose of the repository is to let the public audit how posts enter For You. The top-level directories of the public repository are as follows.

LayerDirectoriesRole
Orchestrationhome-mixer/, candidate-pipeline/Request path: retrieval, hydration, filtering, scoring, blending
Retrievalthunder/, phoenix/, simclusters/, phoenix-rankall/, phoenix-rankall-strato/In-network memory, out-of-network vectors, interest clusters, retrieval index
Rankingphoenix/ (ranking), vm-ranker/Multi-action prediction; DPP reranking
Visibilityvisibility-filtering/, visibility-filtering-client/Allow / Interstitial / Drop
Labelingscarecrow/, botmaker/, botmaker-rules/, abuse-enforcement-service/, safety-label-user-agg/Event rules, account enforcement, post-to-account label aggregation
Understandinggrox/, clip/, media-model-proxy/, adult-content/, pnsfwmedia/, agatha/, bdsm/, user-cred-v2/Text and media classification, account scores, action sequences
Transparencyunder-the-hood/Aggregated reports of account and post labels
DocumentationREADME.md, docs/BIDIRECTIONAL_BOOST_CHANGE.mdSystem design notes and one recorded parameter change

The main languages are Scala, Rust, Python, and Java, with smaller amounts of Strato and Thrift. phoenix/ includes training, serving, and synthetic data, and can be used to reproduce one training and inference run independently.

2.2 What the repository does not include

The official README states the following boundaries:

  • Some Grox LLM prompts (.j2 files) are unpublished.
  • Some botmaker rules are unpublished. The README gives the reason as reducing the risk of targeted circumvention.
  • Deployment, cluster orchestration, internal telemetry, and production data pipelines are mostly absent.
  • Thresholds in BDSM sink_policy.yaml are rewritten to 9.99. Follower-count floors in abuse-enforcement-service are replaced with placeholder values. Those files describe the mechanism. They are not production thresholds.

This report can therefore describe the default Home Mixer pipeline, the scoring formula, the visibility-rule table, and how published labels are consumed. It cannot claim to exhaust every path by which a post receives a given label.

2.3 Method

  • The two Home Mixer pipelines are used as the spine. Source is read along the call chain.
  • Numeric values are repository defaults, cited by parameter name.
  • Intermediate claims that disagree with source are resolved in favor of source. Limits are listed in section 10.

3. System structure

3.1 Design principles

The official README states five design principles. The source is consistent with them.

  1. Multi-action prediction. Phoenix emits a set of action probabilities plus a dwell-time regression. Combining them into one score is a separate weighted sum.
  2. Candidate isolation. In the ranking transformer, candidates cannot attend to one another. They read only viewer context. A candidate’s score does not depend on which other candidates are in the batch, so scores can be cached.
  3. Hash and semantic-ID embeddings. Retrieval and ranking do not maintain a closed vocabulary. A new post can be represented immediately. The production retrieval tower uses residual-quantized semantic IDs (6 levels × 256 codes) and hashed author IDs. It does not use a learned per-user ID embedding.
  4. Ranking and visibility are separate. They use different services, different inputs, and different rules.
  5. A composable pipeline. candidate-pipeline/ separates source, hydrator, filter, scorer, selector, and side effect. Stages can run in parallel and can be toggled independently.

3.2 Two paths

Request path                                 Labeling path (continuous)
────────────                                 ──────────────────────────
Home Mixer                                   grox / clip / media-model-proxy
  ├ PhoenixCandidatePipeline                 agatha / bdsm / user-cred-v2
  │   retrieve → filter → score → Top 50     scarecrow + botmaker
  │   → visibility filter → filter again     abuse-enforcement-service
  └ ForYouCandidatePipeline                  safety-label-user-agg
      posts + ads + Who to Follow + prompts  written to storage, read by VF on request

The request path decides the order of this response. The labeling path decides which labels a post or account carries. Labels do not rewrite Phoenix scores. They can remove a candidate before or after scoring.


4. Request path

The entry point is ForYouCandidatePipeline. Its first candidate source, ScoredPostsSource, runs the full PhoenixCandidatePipeline, converts selected posts into FeedItems, and blends them with ads, Who to Follow, prompts, and other items.

4.1 Query hydration

Before any candidate source is queried, PhoenixCandidatePipeline hydrates viewer-side features in parallel. Items registered in phoenix_candidate_pipeline.rs include:

  • Two User Action Aggregation sequences, one for ranking and one for retrieval (ScoringSequenceQueryHydrator, RetrievalSequenceQueryHydrator)
  • Block, mute, follow, and subscription lists
  • Redis-cached posts
  • Mutual-follow relations
  • Demographics, inferred gender, installed apps
  • Followed Grok topics and Starter Packs
  • Explicit and implicit engagement signals
  • Impression Bloom filter, IP, and geography

ImpressedPostsQueryHydrator is constructed but is not inserted into the query_hydrators vector. Already-seen posts are handled mainly by the Bloom filter, by exclusion in the Thunder request, and by the later PreviouslySeen* and PreviouslyServed* filters.

Candidate sources are queried only after these features are ready.

4.2 Candidate sources

The code registers seven sources. Thunder, Phoenix, SimClusters, and the cache source are enabled by default.

SourceDefault switchDefault capServed typeRole
ThunderSourceAlways registered1200ForYouInNetworkIn-network posts from the in-memory PostStore, using the follow list with already-seen tweet IDs removed
PhoenixSourceEnablePhoenixSource = true1000ForYouPhoenixRetrievalOut-of-network nearest neighbors from the retrieval-sequence embedding
SimclustersSourceEnableSimclustersSource = true800ForYouSimclustersCosine approximate nearest neighbors on LOG_FAV embeddings of the viewer’s engagement-signal posts; maximum age 48 hours
TweetMixerSourceEnableTweetMixerSource = false800Off by default
PhoenixTopicsSourceUsed on topic requests1000Topic retrieval
PhoenixMOESourceEnablePhoenixMOESource = false200ForYouPhoenixRetrievalMoeOff by default
CachedPostsSourceEnableCachedPosts = trueReuses the previous request’s cache

Thunder supplies in-network candidates. Phoenix and SimClusters supply out-of-network candidates. SimClusters also requires post-level engagement signals on the request; otherwise that path returns empty.

4.3 Candidate hydration

After retrieval, features are attached in order: in-network flag, mutual follow, TES text and author, quote, media, subscription, Gizmoduck account data, whether the author has blocked the viewer, filtered topics, language, engagement counts, semantic ID.

These fields are consumed by later filters and scorers.

4.4 Pre-scoring filters

The filter order in phoenix_candidate_pipeline.rs is as follows. The order is part of the semantics.

OrderFilterRemoves
1DropDuplicatesFilterThe same post returned by more than one source
2CoreDataHydrationFilterPosts whose text or metadata failed to load
3AgeFilterPosts older than MAX_POST_AGE (48 hours)
4SelfTweetFilterThe viewer’s own posts
5OONRetweetReplyFilterOut-of-network reposts and replies, and replies whose parent is missing
6OONNsfwSimclustersFilterPosts whose ServedType is ForYouSimclusters, whose author has an NSFW flag, and whom the viewer does not follow
7RetweetDeduplicationFilterRepeated reposts of the same original
8IneligibleSubscriptionFilterSubscriber-only posts the viewer has not subscribed to
9–11PreviouslySeen* / PreviouslyServed*Already-seen or already-served posts
12MutedKeywordFilterPosts matching the viewer’s muted keywords
13AuthorSocialgraphFilterPosts from authors the viewer has blocked or muted
14VideoFilterVideo posts when the request excludes video
15TopicIdsFilterPosts outside the requested topics on a topic request
16NewUserMinEngagementFilterLow-engagement out-of-network posts under the new-account condition
17InventoryHoldoutFilterInventory held out by a deterministic sample over post and viewer

Two points need a separate note:

  • OONNsfwSimclustersFilter applies only to the SimClusters source. Out-of-network originals from NSFW-flagged authors that arrive via Thunder, Phoenix, or the cache are not removed by this pre-filter. They may still be dropped by out-of-network visibility rules.
  • Subscriber-only content is already removed at this layer. DropExclusiveTweetContentRule in visibility filtering further restricts exclusive content: only the conversation author, a super-follow viewer, or a non-repost author may pass.

4.5 Scoring

Three scorers run in sequence.

  1. PhoenixScorer calls PredictNextActions (return_logprob: true) and writes the heads into phoenix_scores. This step does not compute a weighted score.
  2. RankingScorer applies the weighted sum, offset, author diversity, out-of-network discount, and new-author lift, and writes candidate.score.
  3. VMRanker sends a request with DPP context to vm-ranker/. If the service has DPP enabled, only the greedily selected subset keeps its original score; the rest are set to 0. Otherwise the scores are returned unchanged.

Home Mixer sends value_model_id = "dpp" by default, with theta = 0.65 and max_selected_rank = 150. The vm-ranker CLI default for --dpp-enabled is false. The repository does not state whether the production process passes that flag.

4.6 Selection, visibility, and blending

  • TopKScoreSelector keeps 50 posts by descending candidate.score (TOP_K_CANDIDATES_TO_SELECT).
  • After selection, VFCandidateHydrator, VFFilter, AncillaryVFFilter, and DedupConversationFilter run.
  • Posts whose visibility result is Drop are removed. Posts whose result is Interstitial remain in the timeline. This repository does not contain the interstitial UI.
  • If an ancestor, quoted post, or reposted post was dropped, AncillaryVFFilter removes the current post.
  • DedupConversationFilter collapses extra branches of the same conversation.
  • There is no rescoring after visibility filtering. On-screen position can differ from score rank.

The outer ForYouCandidatePipeline uses BlenderSelector to insert non-post items:

ItemDefault position or behavior
AdsDefault partition_organic_low_risk, handled by PartitionOrganicAdsBlender; organic posts may be reordered for ad adjacency
PromptPosition 0
Who to FollowPosition 6
Feed surveyPosition 12
Push-to-home, Jetfuel framesSeparate insertion logic

The organic result-size constant is RESULT_SIZE = 35. Ads and module slots are added separately, so one response can contain more than 35 slots.

After selection, the framework records served history, ad, client, and Kafka events, and refreshes the post cache, via tokio::spawn. That async work may overlap URT serialization. Served records become pre-filter inputs on later requests.


5. Scoring

5.1 Phoenix ranking model

phoenix/ is trained in JAX and served over Rust gRPC. The ranking model is a transformer:

  • Inputs are the viewer’s recent action sequence and the current candidates.
  • Outputs are a set of action logits per candidate, plus a dwell-time regression.
  • Candidates cannot attend to one another. They read only viewer context.
  • Embeddings use multiple hashes and semantic IDs. A new post does not need to enter a closed vocabulary.

Retrieval is a two-tower model. The user tower reads action history. The production configuration also includes country, language, and other profile tokens. It does not include a learned per-user ID embedding. The candidate tower reads semantic IDs and hashed author IDs. Retrieval takes Top-K by dot product. The index is stored in the checkpoint and updated from events by phoenix-rankall/. phoenix-rankall-strato/ decides which index a post enters and queries visibility filtering before insertion.

Home Mixer requests return_logprob: true. The serving side fills top_log_probs = log_sigmoid(logits). The prediction client that writes those values into PhoenixScores.favorite_score and related fields is not in this repository. The official README states the formula as a weighted sum of probabilities. If the client passes log-probabilities through unchanged, the numeric scale changes. Relative weight magnitudes still hold. This report follows the official README and RankingScorer::apply(score, weight) = score * weight.

5.2 Default weighted formula

ValueModelMode defaults to weighted. RankingScorer computes:

raw = Σ_i  weight_i × P̂(action_i)
score = offset_score(raw)

offset_score adds 0.001 when the value is non-negative. Negative values are mapped into the interval (0, 0.001). Author-diversity and out-of-network factors are applied next. The new-author lift runs last.

EnableMpnScoring defaults to false. When it is on, diversity and out-of-network factors apply only to a positive net value. A negative net value is not scaled. dwell_regret_sigmoid and gated_dwell_regret are a different formula that modulates dwell by within-batch relative position. They are not the default path.

5.3 Default weights

Source: home-mixer/params/param.rs. The file is annotated as mirrored from config feature-switch defaults; last sync 2026-08-12T04:09:22Z.

Positive and zero-weight terms:

Predicted actionParameterDefault weightRelative to FavoriteWeight
Share via copy linkShareViaCopyLinkWeight20.040
ReplyReplyWeight5.010
QuoteQuoteWeight5.010
Share via DMShareViaDmWeight5.010
Follow authorFollowAuthorWeight4.08
Share (generic)ShareWeight2.04
RepostRetweetWeight1.02
LikeFavoriteWeight0.51
Open postClickWeight0.40.8
Open linkOpenLinkWeight0.20.4
Expand photo, open video, video quality view (VQV), click quoted postcorresponding *Weight0.050.1
Continuous dwell (seconds)ContDwellTimeWeight0.004
Unexplored postPostUnexploredWeight0.02In-network only; additive by default
Click dwell, quoted VQV, profile click, binary dwellcorresponding parameters0.0Not in the default weighted sum

Negative terms:

Predicted actionParameterDefault weightAbsolute ratio to FavoriteWeight
Not dwelledNotDwelledWeight−0.020.04
Block authorBlockAuthorWeight−31.262.4
Not interestedNotInterestedWeight−43.286.4
Mute authorMuteAuthorWeight−58.8117.6
ReportReportWeight−234.0468

Weights are not multipliers on engagement counts. The model predicts the probability that the current viewer takes each action on the current candidate. A post with a high existing engagement count can still receive a low weighted score if the model assigns low probability to positive actions and high probability to negative actions for this viewer.

5.4 Mutual-follow boost

This applies only when the candidate is original (not a reply and not a repost) and is_mutual_follow_author == true:

  • Reply weight is increased by BidirectionalFollowReplyWeightBoost, default 15. The effective reply weight is then 5 + 15 = 20.
  • Dwell weight is increased by BidirectionalFollowDwellWeightBoost, default 0. That boost was experimented with and was not enabled as the default main path.

docs/BIDIRECTIONAL_BOOST_CHANGE.md records the July 2026 experiment: values 5, 10, 15, and 20 were tested; on 13 July, 20 was expanded to a larger set of users; on 24 July it was changed back to 15. The document’s stated reason is that some users saw less discussion from accounts they did not follow during a large public event.

5.5 Author diversity

EnableAuthorDiversity defaults to true. Candidates are first ordered by the pre-diversity score. Let k be the number of times the same author has already appeared (the first post has k = 0):

multiplier(k) = (1 − floor) × decay^k + floor

Defaults are decay = 0.5 and floor = 0.25. The corresponding multipliers are:

Position among that author’s posts in the resultkMultiplier
1st01.00
2nd10.625
3rd20.4375
4th30.34375
further→ ∞→ 0.25

The formula is not 0.5^k clipped at 0.25. The second post’s multiplier is 0.625.

5.6 Out-of-network discount

After the weighted sum, diversity, and cold start:

  • Out-of-network posts are multiplied by OonWeightFactor, default 0.75.
  • EnableOonRescoreForInNetworkRepliesRetweets defaults to true, so in-network replies and reposts are also multiplied by 0.75.
  • Topic requests use TopicOonWeightFactor, default 0.5.
  • The extra factor NEW_USER_OON_WEIGHT_FACTOR = 0.00001 is used only when account age is below NewUserAgeThresholdSecs and the viewer follows at least five accounts. That threshold defaults to 0. Under repository defaults, this branch usually does not run unless production overrides the age threshold to a positive value.

On the default path, the same original post therefore receives a higher multiplier as an in-network candidate than as an out-of-network candidate, and a higher multiplier than as a reply or a repost.

5.7 New-author lift

EnableViewerColdStart defaults to true. Each request adjusts at most one eligible original:

  • Not a reply and not a repost
  • Author follower count at most ColdStartFollowerCap (1000)
  • View count below ColdStartImpressionThreshold (1000)
  • Rank among non-zero scores below LowImpressionsMaxPositionRatio (0.85)
  • Score is replaced with max(score, target), where target is a score drawn at random from the interval [ColdStartSlotMin, ColdStartSlotMax) = [15, 16) after ranking

The rule applies to at most one original per request. It does not apply to replies or reposts.

5.8 DPP reranking

vm-ranker/ uses a determinantal point process over embeddings, trading off score against dissimilarity to neighboring candidates. The greedily selected subset keeps its original scores. The rest are set to 0. The later Top-K step then drops the zeroed candidates. As a result, some high-scoring candidates that are close in topic to others may leave the selected set.


6. Visibility filtering

6.1 Outcomes

visibility-filtering/ returns one of three outcomes for a (viewer, post) pair:

  • ALLOW: show normally
  • INTERSTITIAL: keep in the timeline; the client draws an interstitial (for example adult or graphic content)
  • DROP: Home Mixer removes the post

Rules are evaluated in registration order and short-circuit. The first rule that returns Drop ends evaluation.

In-network uses TimelineHome. Out-of-network uses TimelineHomeRecommendations. The latter contains all of the former’s drop rules and adds a set of recommendation-only drop rules.

6.2 Rules that drop on both surfaces

base_home_rules() includes:

  • Author suspended, deactivated, erased, or offboarded
  • Protected account that the viewer does not follow
  • Viewer blocks the author, mutes the author, or mutes reposts
  • Exclusive content the viewer is not entitled to see
  • Post labels: PDNA, BOUNCE, SPAM, FOR_EMERGENCY_USE_ONLY
  • FOSNR: hateful conduct, violent speech, abuse, civic integrity (the author is usually exempt; the emergency-use label is not)
  • Nullcast, stale edits, legal or local-law takedowns
  • Sensitive-media gates for logged-out viewers, underage viewers, or viewers with no stated age

The same set also registers interstitial rules for high-precision NSFW, gore and violence, NSFW card images, and NSFW authors. On the out-of-network surface, later drop rules hit some of those cases first. See the next subsection.

6.3 Rules that drop only on the recommendation surface

timeline_home_recommendations_policy() adds:

  • DMCA media and geo-restricted media
  • NSFW user/admin flags on the author or the post
  • Post labels: NSFW high recall, NSFW high precision, gore-and-violence high precision, NSFW card image, NSFW text, DO_NOT_AMPLIFY, malicious URL, SPAM high recall, FOSNR insults (out-of-network only)
  • Author labels: NSFW high recall, NSFW high precision, NSFW near-perfect, NSFW avatar, NSFW banner, SPAM high recall, compromised, read-only, high-precision impersonation
  • User-side ABUSIVE_HIGH_RECALL and DO_NOT_AMPLIFY: drop only when the viewer does not follow the author

A post with high-recall spam or high-precision NSFW labels can therefore appear on a follower’s home timeline and still be withheld from For You recommendations to non-followers.

Repository tests show that EGREGIOUS_NSFW and RECOMMENDATIONS_BLACKLIST have been removed from the drop rules. Those names alone no longer drop recommendations.

6.4 Where labels come from

Labeling systems run continuously. They are not on the request hot path.

SystemInputOutput
grox/Text and media at publish timeClassifications such as spam, adult, and violence, plus text and image representations
clip/Image–text pairsMedia embeddings for downstream classifiers
media-model-proxy/Images and videoXxNsfw, violence and gore, hateful symbols, fingerprinting and categories. The repository has no in-service model named AdultContent. disable_adult_content_v1 is an unused decider
adult-content/, pnsfwmedia/Training and calibrationAdult-media classifiers. The latter combines CLIP embeddings with Agatha calibration scores
agatha/Block, report, and like ratios on an account’s postsOffline account labels, including spam and adult
bdsm/Account action sequencesSigns of inauthentic or abusive behavior; may write labels such as enforcement_threshold_reached
user-cred-v2/PageRank over the follow graph and engagement edgesAn account score in 0–100. The score itself is not a visibility drop rule
scarecrow/, botmaker/, botmaker-rules/Real-time eventsLabels written when conditions hold. Some rules are unpublished
abuse-enforcement-service/Model scores, not individual eventsFirst matching YAML rule: skip, write SpamHighRecall with a 30-day TTL, write RiskyHighVizReply, challenge or liveness check, or suspend
safety-label-user-agg/Post-level safety labelsAggregated account-level labels

The structure of enforcement_user.yaml is: skip on allowlist, high follower count (the floor is a placeholder), cred.is_high, or score ≥ 50; otherwise act on BDSM, slop, majority-poster, and related labels. The file header states that the file is mirrored from GrowthBook. Production CEL or dynamic configuration may differ.

Labels that Scarecrow or Grox write, but that the published visibility-rule table does not read, include AGATHA_SPAM, AGATHA_SPAM_TOP_USER, SEARCH_BLACKLIST, UNSAFE_URL, COPYPASTA_SPAM, and RISKY_HIGH_VIZ_REPLY. They may affect Search or other surfaces, or act indirectly through unpublished rules. This repository alone does not show that they independently drop a For You post.


7. Other subsystems

The following directories do not compute the For You score. They affect whether a candidate enters the retrieval pool, which features it carries, or how it is explained after the fact.

  • thunder/: consumes new posts from Kafka, stores them in an in-memory PostStore, and returns them by follow list. In-network freshness and capacity are determined here.
  • simclusters/: Scala. Clusters accounts and posts by engagement. The approximate-nearest-neighbor service is in simclustersann/.
  • phoenix-rankall/ and phoenix-rankall-strato/: maintain the retrieval index. Visibility filtering is queried before insertion. A post dropped by visibility filtering should not enter the out-of-network retrieval pool.
  • candidate-pipeline/: a generic orchestration framework. Home Mixer is a business instance of it.
  • under-the-hood/: daily jobs collect visibility-affecting labels on accounts and posts; the serving layer aggregates them over a period. The product entry point is x.com/i/under_the_hood.

8. Experiments and configuration

Most weights and switches are read from feature switches rather than hardcoded as literals in the logic. The repository uses scheduled jobs to write primary production values back into param.rs. The README states that experiments at a notable share of traffic (for example 10% or more) are intended to be visible in the repository.

Therefore:

  • Numbers in this report are the primary-path defaults recorded in the repository. They are not constants that hold for every viewer.
  • The mutual-follow reply boost moved through 0, experimental values 5/10/15/20, a broader rollout of 20, and a change back to 15. Weights change with experiments and product decisions.
  • EnablePhoenixSource, EnableSimclustersSource, the ads blender type, and ValueModelMode can all be switched by viewer cohort.

When reading the repository, the defaults can be treated as the current primary hypothesis, and diffs to param.rs as a log of algorithm changes.


9. Implications for creators

This section states only consequences that follow directly from the source. They are descriptions of mechanism, not an operating playbook.

9.1 Conditions for entering the candidate set

  1. AgeFilter and the 48-hour SimClusters cap jointly define For You eligibility. A post older than that window does not enter this pipeline. It is not kept and down-weighted.
  2. Already-seen or already-served posts are removed by pre-filters. A later request from the same viewer will not select the same post again.
  3. A viewer’s own posts do not appear in that viewer’s For You. An author viewing their own post is not a distribution signal.
  4. Subscriber-only or exclusive content does not enter For You for non-subscribers. Distribution to non-subscribers requires an original root post without a subscription wall.
  5. Out-of-network reposts and replies are removed before scoring. The unit of distribution to non-followers is the original root post.

9.2 Weighted score versus existing engagement counts

Default weights are the relative contribution of each predicted action to the combined score. They are not a statement of preferred content form.

Predicted actionDefault weight
Share via copy link20
Reply, quote, share via DM5 each; 5 + 15 = 20 for reply when a mutual-follow viewer sees an original
Follow author4
Like0.5
Profile click, binary dwell0

From the table:

  • Share via copy link, reply, quote, share via DM, and follow author contribute more to the default weighted score than like.
  • The mutual-follow boost applies only to original root posts. A reply under the author’s own post and a reply under someone else’s post do not use the same weight.
  • The default like weight is low. Existing like count is also not a ranking input.
  • The default profile-click weight is 0. Bio, highlights, and outbound links can affect follow conversion. They do not enter the default For You weighted sum.

9.3 Negative terms

Under the default weights, the absolute value of report is 468 times that of like. Mute, not interested, and block are also much larger in absolute value than like.

The model predicts the probability that the current viewer takes those actions. It does not predict the post’s global controversy.

Out-of-network recommendations read an additional, wider set of safety labels. NSFW, high-recall spam, malicious URL, DO_NOT_AMPLIFY, and similar labels can remove a recommendation after ranking. Content that can still appear on a follower’s home timeline is not thereby eligible for For You recommendation.

Account-level labels (high-recall spam, NSFW avatar or banner, read-only, impersonation, compromised) apply to later recommendations from that account, not only to a single post. Avatar and banner also appear in the out-of-network drop rules.

9.4 Form and spacing of posts

  • In one request result, an author’s second post is multiplied by 0.625, the third by about 0.44, with a floor of 0.25. When several posts from the same author enter the same viewer request in a short interval, later items are scaled down by that formula.
  • In-network replies and reposts are multiplied by 0.75 by default. Out-of-network replies and reposts are removed before scoring. On the default path, an original root post receives a higher applicable multiplier than a reply or a repost.
  • Expand photo, open video, and video quality view have a default weight of 0.05. Continuous dwell has a default weight of 0.004 per unit. Media is not the main term in the default weighted sum.
  • If DPP is enabled, some high-scoring candidates that are close in topic are set to 0 and leave the Top 50.

9.5 New-author lift and account score

  • An original from an author with at most 1,000 followers and fewer than 1,000 views on that post may be lifted to around position 15. At most one post is treated per request.
  • When user-cred is at least 50 or cred.is_high is set, abuse-enforcement-service may skip later automatic enforcement. That score is not added to the For You weighted sum. It comes from PageRank over the follow graph and engagement edges.

9.6 Mechanism table

ActionCorresponding mechanism
Publish an original that can be shared via copy linkShareViaCopyLinkWeight = 20
Discuss under one’s own original with mutual followersReply weight is 5 + 15 when the post is original and the follow is mutual
Accumulate likesFavoriteWeight = 0.5; inauthentic behavior may also enter BDSM or abuse-enforcement-service
Publish several posts in a short intervalAuthor diversity decays from the second post
Reach non-followers via reply or repostOONRetweetReplyFilter removes them before scoring
Make the root post subscriber-onlyIneligibleSubscriptionFilter and exclusive-content rules keep it out of non-subscribers’ For You
NSFW labels on avatar or banner, with recommendation distributionOut-of-network user-label rules drop the post
Raise the predicted probability of not interested, block, or reportCorresponding negative terms are larger in absolute value than like
Post older than about 48 hoursAgeFilter removes For You eligibility
Infer ranking from existing like countRanking input is predicted action probability for the current viewer

9.7 Label lookup

Under the Hood aggregates visibility-affecting labels on accounts and posts. If recommendation distribution changes, the labels listed in section 6.3 can be checked there first. The repository describes the mechanism. The tool reports the labels currently attached to an account and its posts.


10. Limits

The following claims cannot be closed from this repository alone, or need to be qualified against the source:

  1. TweetMixer, Phoenix Topics, and MOE sources exist in the code. TweetMixer and MOE are off by default. Whether they are on for some viewers in production is not recorded.
  2. Whether PhoenixScores fields are probabilities or log-probabilities depends on the unpublished prediction client.
  3. Home Mixer sends DPP parameters. The vm-ranker CLI does not enable DPP by default. Whether the production process enables it is not recorded.
  4. NewUserAgeThresholdSecs defaults to 0, so the extra new-user out-of-network factor usually does not apply under repository defaults.
  5. There is no score-based rerank after visibility filtering. Ad blending can reorder remaining organic posts. On-screen position need not equal score rank.
  6. Some labeling rules are unpublished. BDSM thresholds and the abuse-enforcement-service follower floor are placeholders.
  7. Labels such as AGATHA_SPAM are written but are not in the published visibility drop table.
  8. media-model-proxy does not serve a model named AdultContent. Adult-related capability is implemented through heads such as XxNsfw and through the training code in adult-content/ and pnsfwmedia/.
  9. The author-diversity formula is (1 − 0.25) × 0.5^k + 0.25, not 0.5^k clipped at 0.25.
  10. Whether the Following timeline uses the same 48-hour limit was not separately verified in the public source. The 48-hour window in this report applies only to the For You Phoenix pipeline.

11. Source index

TopicPath
Official overviewREADME.md
For You outer blendinghome-mixer/candidate_pipeline/for_you_candidate_pipeline.rs
Post-pipeline assemblyhome-mixer/candidate_pipeline/phoenix_candidate_pipeline.rs
Default weights and switcheshome-mixer/params/param.rs
Size constants (50 / 35 / 48 hours)home-mixer/params/config.rs
Weighted sum, diversity, out-of-network discounthome-mixer/scorers/ranking_scorer.rs
New-author lifthome-mixer/scorers/author_cold_start.rs
Mutual-follow boost change logdocs/BIDIRECTIONAL_BOOST_CHANGE.md
Visibility rule tablevisibility-filtering/rules/registry.rs
Enforcement user rulesabuse-enforcement-service/service-lib/rules/enforcement_user.yaml
Phoenix model notesphoenix/README.md
DPPvm-ranker/scoring/dpp_model.rs

This report is based on static source in the public repository. Live experiments, unpublished rules, and unsynced configuration overrides are defined by 𝕏’s production systems.