The single most important thing to get right about bot detection is that it is an adversarial problem, not a static classification problem. A spam filter trained once and left alone decays slowly. A bot classifier decays on purpose, because the people it classifies read its behavior and change theirs. On a platform with 500 million daily active users running one to two sessions a day, bots left unremediated would make up half or more of all actions, and even after simple heuristics cut that to under 1 percent, the detector still sits in front of billions of actions per day deciding, for each one, whether the account behind it is a machine.
Three constraints shape everything downstream. Compute is first order, because this system fronts nearly every interaction surface on the platform, so an expensive model run on every action is not an option no matter how accurate it is. Labels are scarce and delayed, because the only real ground truth comes from human investigators who can verify a few hundred accounts per week against a population of half a billion. And the data is unstable by construction, because every enforcement action removes evidence, teaches the adversary, and shifts the distribution the next model will train on. Most ML systems fight one of these problems. This one fights all three at once.
The design that falls out is a cascade with a memory. A distilled logistic regression clears the obviously legitimate majority in microseconds. A graph plus sequence model, GraphSAGE over a sampled two-hop neighborhood fused with a bidirectional GRU over the last 200 events, scores the suspicious remainder. Calibration turns raw scores into probabilities so that bans, limits, and demotions fire at bands that mean what they say. An ANN index of removed bot content gives the model a fast-updating memory that reacts to new campaigns without retraining, and unsupervised anomaly detection hunts for the bots no label has ever described.
Scope and requirements
The platform has 500 million daily active users running one to two sessions per day, which puts the action count, posts, likes, follows, messages, logins, in the billions per day. Left unremediated, bots would account for 50 percent or more of those actions. Simple heuristics already cut observed prevalence to under 1 percent, and that residue is the problem this system exists to solve, which means the easy bots are gone and everything the model sees has already survived a filter. Bot remediation usually pays for itself in compute, since the bot activity prevented costs more to serve than the detection costs to run, but that budget argument buys efficiency requirements, not a license to run a heavy model on every action.
Ground truth is the second defining constraint. Human investigators can manually verify whether an account is a bot, and they are reliable, but they process accounts in the low hundreds per week. Every other label source is a proxy with noise in it. The cost of errors is asymmetric in an uncomfortable way, because wrongly restricting a real user suppresses their engagement and pushes them into an appeals process that is expensive to staff, and bot operators navigate that same appeals process as competently as legitimate users do. Meanwhile the adversary adapts. Earlier bot generations sprayed requests at inhuman frequencies and died to rate heuristics. Current generations pace themselves, vary their content, and study what gets their accounts flagged.
The business objective is to minimize the impact of bot activity on legitimate users, subject to guardrails, and it is worth keeping that distinct from the ML objective. The business does not care about a bot account that never touches a real person, it cares about spam in inboxes, fake engagement in feeds, and misinformation in recommendations. The ML objective underneath is plain binary classification at the account level, bot or not bot, with the score consumed by an enforcement policy rather than shown to anyone.
Enforcement itself is a ladder rather than a switch. At high confidence the account is banned and its content removed. At middling confidence the system limits the account instead, capping how many friend requests or messages it can send and demoting its content in ranking. The ladder exists because of the asymmetry above. A limit applied to a real user is an inconvenience they may never notice, while a ban is a support ticket and a lost user, so limits let the system reduce the damage a missed bot can do without paying ban-level costs when the score is wrong.
The shape of the system
Production integrity systems grow layer by layer in response to real attacks, and the design mirrors that. Supervised models cover the bots we have seen before, and they can be tuned for high precision because their patterns are known. Unsupervised anomaly detection covers the bots we have not seen, the unknown unknowns that no label describes yet. A two-stage cascade covers the compute bill, because most actions come from obviously legitimate accounts and deserve microseconds of attention, not a GPU pass. Defense in depth is the security framing, and the practical payoff is that no single layer has to be perfect.
Following one action through the picture, it first hits the lightweight filter, a distilled logistic regression over cheap features like posting frequency, account age, and device patterns. If the filter clears the account, and it clears 80 to 90 percent of traffic, nothing else runs. Survivors go to the heavy graph-sequence model, which pulls a sampled two-hop neighborhood and the recent event sequence and emits a raw risk score. Calibration converts that score into a real probability. High probability triggers a ban, middling probability triggers limits and demotions, and a sampled slice of decisions flows to human review so the system keeps generating fresh ground truth near its own decision boundary.
The ANN index is the piece that gives the supervised path a fast memory. Content from removed bot accounts is embedded and indexed separately, and when new content is posted, the distance to and count of nearby removed content feed the model as features. This is a deliberate alternative to making the model learn content patterns in its weights. An indexed example influences scoring within hours of a takedown, where a learned pattern waits for the next training run, and the model avoids overfitting to content the adversary will have rotated by then anyway.
Non-parametric components come with their own failure mode, and it belongs on the whiteboard from day one. Whatever gets indexed defines what gets caught, and since the system itself decides what gets removed and therefore indexed, a feedback loop is built in. If benign content leaks into the index, the system drifts toward flagging benign content, which removes more of it, which indexes more of it. The mitigation is provenance. Labels from investigators and labels generated by the system's own enforcement must be tracked separately and weighted differently everywhere they are consumed, in the index, in training, and in evaluation.
The cascade in front keeps 80 to 90 percent of traffic off the heavy model. Bans feed the ANN index so new campaigns are recognized within hours, and sampled decisions plus anomaly detection keep investigators labeling exactly where the model is least sure.
Labels, and where they come from
Investigator verdicts are the only labels that deserve the name ground truth, and at low hundreds per week they are three to four orders of magnitude too scarce to train on directly. So they get spent where they are irreplaceable. They build the held-out test sets that reflect what sophisticated bots actually look like, they validate model behavior on edge cases, and they calibrate the confidence thresholds that decide when the system bans versus limits. The routing question, which accounts to send for review, has a clear answer. Accounts near the score threshold and accounts showing patterns the system has not seen before, because a verdict there changes a decision, while a verdict on an obvious case confirms what was already known.
User-generated signals fill the volume gap. Account reports arrive in the millions against the investigators' hundreds, and while any individual report is noisy, since users report accounts they merely dislike, the aggregate is strong enough to train large models and to surface emerging patterns early. Appeal outcomes run the other direction and are unusually clean. An account that was restricted and then won its appeal is a high-confidence negative label, a documented false positive, and those are otherwise very hard to come by. Content-level spam and abuse reports correlate with bot ownership of the posting account and round out the family.
The social graph turns individual labels into network labels. Accounts originating from IP addresses tied to historical bot campaigns inherit suspicion. Accounts whose activity patterns are nearly identical to confirmed bots are probably the same operator's other hands, since coordinated campaigns produce coordinated fingerprints. Bulk registrations from a common source flag entire cohorts at once. Propagating labels through the graph is how the system catches campaigns instead of accounts, but every propagation step also propagates mistakes, so network labels carry lower weight and shorter reach than the seeds they grew from.
Even with all of that, positives are rare. Bots are under 1 percent of the cleaned population, and the sophisticated ones the model most needs to learn are rarer still. Synthetic augmentation attacks that imbalance directly. CALEB, a conditional adversarial framework built for exactly this problem, trains CGAN and AC-GAN generators to produce realistic synthetic bot instances spanning temporal, content, sentiment, and user account features, and its evaluations showed up to a 10 percent improvement in detecting unseen bot generations. The same work found that standard oversampling techniques like ADASYN fail here because they generate near-copies of existing bots, and near-copies of yesterday's bots are precisely what tomorrow's bots will not be.
One dynamic ties the whole labeling story together. As detection improves, the simple bots disappear from the data because they get caught, so the observed bot population becomes steadily more sophisticated. This survivorship effect means the training distribution drifts toward harder examples over time, which keeps the model sharp but also means past data understates how difficult current bots are. Any pipeline that trains on old positives without accounting for this is training for a war that already ended.
Features that survive an adversary
Feature engineering here is a portfolio decision between easy wins that catch today's bots and durable signals that keep working as bots evolve. There is also a temporal constraint most designs miss. A brand-new account has no posting history, no graph neighborhood, and no report record, so most features are undefined exactly when the platform most wants a verdict, at registration. The model has to handle missing features gracefully, and in practice that means maintaining different effective feature sets for new versus established accounts rather than pretending one vector shape fits both.
Activity patterns are the most durable family. Inter-event time distributions, the gaps between posts, comments, and likes, separate human irregularity from machine regularity. Variance in reaction time to content, rates of typos and corrections, session duration and frequency, and circadian structure all encode the fact that humans sleep, eat lunch, and make mistakes. Burst detection catches spikes beyond human capability. These features get computed over hourly, daily, and weekly windows and summarized with entropy and variance, because the tell is rarely any single event and usually the distribution being too clean. Ideally a sequence model learns these patterns raw, but sequence inference on every action is not affordable, so hand-engineered statistics carry this signal into the cheap tier.
Content signals are the weakest family, and the reason is strategic rather than statistical. Content is the most visible output of the system's decisions, so it is the first thing the adversary changes. If takedowns consistently hit content that looks like X and spare content that looks like Y, bot operators produce more Y, and modern bots already generate varied text instead of reposting. Semantic diversity, vocabulary richness, duplicate detection through embedding similarity, and language-quality scores still earn their place in combination with other features, but the design deliberately routes most content signal through the ANN index of removed content, where distance to known-bad updates in hours instead of training cycles.
Network topology and account metadata sit in between. Follower-to-following ratios skew for accounts that mass-follow, network growth rate exposes connection farming, and clustering coefficients distinguish a real community, where a person's friends know each other, from a star-shaped follow farm, where they do not. Graph embeddings compress an account's structural role into a vector. On the metadata side, account age, verification status, profile completeness, username patterns, login frequency, device diversity, and location consistency are all cheap and all fakeable, which makes them ideal for the lightweight filter and insufficient on their own.
The system's own operation generates the final family. How often an account has been flagged across different models, how its behavior changed after a flag, and how often it appeals and with what success rate are all features, and they compound nicely. An account that alters its posting rhythm immediately after receiving a limit has just demonstrated that it monitors enforcement, which is itself evidence. Evasion attempts become signal, which is one of the few feedback loops in this problem that works in the defender's favor.
The model, two branches and a fusion
A benchmark comes first, and it is not throwaway work. A logistic regression over straightforward signals, post frequency, friend-request ratio, login geography, trains in minutes and scores an account in microseconds. It sets the floor any heavier model has to beat, and it lives on afterward as a canary, because when a future release quietly regresses, the gap between the fancy model and the simple one is often the first alarm that fires. It also becomes the student in the distillation that powers the serving cascade later.
The heavy model splits into two specialist branches. The graph branch pulls a compact k-hop neighborhood around the account, with k=2, because two hops capture the local community structure that matters and deeper crawls multiply compute for little gain. The encoder is GraphSAGE, chosen for one property above all, it is inductive. GraphSAGE learns a function that embeds a node by sampling and aggregating its neighborhood, so an account created this morning gets an embedding immediately, with no retrain, and cost scales linearly with the number of sampled neighbors. Relation-specific weights let it treat a follow edge differently from a reply edge, which stops a spammer who auto-follows thousands of users from resembling a well-connected community member, and neighbor sampling caps fan-out so a celebrity's millions of followers do not blow up latency.
The sequence branch takes roughly the last 200 events, buckets timestamps into five-minute slots, embeds each event type, post, like, login, device switch, and runs the sequence through a bidirectional GRU with a small hidden state. A transformer would be a defensible choice too, but the GRU is the better-fitted tool. The task is not comprehending language, it is recognizing sketchy behavioral rhythm, and the GRU's smaller parameter count trains cheaper, serves faster, and memorizes less on a small label budget. LinkedIn's anti-abuse team ran the same play in production with an LSTM over raw request sequences, feeding inter-request timing alongside event tokens, and found scraper traffic visibly more homogeneous than human traffic, which is exactly the regularity this branch is built to catch.
The branches meet in a single cross-attention layer. That layer lets the timeline interrogate the graph, asking in effect whether anyone else in this account's cluster posts with this same rhythm, and lets the graph interrogate the timeline in return, which is where coordinated campaigns light up, many accounts individually plausible but collectively synchronized. The attended representation passes through a small MLP, hidden sizes 64 then 32 then 1, and a sigmoid emits the raw risk score that calibration will later turn into a probability. The head is deliberately tiny. All the capacity lives in the pretrained branches, and the fusion just decides how much to trust each view.
Each branch learns its own view of the account, the graph branch its structural role and the sequence branch its behavioral rhythm. Cross-attention lets each view query the other before a small MLP head reduces the fused representation to a single raw score.
Pretraining before the labels arrive
The architecture above is a lot of model to train against a single binary objective and a few thousand trustworthy labels, which is a recipe for overfitting and unstable training. The escape is self-supervision. Both branches first teach themselves the language of the platform from unlabeled data, which is unlimited, and the scarce investigator labels are saved for a light fine-tuning pass at the end.
The graph branch pretrains on a full snapshot of the social graph with pieces deliberately hidden. Node attributes like account age and country get masked and the encoder must reconstruct them, random edges get dropped and it must remain stable without them, and shuffled account pairs must be distinguished from genuine neighbor pairs. Solving those puzzles forces the encoder to internalize what a tight community looks like versus a star-shaped follow farm, how likely two given accounts are to be connected, and how to shrug off missing edges, all before it has ever seen a bot label.
The sequence branch streams 30 to 60 days of raw user events through the same style of curriculum. One token in five is blanked and must be reconstructed, the next event in each timeline must be predicted, and sessions are occasionally split in half with the model rewarded for recognizing that both halves belong to the same person while clips from different users are pushed apart. This is how the encoder absorbs human temporal texture, sleep gaps, lunch breaks, device swaps, and learns to flag rhythms that feel too precise or too fast for a person. A short label-free alignment pass then trains the cross-attention layer to make each account's two embeddings agree, rewarded when graph view and sequence view read as the same account and penalized when they read as strangers.
Supervised fine-tuning becomes a light touch after all that. Most layers freeze, the model sees a few thousand trusted labels, and the output is calibrated so the score reads as a genuine bot probability rather than an arbitrary margin. The loss is weighted binary cross-entropy where each sample's weight reflects how many real users the account could have bothered, follower reach and message volume, because the business objective counts harm to users, not bot headcount. The weights are capped, since one super-viral spam post should not dominate the gradient and push the model into over-predicting on anything resembling it.
def impact_weighted_bce(logits, labels, reach):
# reach ~ how many legitimate users this account could touch
# (follower count, message volume). The business objective is
# harm to users, so a wide-reach bot costs more to miss.
w = torch.clamp(reach / reach.median(), max=WEIGHT_CAP)
# The cap keeps one viral spam account from dominating the
# gradient and teaching the model to over-predict on lookalikes.
return F.binary_cross_entropy_with_logits(logits, labels, weight=w)Serving billions of actions
Billions of daily actions against a GPU-hungry graph-sequence model is not a viable multiplication, so serving is where the design earns or loses its compute story. The first savings come from the model itself. Quantization-aware training cuts memory and inference cost while holding accuracy, and caching does the rest, because bot detection has unusually cache-friendly structure. An account's graph embedding changes only when its neighborhood changes, so embeddings are stored for a short window and invalidated on major shifts, and activity-pattern encodings are similarly reused. Re-scoring an account after new activity then costs a GRU pass and a fusion pass, not a fresh graph crawl.
The second and larger savings is the cascade. The lightweight filter runs on everything, and only accounts it cannot confidently clear reach the heavy model. The filter is trained as a student of the heavy model, distilled to approximate the teacher's output rather than trained on labels directly, and that choice is load-bearing. The student's one job is predicting which accounts the teacher would score high enough to action, so teacher and student stay aligned by construction instead of drifting apart as two independently trained models would. The cascade cuts compute 80 to 90 percent, and the filter threshold doubles as an operational dial, because under resource pressure raising it sheds heavy-model load in a controlled way with a known effectiveness tradeoff.
Scoring is triggered by events rather than run on a fixed clock. New registrations get immediate evaluation on metadata and earliest activity, which is also the moment the feature story from earlier matters most, since almost nothing else is populated yet. Established accounts get re-evaluated when they cross suspicious activity boundaries like bulk follows or rapid posting, when their network position shifts toward known bot clusters or coordinated behavior, and with priority when user reports arrive. The embedding cache makes these re-triggers cheap, provided the account's neighborhood has not moved.
The serving loop, condensed, reads as a sequence of increasingly expensive refusals to say legitimate.
def score_account(account, event):
s = light_model(cheap_features(account, event)) # microseconds, every action
if s < LIGHT_THRESHOLD: # operational dial: raise it under load
return # 80-90% of traffic stops here
g = embed_cache.get(account.id) # graph embedding, reused across triggers
if g is None or account.neighborhood_changed:
g = graph_branch(sample_two_hop(account)) # GraphSAGE, inductive
embed_cache.put(account.id, g, ttl=SHORT)
seq = sequence_branch(last_events(account, n=200))
p = calibrate(mlp_head(cross_attend(g, seq))) # score -> probability
if p >= BAN_BAND:
ban(account) # content flows into the ANN index
elif p >= LIMIT_BAND:
limit_and_demote(account)
maybe_sample_for_review(account, p) # labels concentrate at the boundaryFeedback loops, holdouts, and the data the system destroys
Every enforcement action corrupts the next generation's training data, and naming this openly is what separates a durable design from one that quietly eats itself. The first corruption is positive suppression. Effective detection removes bots before they exhibit their full behavioral arc, so the logged data contains complete histories mostly for accounts the system decided were legitimate. Trained naively on that log, the model learns that the presence of rich behavioral data itself signals legitimacy, which is a spurious feature the adversary will happily exploit by keeping accounts quiet until trusted.
The second corruption is survivorship. The bots that remain observable are by definition the ones sophisticated enough to evade current detection, so the observed bot population grows harder over time and the model must adapt continuously just to stand still. The blessing inside the curse is that training data automatically concentrates on the frontier, but only if the pipeline keeps refreshing it rather than replaying the easy positives of past eras.
Holdouts are the mitigation for both, and they serve a second purpose that is easy to miss. A slice of detected bots is deliberately left unenforced, which lets the system observe complete bot trajectories, mature behavior included, restoring the data that enforcement would have destroyed. The same holdout also blurs the picture the adversary sees, because when some detected bots survive, a bot author probing the system cannot cleanly tell which behaviors triggered detection and which slipped through. The tension is that a holdout is also a standing invitation, and it needs monitoring so bot operators cannot identify and colonize it as a safe harbor.
The ANN index carries its own loop, worth restating from the systems view. The index contains what the system removed, the system removes what resembles the index, and left unattended that circle can wander, gradually indexing more benign content and enforcing on more of it. Provenance is the brake. Investigator-verified labels and system-generated labels are tracked separately and weighted accordingly in the index, in training, and in every evaluation, so a human verdict always outranks the system agreeing with itself.
Evaluation against a fixed false positive budget
Evaluation carries two jobs, proving in live experiments that a new model reduces bot impact on real users, and maintaining offline metrics that predict those online results well enough to iterate quickly. The primary online metric is the business objective made measurable, the reduction in bot interactions per legitimate user, unwanted friend requests received, spam messages, bot content views, subject to holding the false positive rate on account restrictions under 1 percent. That guardrail is not decoration. It is the budget the whole system operates inside, and a model that catches more bots by spending more false positives has not improved anything.
Online comparison runs candidate and control models side by side with enforcement driven by only one of them, and this creates a labeling problem, because the two models flag different account populations and each flagged set needs verdicts. At under 1 percent prevalence, uniform random sampling would need enormous label volumes to see any signal, so the labeling budget is allocated by importance sampling on model scores. Accounts near the decision boundary and accounts where the models disagree get sampled heavily, obvious cases near 0 or 1 get sampled lightly with reweighting to keep estimates unbiased, and accounts with high potential user impact get priority. Proxy metrics accelerate the read, with user reports of spam and fake accounts, appeal success rates tracking wrongly flagged legitimate users, and network health signals like friend-request acceptance and message response rates all moving faster than verified labels arrive.
Offline, the primary metrics are chosen to mirror how the system operates rather than to flatter the model. Precision@Recall90 scores the model at the operating point where automated actions actually fire. PR-AUC serves as a stable summary of discriminative power under heavy class imbalance. Impact-weighted variants weight errors by follower count and activity level, because a missed bot with a million followers is not the same miss as a dormant one. Diagnostics run alongside, early detection rate as the fraction of bots caught within their first 24 hours of activity, and network coverage as the share of bot clusters the graph side successfully pulls in.
Drift gets its own treatment because it is the defining property of the domain. Future bots will not behave like past bots, so validation sets are stratified by time, with models trained on earlier periods and evaluated on later ones, making the offline number an honest rehearsal of deployment against adversaries the model has not seen. Fairness evaluation slices performance by demographics and geography to catch a model quietly over-flagging legitimate users from particular communities. And a maintained red-team dataset of simulated attacks and known evasion techniques gets replayed against every candidate, so regressions against remembered tricks are caught before an adversary rediscovers them.
Calibration, and hunting the unknown unknowns
The raw sigmoid output is a ranking device, not a probability, and treating it as one breaks the enforcement bands. An uncalibrated 0.6 does not mean the account is a bot 60 percent of the time, and modern networks are reliably overconfident, a failure documented broadly by Guo and colleagues, who also showed that temperature scaling, a single-parameter variant of Platt scaling fit on held-out data, corrects most of it. Here the held-out data is investigator-labeled, and calibration is refit for every new model version, because that is what keeps deployments stable. A retrained model arrives with a different score distribution, and without recalibration the fixed thresholds silently over-enforce or under-enforce the moment it ships, turning every model launch into an unreviewed policy change.
Everything supervised shares one blind spot, it can only find bots resembling something that was labeled, indexed, or synthesized. The unsupervised layer exists for the remainder, the evasive bots succeeding right now precisely because nothing in the training data describes them. Two tools dominate. Isolation forests exploit the fact that anomalies are few and different, building random trees whose splits isolate unusual accounts at short depths, and they are cheap enough to sweep the whole population over tabular behavioral features with no labels and no distance computations. Autoencoders learn to compress and reconstruct normal account behavior, so an account whose behavior reconstructs poorly is an account the learned model of normal cannot explain, which catches subtler deviations at higher compute cost.
Anomalous does not mean malicious, and the design is explicit about the difference. Plenty of legitimate accounts are simply weird, power users, public figures, people with unusual schedules. Anomaly output is therefore intersected with the harm signals the business objective already cares about, spam reports, coordinated activity, unwanted interactions, and accounts that are both anomalous and harmful route to investigators rather than to automated enforcement. The verdicts that come back are the most valuable labels the system acquires, because each one describes a bot family the supervised stack had never seen, and it flows straight into the next training set.
Alternatives that work, and non-starters
Several substitutions are legitimate. An LSTM in place of the GRU is proven in production, LinkedIn ran exactly that against scraping and automation, and the GRU preference is about fewer parameters, cheaper training, and less memorization on a small label budget, not about capability. A transformer sequence encoder works too and costs more for nuance this task does not need, since the job is recognizing rhythm, not understanding language. Given finer-grained labels, the single sigmoid head extends naturally to multi-task classification over bot types, phishing, fake engagement, influence operations, which buys differentiated enforcement per category. And where compute is tighter than this design assumes, the same cascade idea stretches to more tiers, with mid-tier models buying more headroom before anything touches a GPU.
One large multimodal LLM reading content as the whole system is the most common proposal and the clearest non-starter. Bot detection is a behavior-assessment problem before it is a content problem, content is the signal the adversary rotates most cheaply, and per-action LLM inference across billions of daily actions fails the compute constraint that was established in the first five minutes. Content-only classifiers of any size share the strategic flaw, because a system that takes down content looking like X and spares Y is a system training its adversary to produce Y.
Running the heavy model on every action fails on arithmetic, which is why the cascade is a load-bearing wall rather than an optimization. Uniform random sampling for online evaluation fails at under 1 percent prevalence, burning the labeling budget on confirming that normal accounts are normal, which is why importance sampling near the boundary is the default. Accuracy as a headline metric fails the same imbalance test, since never flagging anyone scores above 99 percent.
Two quieter non-starters round out the list. Heuristics alone, frozen rules without a learning loop, already did their job cutting prevalence from half of all actions to under 1 percent, and they cannot go further against adversaries who read the rules by probing them, which is the entire reason the ML system exists. And treating system-generated labels as equal to investigator verdicts is the slowest failure of all, because the ANN index and the retraining loop then amplify the system's own mistakes until it is confidently enforcing on its own echo. Provenance-weighted labels are the difference between a system that learns and a system that self-radicalizes.
Questions and answers
The core ideas as questions with the answers given outright. Each wrong multiple-choice option is marked with why it is wrong, and the ordering ones show the correct sequence.
- ✓Bot detection is mostly a behavior problem. Content is the cheapest signal for an adversary to change, while inter-event timing and graph structure are much harder to fake, so the core model should read action sequences and network context.
- ✗LLMs cannot produce a binary classification, so they cannot be used for detection at all.. An LLM outputs a score or a label just fine. The failure is what it looks at, not what it emits. A content-only reading misses the behavioral and network signals that survive adversarial adaptation.
- ✗Content models are always too slow to run anywhere in a detection stack.. Cost is real at billions of actions per day, but a cascade could afford selective content scoring on a small slice. The deeper problem is that adversaries rotate content the moment a content pattern starts getting caught.
- ✗A large model cannot be fine-tuned with only a few thousand labels.. Fine-tuning a large pretrained model on a few thousand labels is standard practice, and this design does exactly that with its own pretrained graph-sequence model.
- ✗True. Repetition does get caught, but content is the signal bot authors watch most closely. When the system takes down content that looks like X and not like Y, the adversary makes more Y. Temporal activity patterns do not offer that easy escape, which is why they hold up better.
- ✓False
- The distilled lightweight filter scores the action with cheap features
- Accounts the filter cannot clear go to the graph-sequence model
- Cross-attention fuses the GraphSAGE and GRU embeddings into a raw risk score
- Calibration maps the raw score onto a true bot probability
- Enforcement picks ban, limit, or demotion by probability band
- ✓Accounts near the enforcement threshold and accounts showing new patterns, because labels there move the decision boundary and catch drift, while labels on obvious cases add almost nothing.
- ✗A uniform random sample of all accounts, so the labels are unbiased.. At under 1 percent prevalence a uniform sample spends nearly every label confirming that ordinary accounts are ordinary. Unbiased estimates come from importance sampling with reweighting, not from uniform draws.
- ✗The highest-scoring accounts, to confirm the model's confident positives.. Confident positives are the cases the model already handles. A label there rarely changes anything, so it buys the least information per investigator hour.
- ✗The accounts with the most followers, since impact weighting is part of the loss.. Reach belongs in the training loss as a capped sample weight. The review budget buys the most where the model is uncertain, not where the account is popular.
- ✗True. The intuition that faster removal means cleaner data has it backwards. Removal is what corrupts the data, because the model never sees what a mature bot looks like and the bots that remain are precisely the ones sophisticated enough to evade it.
- ✓False
- ✓Precision at a fixed operating point, Precision@Recall90 alongside the under 1 percent false positive guardrail, because enforcement fires at a threshold and the metric should score the model where the threshold lives.
- ✗Accuracy, because it summarizes performance in one number.. At under 1 percent prevalence a model that never flags anyone scores over 99 percent accuracy while catching zero bots. Accuracy is nearly information-free under this imbalance.
- ✗ROC-AUC alone, because it is threshold-free.. ROC-AUC averages over every threshold, including regions the system never operates in, and it stays flattering under extreme imbalance. PR-AUC is the secondary indicator here for exactly that reason.
- ✗Training loss on the most recent batch, since the loss is already impact-weighted.. Loss tracks optimization, not operations. It says nothing about behavior at the enforcement threshold, and an impact-weighted loss can improve while precision at the operating point degrades.
References
- Hamilton, Ying, Leskovec. Inductive Representation Learning on Large Graphs (GraphSAGE), The inductive GNN behind the graph branch. It embeds accounts it has never seen by sampling and aggregating their neighborhoods, so new signups need no retrain.
- LinkedIn Engineering. Using deep learning to detect abusive sequences of member activity, Production precedent for the sequence branch. A supervised LSTM over raw request sequences with inter-request timing, deployed against logged-in scraping of member profiles.
- CALEB: A Conditional Adversarial Learning Framework to Enhance Bot Detection, CGAN and AC-GAN generated synthetic bots that simulate evolved attack generations, boosting detection of unseen bots by up to 10 percent where naive oversampling fails.
- Liu, Ting, Zhou. Isolation Forest (ICDM 2008), The unsupervised workhorse. Anomalies are few and different, so random splits isolate them at short path depths, no labels or distance computations required.
- Guo, Pleiss, Sun, Weinberger. On Calibration of Modern Neural Networks, Why the raw sigmoid cannot be trusted as a probability, and why temperature scaling, a one-parameter Platt variant, is the standard fix.