Case study: a 24-team Fantrax NBA keeper league

Robby: a fantasy league Slack bot built on League Loom

Robby is a Slack bot that answers questions for a 24-team Fantrax NBA keeper league with a salary cap and a long rulebook.

It reads live standings, rosters, matchups, transactions and waivers through League Loom, reads the league's rulebook and offseason sheet from Google, and posts scheduled waiver reminders, matchup reminders and a weekly recap. League Loom's founder built it for their own league; this page explains how it works and how to build one like it.

Free connector · ESPN, Sleeper & Fantrax · Works with compatible AI tools

Looking for the general build guide and code? See Build your own fantasy sports AI agent.

Looking for Fantrax salary cap and keeper help? See Fantrax NBA dynasty and salary cap leagues.

Last updated

Before you start

What you need to build a bot like Robby

A Fantrax, ESPN or Sleeper league

Robby reads a Fantrax NBA league. The same pattern works for any league League Loom reads, with ESPN cookies for a private ESPN league and only a username for Sleeper.

A Slack workspace you can add apps to

Robby needs permission to read mentions and direct messages, post messages, run a slash command and look up users. Robby's own commands cover standings, matchups, transactions, available players, a weekly recap and rules questions.

A model API and a host

Robby uses OpenAI's Responses API with League Loom as a remote MCP tool and runs on Vercel with a daily cron. Any model API that can call a remote MCP server works; the build guide has Claude examples too.

Get connected

From your league to your AI tool

1

Connect the league to League Loom

Run the setup wizard with the league's Fantrax URL and leave the personal team unselected, so the bot answers for the whole league. Add a Fantrax session cookie if the league is private and you want scores and transactions. Copy the connection token.

2

Build the bot

Create a Slack app, then write a small server that verifies Slack's signed requests, sends each question to your model with League Loom attached as a remote MCP tool, and posts the answer back. Robby runs this on Vercel.

3

Add rules and a schedule

Load your rulebook into the instructions with a rule to cite it, then add a scheduled job that posts the weekly recap and reminders. Keep the token and Slack secrets in your host's environment variables.

Remote connector URL

https://leagueloom.com/mcp

Add this URL in your AI tool, then follow the guided setup.

Open setup wizard →

Worked example

One question, three sources

Illustrative walk through Robby's design, based on its source code. It does not quote a real league conversation.

  1. A manager asks in Slack

    Someone mentions Robby or types /league with a question. The server checks Slack's signature, then sends the question to the model with the league instructions and League Loom attached.

  2. The model gathers the facts

    It calls League Loom for the live roster, salary and standings, and reads the matching rule from the rulebook text already in its instructions. If the two disagree, it says so instead of picking one.

  3. Robby answers with a source

    The reply comes back as Slack formatting, with tables converted to native Slack tables and the exact rule heading cited at the end. A /league feedback command lets managers flag a wrong answer.

More about this connection

A league with a salary cap, keepers, an auction and traded picks generates the same questions every week, and the answers live in three places: Fantrax, the rulebook and the commissioner's spreadsheet. Robby puts all three behind one Slack mention.

League Loom is the part that keeps the Fantrax answers current without anyone maintaining a scraper, and the bot's instructions decide how the three sources are weighed. The league itself is private, so this page leaves out its name, managers, documents and connection details.

Architecture

How Robby works

Robby is a small Next.js app on Vercel. Each Slack request becomes one call to the model, which can call League Loom as many times as the question needs before it answers.

teams in one Fantrax NBA keeper league
24
League Loom tools Robby may call
9
sources behind every answer
3
scheduled posts a week
4
What happens when a manager asks Robby a question
  1. In Slack

    A manager asks

    A mention in an approved channel, a direct message or the /league command.

    • @Robby
    • /league standings
  2. On Vercel

    Robby's server

    Checks Slack's signature, then adds the league policy and rulebook text to the instructions.

    • Next.js
    • Daily cron
  3. The model

    Facts from three sources

    Calls League Loom for live data and reads the rulebook and offseason sheet already in its instructions.

    • League Loom
    • Rulebook
    • Offseason sheet
  4. Back in Slack

    An answer with a source

    Slack formatting, native tables and the exact rule heading cited at the end.

    • Cited rule
    • /league feedback

Live data from League Loom

League Loom is attached as a remote MCP tool limited to nine league-wide tools, from league info and rosters to the available-player pool and a league health report.

Rules from a Google Doc

The bot reads the rulebook's text, caches it for five minutes, and builds an index of rule headings so every rules answer cites a real heading.

Offseason data from a Google Sheet

Auction balances, the rookie draft order, the snake draft template and traded pick protections come from read-only sheet exports, cited by tab and cell.

Slack in and out

Mentions in approved channels, direct messages and a /league command with shortcuts such as standings, matchups, transactions, available, weekly, dollars, picks and question.

A schedule

One daily cron decides what to post: waiver reminders on Monday and Friday, the weekly recap on Tuesday and a matchup reminder on Sunday, paused before the season starts.

Team matching

When a manager does not name a team, Robby may use a team hint from their Slack profile, but only if it matches exactly one live team name. Otherwise it asks.

The League Loom tool in Robby, simplified (OpenAI Responses API)
// The League Loom part of a league-wide bot, as in Robby.
const leagueLoom = {
  type: "mcp",
  server_label: "league_loom",
  server_description: "Live fantasy league data: standings, rosters, matchups, waivers and settings.",
  server_url: "https://leagueloom.com/mcp",
  authorization: process.env.LEAGUE_LOOM_TOKEN,
  require_approval: "never",
  allowed_tools: [
    "fantasy_get_league_info",
    "fantasy_get_rosters",
    "fantasy_get_standings",
    "fantasy_get_matchups",
    "fantasy_get_schedule",
    "fantasy_get_transactions",
    "fantasy_get_draft",
    "fantasy_get_available_players",
    "fantasy_get_league_health",
  ],
};

