# How to Integrate Relay with X and Discord Mentions in firstmate

> Learn to integrate Relay with X and Discord mentions in firstmate. Automate replies to public mentions using fm-x-* scripts and streamline your workflow.

- Repository: [Kun Chen/firstmate](https://github.com/kunchenguid/firstmate)
- Tags: how-to-guide
- Published: 2026-08-13

---

**firstmate supports answering public mentions on X (formerly Twitter) and Discord through the optional Relay integration, which polls for incoming requests, links them to spawned tasks, and posts platform-specific replies using a suite of `fm-x-*` scripts.**

The firstmate automation framework can bridge public social interactions to its internal task supervision loop via the Relay integration. By configuring a pairing token and enabling the polling shim, you can transform X and Discord mentions into tracked tasks that post progress updates and final answers back to the originating thread. This guide explains the exact file paths, environment variables, and shell commands needed to activate and manage the Relay pipeline according to the `kunchenguid/firstmate` source code.

## Enabling Relay via Environment Configuration

To activate the Relay integration, add the pairing token to your home directory’s `.env` file. This bootstrap step creates the polling cadence and initializes the inbox directory without modifying firstmate’s core supervision logic.

```text

# ~/.env

FMX_PAIRING_TOKEN=YOUR_RELAY_TOKEN

```

For testing without posting live replies, set the token to an empty value to enable dry-run mode:

```text
FMX_PAIRING_TOKEN=

```

Optional overrides control platform-specific character budgets and follow-up behavior:

```text
FMX_X_REPLY_MAX_CHARS=280
FMX_DISCORD_REPLY_MAX_CHARS=1900
FMX_FOLLOWUP_MAX_COUNT=3
FMX_FOLLOWUP_MAX_AGE_SECS=604800

```

The [`docs/configuration.md`](https://github.com/kunchenguid/firstmate/blob/main/docs/configuration.md) file defines the full contract for these variables, including the default 30-second polling interval.

## Polling and Ingesting Mentions

Once enabled, [`bin/fm-x-poll.sh`](https://github.com/kunchenguid/firstmate/blob/main/bin/fm-x-poll.sh) runs as a background process every 30 seconds (or the configured interval). It queries the Relay API for new mentions and writes each request as a discrete JSON file to `state/x-inbox/<request_id>.json`.

```bash

# Manual test run with dry-run to preview request IDs

FMX_DRY_RUN=1 bin/fm-x-poll.sh

```

The `fmx-respond` skill then drains this inbox, extracts the platform identifier (`x_platform=twitter` or `discord`), and generates a task-meta record that enters the standard firstmate supervision loop. This architecture ensures that Relay sits as a thin layer on top of the existing watchdog flow defined in [`docs/architecture.md`](https://github.com/kunchenguid/firstmate/blob/main/docs/architecture.md).

## Linking Spawned Work to Original Mentions

When the supervision loop wakes a task for a specific request ID, you must explicitly associate the spawned worker with the originating mention. This linkage enables later follow-ups to thread correctly.

Inside your worker script, after completing the primary work, call [`bin/fm-x-link.sh`](https://github.com/kunchenguid/firstmate/blob/main/bin/fm-x-link.sh) with the task ID and request ID:

```bash
TASK_ID=$(bin/fm-crew-state.sh --print-id)
REQUEST_ID=$(cat state/x-inbox/latest.json | jq -r .request_id)
bin/fm-x-link.sh "$TASK_ID" "$REQUEST_ID"

```

The [`bin/fm-x-link.sh`](https://github.com/kunchenguid/firstmate/blob/main/bin/fm-x-link.sh) script records the `x_request_id` in the task’s metadata, creating a durable reference that subsequent reply scripts use to route responses back to the correct X or Discord thread.

## Posting Replies and Follow-ups

The integration provides three distinct scripts for communicating back to the public platform, each respecting platform-specific budgets and threading models stored in [`bin/fm-x-lib.sh`](https://github.com/kunchenguid/firstmate/blob/main/bin/fm-x-lib.sh).

### Sending Initial Replies with [`fm-x-reply.sh`](https://github.com/kunchenguid/firstmate/blob/main/fm-x-reply.sh)

Use [`bin/fm-x-reply.sh`](https://github.com/kunchenguid/firstmate/blob/main/bin/fm-x-reply.sh) to post the first response to a mention. The script automatically detects the platform from the task metadata and truncates or validates content against `FMX_X_REPLY_MAX_CHARS` (280) for X or `FMX_DISCORD_REPLY_MAX_CHARS` (1900) for Discord.

```bash

# Post a reply linked to the task

bin/fm-x-reply.sh "$TASK_ID" "Your request has been queued and is now processing."

```

If `FMX_DRY_RUN` is set, the script prints the payload instead of posting it, allowing safe testing of message formatting.

### Managing Progressive Updates with [`fm-x-followup.sh`](https://github.com/kunchenguid/firstmate/blob/main/fm-x-followup.sh)

For long-running tasks, [`bin/fm-x-followup.sh`](https://github.com/kunchenguid/firstmate/blob/main/bin/fm-x-followup.sh) posts up to three follow-up messages per request. The script enforces the global limits defined by `FMX_FOLLOWUP_MAX_COUNT` (default 3) and `FMX_FOLLOWUP_MAX_AGE_SECS` (default 604800 seconds / 7 days).

```bash

# First progress update

bin/fm-x-followup.sh "$TASK_ID" "Processing is 40% complete."

# Final update that clears the link

bin/fm-x-followup.sh --final "$TASK_ID" "All work finished. Results attached."

```

The `--final` flag signals the terminal milestone, triggering [`bin/fm-public-followup.sh`](https://github.com/kunchenguid/firstmate/blob/main/bin/fm-public-followup.sh) to post the concluding reply and remove the request-to-task link from the state store.

## Platform-Specific Budgets and Error Handling

All platform abstraction logic resides in [`bin/fm-x-lib.sh`](https://github.com/kunchenguid/firstmate/blob/main/bin/fm-x-lib.sh), which exports constants for character budgets and payload schemas. When a reply exceeds the budget for the detected platform, the scripts either hard-truncate the message or exit with an error code, depending on the severity configuration.

To dismiss a mention without replying (for example, when filtering spam or unsupported requests), use the optional helper:

```bash
bin/fm-x-dismiss.sh "$REQUEST_ID"

```

This removes the JSON from `state/x-inbox/` without spawning a task or leaving orphaned state.

## Summary

- **Enable Relay** by setting `FMX_PAIRING_TOKEN` in your home `.env` file; leave it empty for dry-run mode.
- **Poll for mentions** via [`bin/fm-x-poll.sh`](https://github.com/kunchenguid/firstmate/blob/main/bin/fm-x-poll.sh), which writes new requests to `state/x-inbox/<request_id>.json` every 30 seconds.
- **Link tasks** to mentions using [`bin/fm-x-link.sh`](https://github.com/kunchenguid/firstmate/blob/main/bin/fm-x-link.sh) so that replies thread correctly back to the original X or Discord post.
- **Post replies** with [`bin/fm-x-reply.sh`](https://github.com/kunchenguid/firstmate/blob/main/bin/fm-x-reply.sh), which respects platform-specific character limits (280 for X, 1900 for Discord).
- **Send follow-ups** using [`bin/fm-x-followup.sh`](https://github.com/kunchenguid/firstmate/blob/main/bin/fm-x-followup.sh), capped at three updates within a seven-day window by default.
- **Finalize chains** with the `--final` flag or [`bin/fm-public-followup.sh`](https://github.com/kunchenguid/firstmate/blob/main/bin/fm-public-followup.sh) to clear the link and post the terminal response.

## Frequently Asked Questions

### What file handles the Relay polling logic in firstmate?

The [`bin/fm-x-poll.sh`](https://github.com/kunchenguid/firstmate/blob/main/bin/fm-x-poll.sh) script handles all Relay polling logic. It runs every 30 seconds, queries the Relay API for new X and Discord mentions, and persists each request as a JSON file under `state/x-inbox/`.

### How does firstmate distinguish between X and Discord mentions?

The `fmx-respond` skill extracts the `x_platform` field from the incoming JSON payload (set to `twitter` or `discord`) and stores it in the task metadata. The reply scripts in [`bin/fm-x-reply.sh`](https://github.com/kunchenguid/firstmate/blob/main/bin/fm-x-reply.sh) and [`bin/fm-x-followup.sh`](https://github.com/kunchenguid/firstmate/blob/main/bin/fm-x-followup.sh) read this field to apply the correct character budget and API endpoint.

### Can I test the Relay integration without posting live replies?

Yes. Set `FMX_PAIRING_TOKEN=` (empty value) or export `FMX_DRY_RUN=1` before running any `fm-x-*` script. In dry-run mode, the scripts print the request payload and simulated response instead of calling the live Relay APIs.

### What happens if a task needs more than three follow-up messages?

The [`bin/fm-x-followup.sh`](https://github.com/kunchenguid/firstmate/blob/main/bin/fm-x-followup.sh) script enforces the `FMX_FOLLOWUP_MAX_COUNT` limit (default 3). Attempting to post additional follow-ups beyond this cap will fail silently or return an error, depending on the error-handling flags set in [`bin/fm-x-lib.sh`](https://github.com/kunchenguid/firstmate/blob/main/bin/fm-x-lib.sh). To continue the conversation, you must finalize the current thread and prompt the user to create a new mention.