# Understanding the Role of Visibility Filtering in the X Algorithm

> Discover how visibility filtering in the X Algorithm acts as a deterministic gatekeeper, evaluating safety and context to control post visibility before ranking. Learn its crucial role.

- Repository: [SpaceXAI Org/x-algorithm](https://github.com/xai-org/x-algorithm)
- Tags: deep-dive
- Published: 2026-09-12

---

**Visibility filtering is the deterministic gatekeeping subsystem that evaluates safety labels and viewer context to decide whether a post should be shown, dropped, or placed behind an interstitial before it reaches the ranking stage.**

Visibility filtering serves as the primary content safety mechanism in the `xai-org/x-algorithm` repository. This Rust-based subsystem operates upstream of the machine learning ranking models to ensure only permissible content enters the recommendation pipeline. By decoupling safety decisions from ranking logic, the architecture maintains clean separation between content qualification and engagement prediction.

## How Visibility Filtering Fits Into the Recommendation Pipeline

The visibility filtering system acts as a **pre-ranking gatekeeper** that processes every candidate tweet before it is scored by the recommendation model. This placement ensures that the ranking stage only evaluates content that is safe and appropriate for the specific viewer context.

### The Three-Stage Decision Flow

The filtering process follows a deterministic sequence:

1. **Safety-label generation** – Upstream services (including bot-detection rules, media-model scores, and account-credibility models) produce **safety labels** for each tweet, defined in [`visibility-filtering/models/safety_labels.rs`](https://github.com/xai-org/x-algorithm/blob/main/visibility-filtering/models/safety_labels.rs).

2. **Rule evaluation** – The visibility filtering service receives these labels along with the viewer's context (blocks, mutes, and content preferences) and executes the deterministic rule registry located in [`visibility-filtering/rules/registry.rs`](https://github.com/xai-org/x-algorithm/blob/main/visibility-filtering/rules/registry.rs).

3. **Outcome assignment** – The system returns a `TweetVisibilityResult` indicating one of three outcomes:
   - **Show**: Full visibility granted to the post
   - **Drop**: The post is omitted from the candidate set entirely
   - **Interstitial**: The post is displayed behind a warning screen (e.g., NSFW or spam warnings)

### Separation of Concerns: Service vs. Model Enforcement

While the primary visibility decision occurs in the Rust-based filtering service, the Python ranking models enforce consistency through a secondary safety filter. The [`recsys_two_tower_model.py`](https://github.com/xai-org/x-algorithm/blob/main/recsys_two_tower_model.py) file exposes configuration parameters including `safety_filter_mode`, `safety_filter_bits`, and `safety_filter_soft_weight` to ensure the model's forward pass respects the same visibility policies evaluated upstream.

## Core Components and File Structure

The visibility filtering implementation spans multiple crates and Python modules, each with distinct responsibilities in the decision pipeline.

### The Visibility Filtering Service Core

The Rust implementation in [`visibility-filtering/filter.rs`](https://github.com/xai-org/x-algorithm/blob/main/visibility-filtering/filter.rs) serves as the primary entry point, receiving `FilterOutcome` structures and producing `TweetVisibilityResult` objects. The per-tweet evaluation logic resides in [`visibility-filtering/filter_tweets.rs`](https://github.com/xai-org/x-algorithm/blob/main/visibility-filtering/filter_tweets.rs), which maps raw safety outcomes into protobuf-compatible results for downstream consumption.

### Rule Registry and Deterministic Evaluation

All visibility rules are centralized in [`visibility-filtering/rules/registry.rs`](https://github.com/xai-org/x-algorithm/blob/main/visibility-filtering/rules/registry.rs). This registry evaluates rules in a deterministic order, making the system fully auditable and allowing engineers to extend filtering logic without modifying the core evaluation engine. The registry pattern ensures that **viewer-specific actions** (such as account blocks or keyword mutes) are applied consistently across all candidate posts.

### Client-Side Abstraction Layer

Callers interact with the service through the **visibility-filtering-client** library, which abstracts gRPC communication. The [`visibility-filtering-client/models.rs`](https://github.com/xai-org/x-algorithm/blob/main/visibility-filtering-client/models.rs) file provides helper methods like `to_visibility_reason()` to convert raw protocol buffer results into user-friendly explanation strings. This abstraction allows the Python serving infrastructure to consume Rust-authored visibility decisions seamlessly.

### Model-Side Safety Filter Implementation

The ranking models implement the `apply_safety_filter` function to mask unsafe candidates during inference. As implemented in [`phoenix/xrex/models/recsys_two_tower_model.py`](https://github.com/xai-org/x-algorithm/blob/main/phoenix/xrex/models/recsys_two_tower_model.py), this function accepts `candidate_logits` and applies bitwise masking using the `safety_filter_bits` configuration parameter. When `safety_filter_apply_to_candidates` is enabled, the model zeroes out or heavily penalizes logits for candidates that violate safety policies.

## Practical Implementation Examples

The following examples demonstrate how to integrate visibility filtering into both serving infrastructure and model inference.

### Integrating Visibility Filtering in Serving Runners

The [`serving_filters_runner.py`](https://github.com/xai-org/x-algorithm/blob/main/serving_filters_runner.py) module demonstrates how Python serving code consumes visibility decisions:

```python
from xrex.inference.serving_filters_runner import FilteredRetrievalModelRunner

class MyModelRunner(FilteredRetrievalModelRunner):
    enable_bloom_filter = True   # turn on Bloom filter

    enable_topic_filter = False

    def postprocess(self, candidates):
        # `self.filtered_reason_mask` is populated by the visibility service

        safe_candidates = [c for c, mask in zip(candidates, self.filtered_reason_mask) if mask]
        return safe_candidates

```

This pattern ensures that the `filtered_reason_mask` populated by the visibility service is respected during candidate post-processing.

### Applying Safety Filters in Two-Tower Models

When implementing custom ranking models, enforce visibility consistency using the safety filter configuration:

```python
from xrex.models.recsys_two_tower_model import TwoTowerModel

model = TwoTowerModel(
    safety_filter_mode="hard",
    safety_filter_bits=0b11,
    safety_filter_soft_weight=0.0,
    safety_filter_apply_to_candidates=True,
)

# Inside the model's forward pass

candidate_mask, _ = apply_safety_filter(
    logits=candidate_logits,
    bits=self.config.safety_filter_bits,
    soft_weight=self.config.safety_filter_soft_weight,
)
filtered_logits = jnp.where(candidate_mask, candidate_logits, -1e9)

```

The `safety_filter_mode="hard"` setting ensures that dropped content receives a strongly negative logit value, effectively removing it from recommendations regardless of ranking scores.

### Querying Visibility Results from Rust Clients

Rust services can query visibility status directly using the client library:

```rust
let result = vf_client.get_tweet_visibility(tweet_id, viewer_id).await?;
println!("Visibility decision: {:?}", result);
if let Some(reason) = result.to_visibility_reason() {
    println!("Filtered because: {}", reason);
}

```

This approach leverages the type-safe models defined in [`visibility-filtering-client/models.rs`](https://github.com/xai-org/x-algorithm/blob/main/visibility-filtering-client/models.rs) to handle protocol buffer deserialization and error mapping automatically.

## Summary

- **Visibility filtering operates pre-ranking** to ensure only safe, permissible content reaches the machine learning models in the X algorithm.

- **Three distinct outcomes** are possible: Show (full visibility), Drop (complete removal), and Interstitial (warning-screen display).

- **Rule evaluation is centralized** in [`visibility-filtering/rules/registry.rs`](https://github.com/xai-org/x-algorithm/blob/main/visibility-filtering/rules/registry.rs) and executes deterministically to ensure auditability and consistent behavior.

- **Dual enforcement** occurs through both the Rust-based filtering service and Python model-side safety filters to prevent unsafe content from slipping through pipeline gaps.

- **Telemetry integration** via `safety_filter_stats` and `filtered_reason` counters allows monitoring of how visibility decisions impact downstream engagement metrics.

## Frequently Asked Questions

### What are the three possible outcomes of visibility filtering?

The system returns a `TweetVisibilityResult` that specifies **Show** for fully visible content, **Drop** for content that should be removed entirely from the candidate set, and **Interstitial** for content requiring a warning screen before display. These outcomes are evaluated in [`visibility-filtering/filter_tweets.rs`](https://github.com/xai-org/x-algorithm/blob/main/visibility-filtering/filter_tweets.rs) based on safety labels and viewer context.

### How does visibility filtering differ from the ranking model?

Visibility filtering is a **deterministic rule-based system** that makes binary safe/unsafe decisions before scoring occurs, while the ranking model is a **probabilistic machine learning system** that predicts engagement. The filtering service runs in Rust and executes registry rules, whereas ranking models run in Python and focus on relevance prediction.

### Where are the visibility rules defined in the codebase?

All visibility rules are enumerated in [`visibility-filtering/rules/registry.rs`](https://github.com/xai-org/x-algorithm/blob/main/visibility-filtering/rules/registry.rs). This central registry defines the evaluation order for safety labels, viewer blocks, mutes, and content settings, making the system extensible without modifying the core filtering engine in [`filter.rs`](https://github.com/xai-org/x-algorithm/blob/main/filter.rs).

### Can the ranking model override visibility filtering decisions?

No, the ranking model cannot override drop decisions, but it can apply additional constraints through the `apply_safety_filter` function. The model uses parameters like `safety_filter_bits` to ensure its output remains consistent with the service's decisions, effectively masking out candidates that slipped through due to race conditions or stale caches.