All skills
simota avatar

/experiment

@e307415
by shingo imotasimota/agent-skills85 stars
15

Designing A/B tests: hypothesis docs, sample size, feature flags, significance analysis, CUPED, SRM detection, switchback experiments. Use when hypothesis validation is needed.

Use this Skill: https://skilld.dev/gh/simota/agent-skills/experiment

This session only. Nothing lands on disk.

referencefeature-flag-patterns.md

≈2.3k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Feature Flag Patterns

Flag Types

Type Lifecycle Example
Release Short (days-weeks) New checkout flow
Experiment Medium (weeks) A/B test variant
Ops Permanent Kill switch, rate limit
Permission Permanent Premium features

LaunchDarkly Integration

import { init } from 'launchdarkly-js-client-sdk';

const client = init('client-key', { key: userId });

const showNewCheckout = client.variation('new-checkout', false);

Custom Feature Flag

interface FeatureFlag {
  key: string;
  enabled: boolean;
  variants?: Record<string, unknown>;
  targeting?: { percentage: number; segments?: string[] };
}

Cleanup Checklist

  • Remove flag evaluation code
  • Remove losing variant code
  • Archive flag in management system
  • Update documentation

Platform Comparison Matrix (2026-05)

Feature Statsig (OpenAI) Eppo by Datadog / Datadog Experiments GrowthBook 3.6+ LaunchDarkly PostHog Experiments
Ownership / 2025 events Acquired by OpenAI 2025-09 ($1.1B); CEO became OpenAI CTO of Applications Eppo acquired by Datadog 2025-05 (~$220M); rebranded "Eppo by Datadog" Independent OSS company, v3.6 released 2025-05-01 Independent Independent OSS
Statistical engine CUPED, corrected-alpha always-valid p-values (CAA), sequential, MAB CUPED++ (works on new-user tests via assignment covariates), GAVI sequential (Howard et al. 2021), Bayesian + Frequentist Frequentist + Bayesian; Safe Rollouts with one-sided sequential testing on guardrails (3.6) Dual Frequentist/Bayesian engines, CUPED, sequential testing, MAB — all GA Bayesian (default) or Frequentist; new experimentation engine with running-time calc + percentile Winsorization
Feature flags Full (targeting, rollout, kill switch) Via Datadog Feature Flags Full Industry-leading Full
Warehouse-native Dual (Snowflake, BigQuery, Redshift, Databricks, Athena) Yes — primary focus Yes — primary focus No (event streaming only) Self-hosted DB or ClickHouse Cloud
Observability integration Limited Native (RUM, APM, logs, traces) No No Native within PostHog
Auto-rollback / safe rollout Yes Via observability guardrails Yes (Safe Rollouts 3.6) Yes (via monitoring) Yes
Open source No No Yes (self-host) No Yes
Best for Teams already in OpenAI applications stack Data warehouse-centric orgs + Datadog stack Cost-sensitive teams, OSS preference, SQL-defined metrics Enterprise feature management, dual-engine statistics OSS + product analytics + flags in one tool

Selection Guide (2026-05)

Your situation Recommended platform
Already on OpenAI applications stack, want integrated experimentation Statsig (OpenAI)
Metrics live in data warehouse (Snowflake/BigQuery/Databricks) + Datadog observability Eppo by Datadog
Warehouse-native, OSS preference, SQL-defined metrics, want safe rollouts with one-sided sequential GrowthBook 3.6+
Enterprise FF + SSO + audit logs + dual Frequentist/Bayesian engine LaunchDarkly
All-in-one OSS product analytics + flags + experiments PostHog
Small team, just need simple feature toggles Custom implementation (see below)

Note: PII-sensitive workloads should evaluate the OpenAI-affiliation of Statsig vs the Datadog-affiliation of Eppo against their respective data-processing addenda — both vendor mappings changed in 2025.


Warehouse-Native Integration Pattern

Warehouse-native experimentation analyses experiment results directly in your data warehouse, giving you full control and auditability.

┌─────────────┐    exposure events    ┌──────────────────┐
│  Feature    │ ──────────────────▶  │   Data Warehouse  │
│  Flag SDK   │                      │ (Snowflake/BigQuery│
└─────────────┘                      │  /Redshift/etc.)   │
                                     └──────────┬────────┘
                                                │
                                         SQL analysis
                                                │
                                     ┌──────────▼────────┐
                                     │  Experiment Report │
                                     │  (dbt / Jupyter)   │
                                     └───────────────────┘

Exposure table schema:

CREATE TABLE experiment_exposures (
  exposure_id       STRING NOT NULL,
  experiment_name   STRING NOT NULL,
  variant           STRING NOT NULL,  -- 'control' | 'treatment'
  user_id           STRING NOT NULL,
  exposed_at        TIMESTAMP NOT NULL,
  session_id        STRING,
  device_type       STRING,
  PRIMARY KEY (experiment_name, user_id)  -- one exposure per user per experiment
);

