- Sources read: 2
- Canon files updated: 2
- Radar entries: 1
Other changes reviewed today:
- In the same X commit, the visibility-filtering service VF split the state-management logic out of data lookup and deleted two lookup function files.
- From the same commit, Cold retrieval candidates of Phoenix (X's Grok-based Transformer model) are shown only to the Treatment arm of the author cold-start experiment.
- The research-automation paper AgentX-Model reported acquisition +10-15%, ad spend +15-20%, and watch time +0.3-0.8% in five production A/B tests.
1A gate now blocks re-applying suspensions and labels that a human reviewer overturned — X
Source xai-org/x-algorithm@4c5cfe8 — 2026-09-26 commit, +9,130/−2,652, 80 files. These notes number X commits after the Gen4 release in order, and this commit is Gen4+30.
Background The X repository has published a snapshot commit roughly every day since Gen4 (first released 2026-08-13). Yesterday's commit (Gen4+29, bf7db1b) rewrote the hydration layer of VF from a function layer into a data table and a scheduler. Hydration is the stage that merges the data needed for rule verdicts (tweet text, safety label, social graph edges, etc.) from multiple backends. This commit continues that rewrite on two axes.
- On the abuse-enforcement side, a new precheck layer called the overturn-hold gate was introduced in
abuse-enforcement-service(AES below), X's internal enforcement dispatcher.- The introduced
overturn_hold_gate, 5,270 lines, appears as a single file,overturn_hold.rs. - This gate is the last door that, while a hold is valid, stops a suspension or label that a human reviewer overturned while handling an appeal from being applied again.
- It prevents the recurrence in which an account is suspended, released after the user's appeal is approved, and then suspended again by an automated follow-up verdict.
- The introduced
- On the VF hydration side, the state-management logic of
execute.rs(1,280 lines), introduced yesterday, was split today into a separate file,store.rs.- The data table and scheduler that resulted from yesterday's rewrite consisted of
plan.rs,execute.rs, andsources.rs. store.rsis a new file of 339 lines.safety_label_hydrator.rs(167 lines) andtes_hydrator.rs(79 lines) were deleted entirely.- All the function-based leftovers that remained through yesterday were removed, and the scheduler now references only the data table.
- The data table and scheduler that resulted from yesterday's rewrite consisted of
What we learnedA. The overturn-hold gate was introduced as an AES precheck
This gate is the last precheck before a suspension or a gated label is dispatched verified. The comment at the top of the file states the purpose in one sentence: it exists so that an enforcement a human reviewer already overturned on appeal is not applied again.
"Overturn-hold gate: the last precheck before a suspend (or a gated label) is dispatched. It exists so we do not re-apply an enforcement that a human reviewer already overturned on appeal." —
abuse-enforcement-service/service-lib/src/overturn_hold.rsThe gate runs in three modes, Off, Shadow, and Enforce, and the default is Off verified.
- The modes are defined as
GateMode::Off | Shadow | Enforce. - Shadow runs the verdict line but takes no actual action, recording only to metrics and the decision outcome.
- Enforce actually blocks the dispatch.
- The modes are defined as
There are two gate kinds, blocking suspension re-application and blocking label re-application verified.
- They are
GateKind::SuspendandGateKind::Label, respectively. - The two kinds correspond to the constants
HOLD_KIND_SUSPEND="suspend"andHOLD_KIND_LABEL="label".
- They are
Suspensions split into temporary and permanent, and a separate verdict flows for each suspension kind verified.
- A temporary suspension is
GatedAction::Suspendand a permanent suspension isGatedAction::PermSuspend.
- A temporary suspension is
The gate receives the list of active holds from a remote ledger service verified.
- An HTTP client reaches the ledger service at the
/v1/holds/lookuppath. - The connect timeout is 200ms.
- The positive cache is 60 seconds and can be tuned up to 3,600 seconds.
- The response body cap is 64 KiB.
- The maximum weight of the moka cache is 100,000, and the config publish interval is 15 seconds.
- An HTTP client reaches the ledger service at the
The circuit breaker opens after 5 consecutive failures and blocks requests for 10 seconds verified.
- Retry works by letting one request at a time through as a half-open trial.
- Separately, when reachable errors (for example, HTTP 5xx) occur 5 times in a row, this is mitigated with a 5-second back-off.
The gate is integrated at two points in lib.rs verified.
- At startup it builds the gate with
HoldGate::from_url(cfg.overturn_hold_ledger_url, ..., cfg.overturn_hold_env). Then it injectsArc<overturn_hold::HoldGate>intoEnforcementCtx. - On the execution path,
gated_actions(&specs, &cfg)picks out and returns only the gated actions (Suspend/Label) from the dispatch candidates. The type of the dispatch candidates isVec<ActionSpec>. strip_held_labels(&mut specs, &gate.strip_labels)removes the already-overturned label names from the spec list.
- At startup it builds the gate with
The verdict result is exposed as two status codes verified.
STATUS_HOLD_OVERTURNED = "hold_overturned"is the case where a hold is active and the action was actually blocked.STATUS_HOLD_LOOKUP_FAILED = "hold_lookup_failed"is the case where the ledger lookup itself failed.
The following diagnostic keys are carried in the same decision outcome dict verified.
overturn_hold_idindicates which hold matched.overturn_hold_modeindicates in which mode, off, shadow, or enforce, the verdict was made.overturn_hold_headis the head fingerprint of the ledger response.overturn_hold_expires_atis the hold's expiry time.overturn_hold_labels_strippedis the list of label names the label gate removed.
These diagnostic keys also enter the dedup retention layer verified —
abuse-enforcement-service/service-lib/src/lib.rs:2469-2501.- A dedup retention entry is newly set for each of the two statuses, so the duplicate-action removal pipeline treats the two statuses as separate slices verified — same file.
- The new entries are
dedup_retention_for(STATUS_HOLD_LOOKUP_FAILED)anddedup_retention_for(STATUS_HOLD_OVERTURNED).
- The new entries are
- A dedup retention entry is newly set for each of the two statuses, so the duplicate-action removal pipeline treats the two statuses as separate slices verified — same file.
What we learnedB. VF hydration split the running state into a separate struct and moved the follows lookup to the wingman service
A new struct that holds in-flight results during hydration execution was introduced verified.
- The struct is
Store, introduced by the new filestore.rs(339 lines, new). - It has the following 8 fields, all held as
Option<...>.pure_cores: the minimal skeleton of a tweettweets: TweetForVisibilitycontrols: ConversationControl armlabels: SafetyLabelMapviewer: ViewerProfileauthors: DecodedAuthoredges: socialgraph edge resultVec<(Hydrators, RawHydrationBatch<Hydrators>)>viewer_country: Arc<str>
- The struct is
The input keys that downstream hydrators need are extracted by the store along the origin axis verified.
- The function that does this is
Store::keys(origin: KeyOrigin) -> Vec<u64>. - Axes such as
KeyOrigin::RequestTweets,Viewer,ViewerForCoAllowedList,PureCoreAuthor,PureCoreReplyRoot, andExclusiveConversationAuthorare defined. - In yesterday's
plan.rs, thekeyofNodeSpec { source, part, key, label }was this origin. Now the store resolves the actual value for each origin on the execute path.
- The function that does this is
The
edgesfield is filled only with a subset of the set of hydrators executable in this request verified.Store::callable: Hydratorsholds this set as a bitset, locking theedgesfield so that it is filled only with that subset.
The follows relationship lookup moved from direct socialgraph calls to a separate service path called wingman verified.
- The
wingman_clientthat handles this lookup is the new fileclients/wingman_client.rs(54 lines, new).
const FOLLOWS_GRAPH: u32 = 1; const FOLLOWS_FLEET: Fleet<'static> = Fleet { wily_path: "/s/wingman/wingman-api-follows", authority_template: "wingman.wingman-api-follows.prod.{datacenter}.s2s.twttr.net", ... };- The
The wingman client's interface is only
batch_exists_intersect(viewer_id, root_author_ids), and the mode isIntersectMode::FwdXRevverified.- FwdXRev is the mode that checks the product of the forward viewer → author edge and the reverse author → viewer edge.
- This mode is used to check in a single RPC call whether "the reply root author and the viewer follow each other".
- From FOLLOWS_GRAPH being the constant
1, we can guess that wingman holds multiple graphs. Graph 2 and later are not yet in the public code.
Two hydrator files whose functions became unnecessary yesterday were deleted entirely in this commit verified.
- The two files are
safety_label_hydrator.rs(167 lines) andtes_hydrator.rs(79 lines). - Their functions became unnecessary yesterday when they were moved to the data-based scheduler, but the files remained for a 24-hour grace period.
- The two files are
What we learnedC. The VF rules layer was unified under a Policy struct, and a rules-only metrics module was added
The rules registry file was effectively rewritten entirely verified.
rules/registry.rschanged by +206/−203.
The VF rules layer was unified under a
Policystruct verified. The core is thePolicy<'a>struct, which holds the rule set of each SafetyLevel.pub(super) struct Policy<'a> { base: &'a [RuleClause], additional: &'a [RuleClause] } static FILTER_ALL_POLICY: Policy = Policy::new(&[tweet_rules::FILTER_ALL]); static TIMELINE_HOME_POLICY: Policy = Policy::new(&TIMELINE_HOME_SHARED_RULES); static TIMELINE_HOME_RECOMMENDATIONS_POLICY: Policy = Policy::with_additional(...); static TIMELINE_HOME_HYDRATION_POLICY: Policy = Policy::new(&[...]); static IMMERSIVE_EXPANDED_RECOMMENDATIONS_POLICY: Policy = Policy::new(&[...]);RuleEngine::select(level) -> &'static Policyreferences one of the 5 statics above for each requested SafetyLevel.Policy::with_additional(base, additional)is a tool that builds a derived policy by joining two slices.
Because policies became statics locked as data, golden tests can pin the policy specification directly verified.
- In the previous structure, the rules for each SafetyLevel were assembled inline inside functions.
- The function used for pinning is
wired_rule_names(level), which is actually used in the tests afterregistry.rs:346.
A metrics module dedicated to the rules layer was added verified.
- The new file is
rules/metrics.rs(58 lines, new). - Through yesterday, the hydration
metrics.rsalso held the metrics related to rule verdicts. As verdicts and hydration were separated, the metrics were separated too.
- The new file is
Incidentally, filter code shrank verified.
filter.rswas trimmed by −94 lines.- As the Verdict tree (introduced in Gen4+26, 2026-09-22) settled in, the filter no longer needed to control the rule execution flow directly.
What we learnedD. The targets of Phoenix ads purchase-value prediction were cataloged as 6 combinations of event and point in time
The event × level combinations for ads purchase-value prediction were stated explicitly as a data structure verified.
- The file is
phoenix/crates/serving/xai-recsys-proto/src/purchase_value.rs, rewritten with +230/−4.
pub const ACTION_INDEX: usize = ContinuousActionName::AdsWebCtPurchaseValue as usize; pub const MAX_EVENT_USD: f64 = 100_000.0; pub fn is_countable_usd(usd: f64) -> bool { usd.is_finite() && usd > 0.0 && usd <= MAX_EVENT_USD } pub enum ValueEvent { Purchase, ContentView, AddToCart } pub enum ValueLevel { ClickThrough, ViewThrough } pub struct ValueTarget { event: ValueEvent, level: ValueLevel } impl ValueTarget { pub const ALL: [ValueTarget; 6] = [ ... ]; pub const PUBLISHED: [ValueTarget; 4] = [ ... ]; pub const REQUIRED: [ValueTarget; 2] = [Self::PURCHASE_CT, Self::PURCHASE_VT]; }—
phoenix/crates/serving/xai-recsys-proto/src/purchase_value.rs- The file is
The ads purchase-value continuous head has 3 events × 2 points in time = 6 targets verified.
- There are three ValueEvents.
Purchase: conversion_type 2, clickhouse storage namepurchaseContentView: 19,content_viewAddToCart: 12,add_to_cart
- There are two ValueLevels.
ClickThroughis a conversion that occurs after an ad click, andViewThroughis one that occurs with only an ad impression and no click. - REQUIRED is the 2 targets the model must predict: purchase_ct and purchase_vt.
- PUBLISHED is the 4 webhook targets: purchase_ct, purchase_vt, content_view_ct, and add_to_cart_ct.
- is_countable_usd excludes an event from training and evaluation if a single event exceeds $100,000 USD. NaN, negative, and infinite values are also excluded.
- These constants (the 6/4/2 combinations) lock in as data which event × level is trained and which is only extracted and not exposed.
- There are three ValueEvents.
The ads purchase-value prediction layer, disclosed piecemeal in the three earlier commits, was unified today into a target catalog verified.
- Gen4+21 (2026-09-15,
ADS_WEB_CT_PURCHASE_VALUEintroduced) - Gen4+22 (2026-09-16, purchase-value loss formally connected)
- Gen4+24 (2026-09-18, purchase-value loss narrowed to the early-relabel slice)
- Gen4+21 (2026-09-15,
How the baseline field introduced in Gen4+21 holds the event × level axes is now settled in code verified.
- That field is the
PurchaseValueBaselinerequest field. ValueTarget::mean(&PurchaseValueBaseline)returns the mean for each of the 6 targets.
- That field is the
What we learnedE. In the author cold-start experiment, Phoenix Cold channel candidates are shown only to the Treatment arm
In the author cold-start scorer of home-mixer (the service that receives For You and Following feed requests), the served_type subject to arm-gating was expanded verified.
- In
home-mixer/scorers/author_cold_start.rs, theis_phoenix_moehelper was renamedis_arm_gated_retrieval.
fn is_arm_gated_retrieval(c: &PostCandidate) -> bool { matches!( c.served_type, Some( pb::ServedType::ForYouPhoenixRetrievalMoe | pb::ServedType::ForYouPhoenixRetrievalCold ) ) }- In
Starting today, Cold channel candidates are shown only to the Treatment arm among the Holdout/Control/Treatment arms of the cold-start experiment verified.
- That is, Cold channel candidates follow the same arm-gating rule as MoE retrieval candidates (served_type
ForYouPhoenixRetrievalMoe). - The new test
cold_retrieval_is_gated_like_moeverifies this. In Holdout and Control the Cold candidate score is 0, and in Treatment it remains at 5.0. - The Cold channel is the
HOME_COLD=13channel that was introduced in Phoenix retrieval in Gen4+28 (2026-09-24, 44d37eb) together withHOME_HOT=14verified —retrieval_dataset.py:280-281. - This channel had split the
1fav_1day.parquetsource with a fav<8 & views<500 mask.
- That is, Cold channel candidates follow the same arm-gating rule as MoE retrieval candidates (served_type
What we learnedOther changes
- The Phoenix async embedding CUDA layer shrank verified.
async_emb_api.ccis +123/−191, andasync_emb_comm.ccis +86/−63.- The gradient exchange API surface is being tidied in a more data-centric direction.
- Optimizer and trainer boilerplate shrank verified.
trainer_recsys.pyis +48/−200, androwwise_adagrad.pyis +51/−120.
- Two VF hydration files were adjusted slightly verified.
- They are
visibility-filtering/hydration/tes_composite.rs(+29/−32) andhydration/plan.rs(+48/−12). - The adjustment to plan corresponds to the addition of wingman.
- They are
- Dispatch was tidied to match the hydration and rules overhaul verified.
- The changed files are
visibility-filtering/server.rs(+35/−21),filter.rs(+26/−120), andevaluate_tweets.rs(+57/−51).
- The changed files are
Canon update Introduced a Gen4+30 subsection under the safety section of services/x.md and documented all of the following.
- The structure and constants of the abuse-enforcement overturn-hold gate
- The store/execute split in VF hydration and the move to wingman
- The Policy static form of the rules registry
- The Phoenix purchase-value target catalog
- The addition of the Phoenix Cold channel to cold-start
Why it matters Today's real headline is not VF but that abuse-enforcement introduced a human reviewer's overturn as a first-class citizen of the automated prechecks. This introduction suggests two things.
- The priority between automated verdicts and human verdicts is locked in as data.
- Previously, the problem of automated re-verdicts suspending an account again even after an appeal was approved was likely managed through policy and process.
- Now the code contains a last door that, whenever a suspension spec is created on the automated dispatch path, checks through a hold ledger lookup whether "this action has already been canceled by a human" and gates it.
- This recurrence prevention became an explicit code path.
- The cancellation of a suspension is treated as a "persistent state".
- A hold is a time window with an expiry time (
expires_at). During that window it blocks automated actions against a specific target, and the target is an account or a label. - In other words, a human reviewer's approval of an appeal becomes a policy item of "no re-application until time T" rather than a "one-time cancellation".
- In Gen4+13 (2026-09-01) there was a policy file refactor, and in Gen4+26 (2026-09-22) the binary verdict tree was introduced. Overturn-hold is an enforcement state-management layer placed on top of them.
- That dedup retention treats the two statuses (hold_overturned, hold_lookup_failed) separately also implies a need for after-the-fact auditing.
- A hold is a time window with an expiry time (
The VF overhaul repeats a 24-hour half-life pattern. safety_label_hydrator and tes_hydrator, which were functions through yesterday, were deleted today, and the state logic of execute.rs, introduced yesterday, was split into store.rs today.
2AgentX-Model automated the recommendation model research loop with two agents — arXiv
Source arXiv 2609.30001 — arXiv, 2026-09-24 v1, 37-page technical report. The title is "Advancing Model Research in AgentX: Long-Horizon Autonomy for Industrial Recommender Systems", and it has 23 authors.
Background This paper is not about an algorithm itself such as a new ranker or retrieval, but about a framework that automates the research loop that improves algorithms. The paper starts from the observation that the bottleneck of a production recommendation team lies less in the experiment ideas themselves than in the cycle of designing and running experiments and carrying the results into the next idea. Kuaishou, presumed to be the authors' affiliation, is not a tracked service, but the stated production scale and A/B figures are large, so it qualifies for radar inclusion. AgentX-Model in this paper composes this cycle with two agents.
- The Research Agent builds independently reviewed proposals from papers and earlier experiment results.
- The Model Agent turns those proposals into actual code and measurements.
- The Research Agent also formulates the next question based on the results.
What we learnedA. The author affiliation is presumed to be Kuaishou
- The author affiliation is presumed to be Kuaishou inferred. The v1 HTML version of the paper does not render affiliations.
- The 23 authors include Peng Jiang, Zhaojie Liu, and Wenwu Ou, and these three names are publicly in the Kuaishou line.
- Peng Jiang is a VP, Wenwu Ou moved from Alibaba to Kuaishou, and Zhaojie Liu is also at Kuaishou.
- The prior paper from the same team, AgentX v1 (arXiv 2603.xxxxx, "Towards Agent-Driven Self-Iteration of Industrial Recommender Systems"), has more well-known Kuaishou names such as Kun Gai and Han Li, so we infer that the codename "AgentX" refers to a Kuaishou internal framework.
What we learnedB. The research loop is split between the Research Agent and the Model Agent and organized into four actions
The architecture is a dual-agent structure of a Research Agent and a Model Agent verified. The paper's abstract is reproduced as is.
"AgentX-Model adopts a dual-agent architecture comprising a Research Agent and a Model Agent. The Research Agent develops independently reviewed proposals from papers and experimental findings, while the Model Agent conducts multi-round investigations and returns code, measurements, and unresolved questions. Using the returned results, the Research Agent selects a starting implementation and formulates the next research question, allowing subsequent experiments to build on earlier findings." — AgentX-Model abstract
- The research loop is organized into 4 actions.
- Reproduce: reproduces a prior experiment.
- Follow-up: extends on top of it.
- Composition: combines multiple techniques.
- Diagnose: collects the evidence needed to repair, for example, an issue found in online evaluation or a prediction bias measured by PCOC.
- The first three actions run routine research, and Diagnose covers diagnosis and repair-candidate selection when a problem is detected.
- The research loop is organized into 4 actions.
What we learnedC. In the latest 5 online A/B tests three metrics improved, and the paper states that the watch-time model cut FLOPs by about 10%
The paper states the production results in its abstract as follows verified.
"Across the production evaluation, 560 of 636 completed model-changing experiments recorded AUC above their business baselines. As research continued, some experiments recorded AUC above every comparable ancestor in their lineages. The five latest online A/B evaluations across different business settings reported gains including 10-15% in acquisition efficiency, 15-20% in target-segment advertising spend, and 0.3-0.8% in watch time; the watch-time model used approximately 10% fewer FLOPs and parameters." — AgentX-Model abstract
- Unpacked, the statement has three parts.
- Of the 636 model-changing experiments completed along the way, 560 (88%) had higher offline AUC than the business baseline.
- The latest 5 online A/B tests produced acquisition efficiency +10-15%, target-segment ad spend +15-20%, and watch time +0.3-0.8%.
- The watch-time model achieved this while cutting FLOPs and parameters by about 10%.
- The statement that the three business metrics (new user acquisition, ad spend, watch time) improved by +10-15%, +15-20%, and +0.3-0.8%, respectively, is quite large as a performance profile for an automated research framework.
- Unpacked, the statement has three parts.
What we learnedD. It also released a benchmark that evaluates research resource allocation
- The paper also releases a dependency-aware historical-replay benchmark. It evaluates research resource allocation, that is, which experiment to spend the next budget on.
- The initial result states that "when the agent already analyzes and selects concrete candidates, more complex scheduling does not give a consistent efficiency gain".
- In other words, the observation is that the quality of candidate judgment, not the scheduler itself, is the bottleneck.
Canon update Added AgentX-Model to the top of "new this month" in radar.md. Kuaishou is not a tracked service of the canon (this repository's canon documents), so no services canon file is created.
Why it matters The research-automation angle is the second case this repository has observed this month. However, the novelty of this source lies on the organizational axis, not on the ranking or retrieval mechanism axis, so it is far from the repository's main interest (the feed pipeline itself). We keep it as a deep dive candidate.
- The first case was the "37-day human-gated autoresearch campaign that caught the evaluator output-depth 3000/600 defect and recovered offline +3.20 pp" in Meta VDD MBR + EvoPilot (2026-09-22).
- If Meta's was the angle of automating search retrieval improvement, AgentX-Model (presumed Kuaishou) is the angle of automating the whole recommendation model research loop itself.
- It attaches as an observation thread because two companies publicly named automated research frameworks explicitly, one after the other, this month.
Radar
- Added AgentX-Model (presumed Kuaishou) as new this month.
What to check next
- Check what the overturn-hold ledger service actually is — the ledger the gate queries is a separate service, but this repository has no code for it.
- The path the gate queries is
/v1/holds/lookup. - How it connects to XReview (Gen4+14) and the UTH line (Gen4+19, +20, +23) is the next checkpoint to watch.
- UTH (Under the Hood) is a transparency tool through which users look up the visibility-impacting labels attached to their accounts and posts.
- The path the gate queries is
- Track the remaining graphs of the Wingman service — only
FOLLOWS_GRAPH=1was exposed this time. What to track is whether graph ID 2 and later hold other social relations (mute, block, quality) or form a separate fleet. - Find the webhook consumers of the Phoenix
ValueTarget::PUBLISHED4 targets — the clickhouse column names were settled this time, but which advertiser API actually consumes these 4 is outside the repository. If follow-up releases about the advertiser dashboard or the conversion API appear, fold them in. - Confirm the AgentX-Model affiliation — no affiliation appears in HTML v1. If v2, a conference acceptance notice, or a company blog post appears, promote [inferred] to [verified].