A close reading of xai-org/x-algorithm · Aug 2026

The Machine

Everything that happens to a post between the moment you hit send and the moment it lands, or doesn't, in a stranger's For You feed. This walks the whole open-sourced pipeline, and spends most of its time on the part nobody explains in plain language: the moderation engine that quietly decides your reach.

01 A post is born

A post is born

You hit send. Your tweet gets a snowflake ID, a 64-bit integer with the millisecond you posted baked into its high bits, so the number itself is a timestamp, and it lands in the store. As far as ranking is concerned, nothing has happened yet: no one has been offered your post, no score exists. But in the same instant a second pipeline wakes up and starts photographing it. This is the labeling path, and it runs whether or not a single human ever sees what you wrote.

It helps to hold onto one distinction for the rest of this, because the whole system is built on it. The released code splits into two halves that never quite touch. The request path is what assembles a feed when someone opens the app; it decides order. The labeling path runs continuously in the background, attaching invisible tags to posts and to accounts, and those tags decide something more fundamental than order: whether a post is allowed to be shown at all. A brilliant post with the wrong label is not ranked low. It is simply never a candidate. So we start there, with the machine that judges you before anyone gets a vote.

02 The labeling path · moderation

The labeling path

Six systems read what you posted, and not one of them is a person. There is a rule engine running thousands of little condition-action scripts, two separate models scoring whether your account is a spammer, a transformer that watches the rhythm of your behavior, an LLM reading your text and images, and a stack of vision classifiers. Any of them can pin a label on you, and the labels run the full range from "quietly hide this from strangers" to "this account no longer exists." What follows is the assembly line, walked in rough order of how badly each stage can ruin your day. It is worth noticing, as we go, how much of this machine is built not to catch you but to avoid catching the wrong people.

i · the rule engine

Most labels are applied by botmaker rules: little condition→action scripts run by a server called scarecrow. A rule watches for an event (a URL resolves, a tweet is pinned, a follow happens), checks conditions, and applies a label. They're first-match, and almost every one ends with the same four-line escape clause we'll get to. Your own report flagged exactly one of these: SPAM_HIGH_RECALL on one post.

rule 3226 · Tweet_Spam_High_Recall_..._Bad_URL_Sources

Fires when a link in your post resolves through a redirect chain to a domain the URL-reputation service dislikes. A verdict of exactly BAD applies SPAM (post removed from X entirely). Anything softer, LOW_QUALITY or a not-quite-BAD hop, applies SPAM_HIGH_RECALL: hidden from For You for non-followers, followers unaffected. One flagged post in a month, on a 30-day timer. botmaker-rules/…/Tweet_Spam_High_Recall.bot ↗

ii · agatha, the account reputation graph

agatha scores whether your account is a spammer, using pointwise mutual information over 21 different graphs: who you follow, fav, retweet, reply, mention, block, mute, and, less comfortably, Phonebook, Email, and your signup IP at /16 and /24 granularity. Subnet co-registration is a first-class spam feature: if a hundred accounts were born on your IP block, the graph knows.

Every agatha label is normalized per favorite. The unit of suspicion is reports_per_fav: how much people report or block you, relative to how much they like you. Cross a threshold like 0.9975 and you earn AGATHA_SPAM for a week. agatha/…/AgathaLabelManager.scala ↗

The mechanics

Agatha is pointwise mutual information between graph features and spam labels, but with a statistical safety net so rare co-occurrences don't scream. For a feature and a label it computes a variance-corrected PMI: the log-ratio of observed to expected co-occurrence, Bayesian-smoothed with a large pseudo-count and then given a confidence-interval haircut of z = 2 standard errors. Anything with |PMI| below 0.01 is dropped as noise.

PMI(feature, label) = log( corrected_P(feature ∧ label) ) − log( P(feature)·P(label) ) pseudo_counts = 10000, z = 2.0, drop if |PMI| < 0.01

The "reports per fav" you get labeled on is not a raw ratio either. It's smoothed toward a prior so a day-old account with one report and zero likes doesn't read as 100% spam:

reports_per_fav = (reports + s) / (reports + favs + s / prior), s = 0.1