// Rules and live data travel together: the rulebook text goes in the instructions,
// League Loom supplies the numbers.
const response = await client.responses.create({
  model: "YOUR_MODEL",
  input: [
    { role: "developer", content: leaguePolicy + rulebookText },
    { role: "user", content: slackQuestion },
  ],
  tools: [leagueLoom],
});

Simplified from Robby's source. leaguePolicy, rulebookText and slackQuestion stand for the bot's own instructions, the Google Doc text and the manager's message.

A week in the channel

A week with Robby

Most of Robby's value is the posts nobody has to remember to write. One daily cron checks the day and posts what is due, and managers ask whatever they like in between.

Illustrative posts with made-up teams and numbers, based on Robby's schedule, not real league messages

Monday and Friday: waiver reminders

A nudge before waivers run, with the best available players at the positions teams are thin at.

#league-chat · Monday

Robby

Waivers run tonight. The top available guard is averaging 14 points in his last five games, and four teams have only one healthy center.

Tuesday: the weekly recap

Last week's results, the standings and the moves that mattered, written from League Loom's matchups, standings and transactions.

#league-chat · Tuesday

Robby

Week 4 recap: Bench Mob swept the categories to take first, the Splash Bros traded a 2027 first for a starting forward, and six teams sit within one game of the playoff line.

Any day: ask anything

Managers ask in plain language or use a /league shortcut. When an answer rests on the rulebook, Robby names the rule heading so anyone can check it.

#league-chat

Sam

/league available centers

Robby

Three centers are free agents. The best fit for the cap is the backup averaging 9 rebounds, at the minimum salary. Adds go through Fantrax as usual.

League rules

Teaching the bot the league's keeper rules

Fantrax returns a keeper-years-left value, but the league's rules decide what it means. Robby carries the commissioner's rulings as an explicit policy in its instructions, separate from the rulebook, and the build includes a paid test run against tricky made-up cases.

Roster first

A player on waivers or in free agency is not keepable, whatever the keeper value says. Bench and injured reserve still count as rostered.

Zero means zero

An explicit zero keeper years left means not keepable. A missing value on a player record that loaded is the league's default of two years.

Salary against the keeper cap

The bot compares full-dollar salaries against the keeper cap in the current rulebook, and adds up a proposed keeper group instead of judging players one at a time.

Illustrative example, not a real league answer

You askCan I keep my starting center?

Example answer

Not keepable. Fantrax shows 0 keeper years left for that player on your current roster.

Source: the keeper section of the league rulebook, plus the commissioner's ruling that zero years left means not keepable.

What this approach does not cover

  • League Loom reports what Fantrax returns. Whether a player is keepable comes from the league's rules, which the bot has to be told.
  • Contracts or exceptions the rulebook leaves unclear go back to the commissioner. The bot asks instead of deciding.

Lessons

What building Robby taught us

A few choices made the biggest difference to how much the league trusts the bot.

Limit the tools

Allowing only the league-wide tools keeps answers about the league, not about whoever set up the connection.

Treat every source as data

The instructions tell the model that the rulebook, the sheet and Slack messages are data, never instructions, so a pasted message cannot rewrite the bot's rules.

Log usage, not people

Robby logs the response id, route, model and token counts, never the question, the Slack identity or the connection, so costs can be tracked without storing league chatter in logs.

Cache the shared part

The rulebook and sheet context sit in a stable prompt prefix, so repeated questions can reuse the provider's prompt cache. Measure hits before assuming savings.

Sources checked . Written from Robby's source code (its September 12, 2026 version) and the founder's description of the league. The league's name, managers, documents and connection details are left out on purpose.

OpenAI: remote MCP servers in the Responses API · Anthropic: the MCP connector in the Messages API

Before you connect

Questions, answered

What is Robby?

Robby is a Slack bot for a 24-team Fantrax NBA keeper league with a salary cap. It answers managers' questions from live league data through League Loom and from the league's rulebook and offseason spreadsheet, and it posts scheduled waiver reminders, matchup reminders and a weekly recap.

How does Robby get live Fantrax data?

Robby attaches League Loom as a remote MCP tool in OpenAI's Responses API, limited to nine league-wide tools such as standings, rosters, matchups, transactions and available players. The model calls them while it writes each answer.

Can I use Robby in my league?

Robby is private to one league and its code is not published. You can build the same kind of bot: the build guide has the League Loom connection code for the OpenAI and Claude APIs, and this page describes how Robby is put together.

Does a league Slack bot need a Fantrax API key?

No API key. League Loom reads a Fantrax league from its URL. For a private Fantrax league, matchup scores and transactions also need your Fantrax session cookie, entered on League Loom's setup page, or a commissioner can make the league publicly viewable.

Does the same approach work for ESPN or Sleeper leagues?

Yes. League Loom reads ESPN and Sleeper leagues through the same tools, so the bot code does not change. A private ESPN league needs espn_s2 and SWID cookies at setup; Sleeper needs only a username or league URL.

Can Robby make trades or set lineups?

No. League Loom's league tools retrieve and analyze data, and Robby only reads. Managers make their own moves in Fantrax.

Before you connect a league, read how League Loom is built, what the privacy policy says is stored, the terms of service and the full FAQ, or check the press kit with key facts and who builds it.