---
name: social_graph_ranking
description: Ranks who matters in a social graph: degree, betweenness, harmonic closeness, eigenvector, and PageRank centrality plus Louvain community detection over any edge list, via a tested CLI. Use when an agent needs to identify influencers, find brokers and bridge accounts, map communities, or pick seed spreaders in a network built from open data.
---

# Social Graph Ranking

## Purpose

Turn an edge list into an answer to "who actually matters here." Computes five
centrality measures, VoteRank seed spreaders, and Louvain communities, then
cross-checks the measures against each other so the agent reports robust
findings instead of one number. Built for networks an agent can legally obtain:
Bluesky follow graphs, public datasets, mention/reply graphs, collaboration
networks. See `references/data-sources.md` for what is actually collectible
and what is not.

## Workflow

1. **Build the edge list.** One row per relationship. CSV with a
   `source,target[,weight]` header, or SNAP-style plain `src dst [weight]`
   lines. For follower data, record `source` as the FOLLOWER and `target` as
   the account being followed. Anonymize handles before sharing the report.
2. **Run the CLI.**
   ```bash
   pip install networkx
   python3 bin/sg_rank.py edges.csv --directed --top 15 --out report.json
   ```
   Flags: `--format plain` for SNAP-style files; `--top N` for ranking depth;
   `--resolution` for Louvain granularity (>1 finds smaller communities);
   `--seed` for reproducibility.
3. **Read the consensus first.** The report's `consensus_top` lists nodes that
   rank in the top-N of two or more measures. A node that leads on every
   measure is a safe call. A node that leads on only one measure is a
   specialist; see `references/measure-guide.md` for what each specialty means.
4. **Map communities.** `communities` count, `modularity`, and `community_sizes`
   tell you whether the network has real subgroups. Modularity around 0.3 or
   higher means strong structure; near zero means one blob.
5. **Report with caveats.** State the data window, the boundary (who was
   included), and which measures agreed. Never present a centrality rank as
   "the most influential person," only as "top-ranked in this graph."

## Output Contract

`--out report.json` produces:
- `nodes`, `edges`, `directed`, `connected`: graph basics
- `rankings`: per-measure top-N lists of `{node, score}` for
  `degree` (or `in_degree`/`out_degree` when directed), `betweenness`,
  `harmonic_closeness`, `pagerank`, `eigenvector` (undirected, when defined)
- `voterank_spreaders`: top-10 seed nodes for maximum spread
- `communities`, `modularity`, `community_sizes`: Louvain partition summary
- `consensus_top`: nodes in the top-N of 2+ measures, with which measures
- `betweenness_sampled: true` when exact betweenness was too expensive

## Operating Rules

1. No single measure is "importance." Degree counts friends, betweenness finds
   brokers, PageRank finds the followed, eigenvector finds the connected-to-power.
   Report the measure that matches the question being asked.
2. Edge direction decides everything. Follower -> followee is the convention
   this skill assumes. If the input has it backwards, fix the input, not the
   interpretation.
3. Betweenness is exact under 2,000 nodes and sampled (k=256) above that. On
   graphs over ~100k nodes, skip betweenness and lean on PageRank + degree.
4. Louvain has a resolution limit: tiny real communities can merge into big
   ones. If small groups matter, raise `--resolution` and compare.
5. The graph is a sample, not the world. Deleted accounts, private profiles,
   bots, and follow-back rings all distort the rankings. Say so in the report.
6. Work from public data only. Do not scrape behind logins, do not publish
   ranked lists of real people's handles without a clear public-interest reason,
   and keep raw edge lists private.