And because one determined enemy shouldn't be able to sink you, each source account's contribution is a reservoir sample capped at 100, and your total feature mass is capped at 1000. The final "Blink" score per label averages the PMI moments against the prior and is then calibrated into a percentile across 1000 partitions, so scores are comparable between users.

iii · bdsm, the behavioral bot detector

Yes, that's what it's called in the tree: Behavioral inauthentic-account detection. Someone fought for that acronym. It's a transformer that reads your action stream, the raw sequence of everything you do, and decides if you're a bot. Its cleverest trick: time-aware RoPE, positional embeddings driven by the timestamps of your actions instead of their order, built explicitly to model "burstiness, mechanical cadence." Your rhythm is the fingerprint.

The mechanics

The backbone is a bidirectional transformer encoder, 8 layers wide at dimension 1024, with grouped-query attention, RMSNorm and a SwiGLU feed-forward, run over your last 512 actions. Ordinary RoPE rotates each token by its position i. Time-aware RoPE instead rotates it by a normalized timestamp, so two sequences with identical content but different timing encode differently. A CLS token is pinned at position zero and its output is what the heads read.

rotate(token_k) by θ_k = (impression_ts_k − ts_min) · base^(−2k/d), base = 10000 day_of_week = ((impression_ts // 86400) + 4) mod 7 // +4 because the Unix epoch was a Thursday

Every action becomes a fat vector: a 256-way action-type embedding, plus discrete features (client app hashed mod 512, a transition bigram of previous→current action hashed mod 8192, page, country, hour), plus continuous features each pushed through their own 2-layer GELU MLP (battery, brightness, storage ratio, dwell ratio, a burst count, a same-author streak, feed position), plus six booleans (is device charging, is this a promoted tweet, did you engage without it ever rendering), plus 18 sequence-level statistics computed on the fly:

action_entropy = Shannon entropy over your action-type histogram timing_regularity = 1 / (1 + std(gaps between actions)) // a metronome scores ~1.0 unique_ips, target_tweet_repetition, session_time_span …

Eight heads sit on the CLS embedding, each a 3-layer 512→256 MLP, trained with a masked sigmoid cross-entropy plus a symmetric reverse-CE term plus focal weighting (γ = 2) and label smoothing. Each head carries a hand-set training selection weight (LikeBot 60,320, FollowBot 27,576, RTBot 5,290), a sampling prior baked into the model. And the serving process refuses to start unless the backbone's SHA-256 matches a pinned hash, so a tampered model simply won't boot.

It watches a 256-slot action vocabulary that includes TAKE_SCREENSHOT, CLICK_GROK_ANALYZE, external-link dwell buckets, and roughly 120 slots of ad-conversion events. The bot detector sees your ad funnel. Eight "heads" each hunt a bot archetype: FollowBot, LikeBot, ReplySpamBot, and so on. But the thresholds that decide enforcement?

Redacted in the release

Every operating point in the shipped config is the sentinel 9.99, a value out of range for a probability, so it can never fire. Their stated reason: publishing the real numbers "would hand adversaries the detector's evasion boundary." A unit test even asserts the file hasn't quietly drifted back to real values. What ships is the machine, not its trigger points.

A few real numbers survived. Enforcement needs at least 30 actions. And a whole client_dwell_dropout subsystem exists to skip enforcement for people "whose dwell telemetry dropped out during the adblocker outage," with a comment stating plainly that these adblocker victims "are not bots." It fails closed: if the checker errors, assume dropout and spare them.

Get flagged and you don't always get suspended: you often get challenged. Which challenge you get is a salted CRC32 lottery on your user ID. The split is set by a CLI flag whose help text preserves a dated executive instruction: --challenge-liveness-per-10k = 9000 means 90% liveness / 5% arkose / 5% recaptcha, tagged "owner directive 2026-08-12," living in a command-line help string. Heavy posters, meanwhile, are structurally exempt from hard suspension: if more than half your actions are "create tweet," the hard-suspend gate can't trigger. bdsm/runtime/score_results_sink_focal.py ↗

The FollowBot head has three separate escape hatches, all shielding new accounts: under-48-hours-old is never enforced, seeing the login starter pack recently is a pass, and following any starter pack downgrades a suspension to a mere challenge. That last one comes with a measured, dated justification, straight from the comment: pack membership is common among legit users, a 21.8% base rate in follow-heavy legit-scored accounts as of 2026-07-15, "so challenge, never free-pass." And a separate lane will hard-suspend a reply-spammer only if ≥90% of their replies come from a first-party client, on the stated logic that legit API services post through third-party OAuth apps and never trip that gate.

Can you predict your challenge?

Partly, and here is exactly how much. The routing has two stages. The first decides whether you land in the 90% "liveness" bucket, and it is hashed with a secret salt the release does not ship, so it is opaque. But the second stage, arkose vs recaptcha for everyone else, ships unsalted: it is a plain CRC32 of your account ID. That coin is deterministic and computable right here. Type a @username or paste a numeric ID.

This reproduces exactly one line of the real function: ("arkose","captcha")[crc32(str(uid)) % 2]. What stays hidden is the salted liveness gate (needs the secret BDSM_CHALLENGE_SALT) and whether you are challenged at all (those thresholds are the redacted 9.99 sentinels). So the coin is knowable; whether it gets flipped is not. bdsm/runtime/score_results_sink_focal.py ↗

iv · grox, moderation by grok

An LLM (internally "grox") reads posts and replies against a taxonomy of 33 policy types across 10 categories, using models named, with a straight face, grok-420-reasoning-x-algo. A reply it spam-scores above 0.97 gets tagged RISKY_HIGH_VIZ_REPLY for 14 days.

The mechanics

How hard the LLM thinks about your post scales with how popular it is, and popularity is bucketed to the nearest power of two, so a post with 200 favs and one with 255 get the same treatment:

fav_bucket = 2^(bit_length(fav_count) − 1) cheap path: Gemma-26b // most posts deluxe path: fav ≥ 128 → grok-4.3-reasoning fav ≥ 1024 → grok-4.5-internal // the expensive model, only for the very popular

Child-safety is the one category that doesn't trust a single model: Gemma flags it first, then grok-4.5-internal has to independently agree, or the verdict is dropped to no-violation. Violent-speech and self-harm get chain-of-thought reasoning; spam gets the cheap Gemma. Each model sits behind a circuit breaker that trips at a 50% failure rate and recovers after 600 seconds. And the enforcement writer honors the same caste as everywhere else: high-PageRank and government-verified authors are exempt from most labels, except engagement-farming spam, which always labels.

The popularity tax

In its expensive mode, a post that crosses 128 favs and has media, but isn't already flagged, gets a synthetic adult-content violation injected to force a re-review, with the literal reason "high-fav adult content recheck". Getting popular is itself a trigger for suspicion. Popular posts also get routed to the reasoning model; everyone else gets a cheap Gemma pass.

Two account IDs are hardcoded to be skipped from reply-spam and coordinated-spam detection entirely: @grok and @gork. They are the only hardcoded accounts in the whole repository that change a moderation outcome. grox/core/constants.py ↗

v · the image stack, and your followers

Media runs through a shared CLIP embedding, then small classifiers for NSFW and gore. The NSFW model (pnsfwmedia) is the uncomfortable one: it decides whether your image is adult using the picture, your agatha score, and nsfw_consumer_follower_score, a signal inferring you post porn because porn-consumers follow you. Your audience is evidence against your pixels.

One asymmetry worth naming: the gore/violence image model is the single place where big accounts aren't auto-labeled. Instead they're routed to human review. Avatars and banners always are. Everyone small gets the automated verdict. pnsfwmedia/model_experimental.py ↗

vi · enforcement, where labels become consequences

The abuse-enforcement-service turns scores into actions via a first-match-wins rule file. There's a lane called llm_slop_user that tags accounts scored as LLM slop with SpamHighRecall for 30 days. There's a permanent-suspend lane for CSE. And the last rule in the file is a catch-all suspend with the condition "true": any score that survives to the bottom of the file suspends the account. That's how the bot detector's verdict becomes a suspension without any rule naming it. abuse-enforcement-service/…/enforcement_user.yaml ↗

vii · the tells

Reading this code closely, you catch the machine talking to itself. Three tells stand out.

They published fake numbers on purpose

The enforcement rules skip anyone above a follower floor of 12.34, an impossible fractional follower count. The comment next to it says the quiet part out loud: "Prod uses a different follower count floor; this is a mock value to reduce gaming." The real threshold was scrubbed and swapped for a nonsense placeholder before release, the same move as the 9.99 sentinels.

One specific user is whitelisted from an assertion

Deep in Agatha's scoring is a line that crashes the job if a score comes out NaN, "see ticket PFM-1435", except for exactly one account, identified by userId % 123456789 == 9470603. Somewhere there is a single real user whose broken score was easier to hard-code an exception for than to fix. agatha/…/BlinkScoreJobTemplate.scala ↗

And the asymmetry that says the most: at the very bottom of the enforcement files, an account with no matching rule defaults to suspend, while a post with no matching rule defaults to allow. The benefit of the doubt runs to content, never to the account. enforcement_post.yaml ↗

the escape clause

Here's that four-line ending nearly every rule shares. A post is only labeled if the author is not a test user, not high-PageRank, not on a manual skip list, and not government-verified. Toggle who you are and watch the machine lose interest:

SELECT YOUR CASTE →
high PageRank (score ≥ 54, or >25k followers)
government gray-verified
on the AutoExpiringTempSkipList
SPAM_HIGH_RECALL (bad URL)hidden from strangers
COPYPASTA_SPAMduplicate-text label
AGATHA_SPAMaccount spam label
RISKY_HIGH_VIZ_REPLY (grok)reply downranked 14d
NSFW auto-label (media)→ human review instead
bdsm hard suspendaccount suspended
You are a normal user. All six systems apply to you.

"Gray-verified" resolves to verified_type == "government". The high-PageRank test comes from user-cred-v2, an actual PageRank over the follow graph, whose uniform teleport prior is seeded exclusively from Premium subscribers. Buying a checkmark literally makes you a source of the algorithm's trust.

The mechanics of "high PageRank"

It's a real PageRank over the follow graph, damping α = 0.2, run until the mass vector stops moving (L1 change ≤ 0.001) or 50 iterations. Each round spreads mass along follows and reinjects the teleport plus any dangling mass:

mass' = incoming·(1 − α) + jumpMass teleport prior = (1 − β)·uniform + β·engagement, β = 0.5

The engagement half of the teleport flows mass to accounts you favorited or retweeted in the last 7 days, weighted by the engager's own mass, so trust propagates from the already-trusted. The uniform half, the democratic floor every account would otherwise get, is filtered to Premium and verified accounts only. That raw mass is then mapped to the score the moderation rules actually check:

cred_score = clip( 165.2 + 7.07·ln(mass), 0, 100 ) "high PageRank" (exempt from most moderation) = cred_score ≥ 54

Before a fresh snapshot replaces the old one, a safeguard rejects it if total mass drifts outside [0.99, 1.005] or the count of high-cred accounts moves more than 5%, so a corrupted run can't quietly de-trust everyone at once.

03 Building someone's feed

Building the feed

Switch sides. Someone you've never met pulls to refresh, and a feed is assembled just for them, from scratch, in the time it takes the spinner to turn. Nothing is precomputed; the For You timeline does not exist until it is asked for. And before your post can be ranked against anything, it has to be found, which is a harder bar than it sounds. Candidates come from three pools, blended together, and which pool you fall into decides almost everything about your ceiling.

in-network · thunder

Recent posts from accounts the viewer follows, held in memory. Hard cap: your last 50 originals is all a follower's feed can ever pull from you.

out-of-network · phoenix retrieval + simclusters

A two-tower model and the classic community-embedding system surface posts from accounts the viewer doesn't follow. The retrieval index is literally named 1fav_1day: posts with at least one like in the last day, about 28.7 million of them. A like is the entry ticket to being discoverable.

The new-user cliff

A constant sits in the config: NEW_USER_OON_WEIGHT_FACTOR = 0.00001. A young account that follows at least 5 people has its out-of-network candidates multiplied by one hundred-thousandth. For a new user, the feed is almost purely in-network. Cold start on X is brutal by design (though currently gated behind an age threshold set to 0).

04 Ranking: the transformer

Ranking

Every candidate that survives is handed to one model, Phoenix, and it is a genuinely large one: eight transformer layers, a model dimension of 2560, reading up to 1022 posts of your recent history alongside 64 candidate posts at once, trained on a hundred billion examples. For each candidate it does something narrow and specific. It predicts, as a probability, whether you in particular will take each of dozens of possible actions on it: fav, reply, retweet, quote, report, mute, screenshot, linger. Sixty-four of these predictions are discrete actions; the taxonomy runs past a hundred named events once advertising is folded in. Hold onto the word "predicts," because it is doing a lot of work here.

2560
model dimension
64
discrete action heads
100B
training samples

Candidate isolation: a block-sparse attention mask lets each candidate see your history but never the other candidates. So a post's score genuinely can't depend on what it's shown against. And the single most important fact in the whole release: every one of those heads is trained with equal weight (plain sigmoid cross-entropy, no per-action weighting). The model has no opinion that a reply matters more than a like. It just estimates probabilities.

The mechanics

Candidate isolation is enforced by the attention mask itself, not by anything downstream. The sequence is your history followed by the 64 candidates. Every position may attend to the whole history, but a candidate may attend only to itself:

query in history[i] → attends to history[0..i] query in candidate[j] → attends to all history + candidate[j] only // never candidate[k≠j]

Because no candidate can see another, the 64 scores are independent of each other and of batch order, which is what makes them safe to cache. Posts themselves aren't stored as one big learned vector. Since a "semantic ID" migration, each post is a short code produced by residual quantization, six levels deep, 256 options per level, trained by k-means over a 1024-dim multimodal embedding, and the transformer cross-attends to those code tokens.

semantic_id = RQ-KMeans(post_multimodal_embedding), 6 levels × 256 centroids

The sparse identity features (who, what, which author, which IP) hash into fixed-size tables, 100M rows for users, 100M for posts, 30M for authors, 10M for IPs, updated with rowwise AdaGrad at learning rate 0.2, while the dense weights use Adam. Retrieval, the step that even makes you a candidate, is a separate two-tower model whose only positive label is a favorite; its hard negatives are report, mute, block and not-interested; and it learns against 64 sampled "global" negatives per example with a learned temperature. Its candidate pool is the 1fav_1day index of roughly 28.7M posts.

It sees your phone's battery

Among the per-impression features feeding the model: inferred gender and score, DMA code, latitude/longitude, installed apps, and, genuinely, deviceBatteryLevel, deviceIsCharging, deviceBrightnessLevel, and free storage. Nobody designed these as signals. They're just fields the client already reports, thrown into a 100-million-slot embedding table, and 100 billion samples decided they moved a probability.

05 Scoring: the value model

Scoring

Here is the sleight of hand, and it is the most important thing in the entire release. The model from the last section has no opinions. It will tell you a post has a 4% chance of a reply and a 30% chance of a like, and it stops there. To turn those probabilities into a single number you can sort by, each predicted action is multiplied by a weight and the results are added up. Those weights are where every value judgment X makes about your feed actually lives, and they are not learned, not buried in a neural network, not hard to change. They are plain numbers in a config file that someone could edit over lunch. This is the real table:

Read it out loud: a like is worth 0.5, a reply 5.0, someone copying your link 20.0. One predicted report is −234: it cancels roughly 468 predicted likes. A mute (−58.8) is scored as nearly twice as bad as a block. The machine is terrified of the actions people take when they never want to see you again, and nearly indifferent to the like.

The mechanics

The blended number isn't simply the weighted sum. A post the model expects to be reported would score deeply negative and break the ordering, so negatives are folded into a tiny positive band instead: everything stays above zero, the doomed post just lands at the very bottom.

raw = Σ weight_i · P(action_i) score = raw ≥ 0 ? raw + 0.001 : (raw + negative_sum) / total_sum · 0.001 // squashed into [0, 0.001]

Then two multipliers. Author diversity discounts the k-th post from the same author in your slate, and a "clickbait" penalty scales down posts that get long click-dwell but few favorites:

author_diversity(k) = 0.75 · 0.5^k + 0.25 // 1st post ×1.0, 2nd ×0.625, 3rd ×0.44 … dwell_regret modulation = 2·sigmoid(pos/T)·exp(min(neg,0)/T), T = 10

Which of the two value models you get (the plain weighted sum or the harsher dwell-regret one) is decided per user by a 19-feature logistic gate. When your features land inside its hysteresis band, the tiebreak is a deterministic hash of your own account ID, so it's a coin flip, but always the same flip for you:

tiebreak = (user_id · 0x9E3779B97F4A7C15) & 1

One more quiet rule: if you have 10,000 or more followers, your video-quality-view weight is zeroed entirely. The signal that a big account's video was watched simply doesn't count.

Layered on top: author diversity decays the k-th post from one author to 0.5ᵏ (floored at 25%). Mutual-follow replies get a large additive boost (cut from 20 to 15 in July after World Cup complaints that feeds were all mutuals). And a clickbait penalty down-weights posts that earn long click-dwell but few favs.

There is a second, harsher value model

A per-user logistic gate (19 features, over a 28-day window) decides whether you're scored by the simple weighted sum above or by an alternate "dwell-regret" model. In that one the negatives are an order of magnitude larger: not-interested −10,000, block −8,000, mute −15,000, report −60,000. Whether a post lives or dies can depend on which value model a coin-flip on your user ID assigned you. home-mixer/params/param.rs ↗

06 Visibility filtering: the gate

The visibility gate

Ranking decided what order posts go in. This decides whether they appear at all, and it is where every label from the labeling path finally comes due. Visibility filtering runs 28 base rules, plus another 26 that apply only to out-of-network content, and each one turns a label into one of three verdicts: show it, drop it, or show it behind a content warning. The interesting thing is not that this exists but how finely graded it is: the same post can be visible to your followers, hidden from strangers, and invisible to a logged-out reader in a particular country, all at once. The tiers are the whole story.

"freedom of speech, not reach" (FOSNR)

The harshest tier, HATEFUL_CONDUCT, VIOLENT_SPEECH, ABUSE, CIVIC_INTEGRITY, drops the post for your followers too, on every surface. Only the author is exempt. Discoverability collapses to your own profile, and everyone sees a "limited visibility" notice. A softer tier (ABUSE_INSULTS) only hides from strangers.

NSFW age-gating · a 16-country list

Hardcoded: ar au br ca de es fr gb id it kr mx nl ph pt th. In those jurisdictions, a logged-in user with no stated age has sensitive content dropped. Everywhere else, no-stated-age passes. Your account_country_code beats your IP, so you can't dodge it with a VPN.

rules quietly switched off

The test files are named for it. EGREGIOUS_NSFW now allows on both surfaces "after rule removal." The classic Twitter-era RECOMMENDATIONS_BLACKLIST user label is now inert, the old "not recommendable" list no longer does anything in For You.

The mechanics

The rules are evaluated in order with a strict precedence: the first Drop wins immediately and nothing after it matters; an interstitial (content warning) is only recorded if it's the first one seen and nothing later drops the post. Drop always beats warn.

The NSFW thresholds are worth staring at, because they're inverted, the model emits a recall score where lower means more likely adult:

NSFW high-recall: score ≤ 0.8568428 (non-video) / ≤ 0.6 (video) NSFW high-precision: score ≥ 0.95 near-perfect: score ≥ 0.999 gore/violence: tweet image > 0.6, video ≥ 0.95, avatar/banner ≥ 0.85

Geography is resolved carefully to close the obvious loophole: your account_country_code is consulted before the country of your current request, so a VPN doesn't move you out of a gating jurisdiction. The sentinel "xx" stands in for "worldwide," and the age of adulthood is hardcoded at 18.

07 The report you're shown

The report you get back

This is the part X actually shows you: a transparency tool that reads back the labels on your account and your posts. Credit where it's due, it is real, and every effect it describes checks out against the code we just walked. But it is a curated window, not the whole room. The public dictionary it draws from lists 18 post labels and 12 account labels, each explained in plain English, and it lines up almost exactly with the visibility rules. Almost. The gap between what the code applies and what the report is willing to name is the last thing worth looking at.

Labels the code applies but the report never mentions

AGATHA_SPAM · COPYPASTA_SPAM · SEARCH_BLACKLIST · UNSAFE_URL · LOW_QUALITY. All applied by the shipped botmaker rules. None appear in the transparency dictionary. "This report is provided on a best-effort basis," as your own JSON puts it.

There's also a rule that mathematically cannot fire: an account-level NSFW aggregation configured to need 11 of your last 10 posts flagged. The config validator's ceilings are set to exactly permit the impossible, keeping the label "enabled: true" while disabling it by arithmetic.

So: was your reach limited? For one post, yes, a link the reputation service didn't trust, for 30 days, to strangers only. Your account is clean. But now you've seen the whole machine that produced that one line, and how much of it never shows up in the report at all.

08 Testing it against the real corpus

Checking the premises against reality

Reading the code tells you what the machine is supposed to do. Having a large archive of real posts lets you check the premises. These numbers come from a corpus of scraped tweets, one that skews toward posts with some traction, so read them as a floor: reality is more extreme, not less.

the retrieval gate is brutal

To be discoverable out-of-network, a post has to enter the retrieval index, and that index is 1fav_1day: posts with at least one like in the last day. On a single day of 11.2 million original posts, 33% got zero likes, so a third never qualify for out-of-network discovery at all, by construction. In the true firehose (most posts get no engagement) that fraction is far higher. The median post here gets 2 likes and 0 replies. Reach isn't taken from most posts; it was never offered.

where the algorithm's "value" actually comes from

A reply is weighted ten times a like. But replies are rare and likes are everywhere, so which one moves the aggregate? Summing the released weights across every retrievable post in that day:

55%
from likes
(weight 0.5)
22%
from replies
(weight 5.0)
14%
from retweets
(weight 1.0)
8%
from quotes
(weight 5.0)

Likes still supply the majority of total value despite the tiny weight, simply because there are so many of them. Replies punch to nearly a quarter off a far smaller count, which is the whole point of the 10× weight: reward the rare, expensive action. And raw like count correlates 0.92 with the full blended value, so "most-liked" is a strong proxy for "most-amplified", but not a perfect one. That last 8% is exactly where a reply-heavy or quote-heavy post leapfrogs a merely popular one.

can you predict the value model from content alone?

Partly. We trained a small model to predict per-impression rates for each action from a post's text and image, then blended them with the released weights to reconstruct the algorithm's own value number. On held-out posts it reaches a rank correlation of 0.458 against the realized value, about as good as older models did at predicting raw likes. The per-action breakdown is the interesting part:

retweet.53
like.52
reply.40
quote.36

Content predicts the lightweight reactions (retweet, like) far better than the conversational ones (reply, quote). That gap is the ceiling on any "will this go viral" tool: a like is mostly a reaction to the post in front of you, but a reply or a quote is a reaction to who said it and what's happening, which the pixels and the words can't see.

09 The whole machine

Every component, one line each

The open-source tree is every subsystem that touches your reach. Here is all of it, grouped by what it does, each linking to its code. The spicy constant is called out where there is one.

Try it Trace a post

Trace a draft through the rules

This can't run Phoenix (no weights, no semantic-ID codebook shipped). But the botmaker rules are legible, so this checks the same surface features they do: links, mentions, all-caps, duplicate-looking text. It's a caricature of the labeling path, not a verdict.

attaches an image
is a reply to a non-follower
account < 48h old
Heuristic emulation of the botmaker rule conditions (URL reputation, mention-to-non-follower, copypasta, all-caps ratio). The real system uses live reputation services, graph features, and models this page cannot see. Not affiliated with X.
10 Appendix: every reach-limiting label

Every label that can touch your reach.

Drawn from the visibility rules and the transparency map. Colour = severity. Click to expand trigger, effect, exemptions, and whether the transparency report will ever tell you about it.

all
reach-limited
hidden / removed
account-level
not in report