Analysis query (BigQuery example):

WITH exposure AS (
  SELECT
    user_id,
    variant,
    DATE(exposed_at) AS exposure_date
  FROM experiment_exposures
  WHERE experiment_name = 'checkout_redesign'
    AND exposed_at BETWEEN '2024-01-01' AND '2024-01-15'
),
conversions AS (
  SELECT DISTINCT user_id
  FROM order_events
  WHERE event_type = 'purchase'
    AND created_at BETWEEN '2024-01-01' AND '2024-01-22'
)
SELECT
  e.variant,
  COUNT(DISTINCT e.user_id)                         AS users,
  COUNT(DISTINCT c.user_id)                         AS conversions,
  ROUND(COUNT(DISTINCT c.user_id) * 100.0
        / COUNT(DISTINCT e.user_id), 2)             AS conversion_rate_pct
FROM exposure e
LEFT JOIN conversions c USING (user_id)
GROUP BY e.variant
ORDER BY e.variant;

Basic Feature Flag Setup

// lib/featureFlags.ts
interface FeatureFlag {
  name: string;
  variants: string[];
  allocation: number[];  // Percentage for each variant
  enabled: boolean;
}

const flags: Record<string, FeatureFlag> = {
  'new_checkout_flow': {
    name: 'new_checkout_flow',
    variants: ['control', 'treatment'],
    allocation: [50, 50],
    enabled: true
  }
};

export function getVariant(
  flagName: string,
  userId: string
): string {
  const flag = flags[flagName];
  if (!flag || !flag.enabled) {
    return 'control';
  }

  // Deterministic assignment based on user ID
  const hash = hashUserId(userId, flagName);
  const bucket = hash % 100;

  let cumulative = 0;
  for (let i = 0; i < flag.variants.length; i++) {
    cumulative += flag.allocation[i];
    if (bucket < cumulative) {
      return flag.variants[i];
    }
  }

  return 'control';
}

function hashUserId(userId: string, salt: string): number {
  const str = `${userId}:${salt}`;
  let hash = 0;
  for (let i = 0; i < str.length; i++) {
    const char = str.charCodeAt(i);
    hash = ((hash << 5) - hash) + char;
    hash = hash & hash;
  }
  return Math.abs(hash);
}

React Integration

// components/ExperimentProvider.tsx
import { createContext, useContext, ReactNode } from 'react';
import { getVariant } from '@/lib/featureFlags';
import { useUser } from '@/hooks/useUser';
import { trackEvent } from '@/lib/analytics';

interface ExperimentContextValue {
  getExperimentVariant: (experimentName: string) => string;
  trackExposure: (experimentName: string) => void;
}

const ExperimentContext = createContext<ExperimentContextValue | null>(null);

export function ExperimentProvider({ children }: { children: ReactNode }) {
  const { user } = useUser();

  const getExperimentVariant = (experimentName: string): string => {
    return getVariant(experimentName, user?.id || 'anonymous');
  };

  const trackExposure = (experimentName: string): void => {
    const variant = getExperimentVariant(experimentName);
    trackEvent('experiment_exposure', {
      experiment_name: experimentName,
      variant: variant,
      user_id: user?.id
    });
  };

  return (
    <ExperimentContext.Provider value={{ getExperimentVariant, trackExposure }}>
      {children}
    </ExperimentContext.Provider>
  );
}

export function useExperiment(experimentName: string) {
  const context = useContext(ExperimentContext);
  if (!context) {
    throw new Error('useExperiment must be used within ExperimentProvider');
  }

  const variant = context.getExperimentVariant(experimentName);

  // Track exposure on first render
  useEffect(() => {
    context.trackExposure(experimentName);
  }, [experimentName]);

  return {
    variant,
    isControl: variant === 'control',
    isTreatment: variant === 'treatment'
  };
}

Usage Example

function CheckoutPage() {
  const { variant, isTreatment } = useExperiment('new_checkout_flow');

  return (
    <div>
      {isTreatment ? (
        <NewCheckoutFlow />
      ) : (
        <CurrentCheckoutFlow />
      )}
    </div>
  );
}

Source: SKILL.md on GitHub

No alerts13d5 checks · Risk SAFE
  • Gen Agent Trust Hub13d

    The skill is a comprehensive technical reference for product experimentation, including A/B testing, Bayesian analysis, switchback designs, and feature flag management. It contains detailed statistical methodologies, code snippets for implementation, and integration guides for well-known industry platforms. No malicious patterns, exfiltration attempts, or security risks were identified.

  • Socket13d

    No alerts

  • Snyk13d

    Risk: LOW · No issues

  • Runlayer6mo

    7 files scanned · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at e307415. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 days ago.

Activeupdated 2 weeks ago

README badge

README badge for simota/agent-skills/experiment