How to Integrate Relay with X and Discord Mentions in firstmate
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.
# ~/.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:
FMX_PAIRING_TOKEN=
Optional overrides control platform-specific character budgets and follow-up behavior:
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 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 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.
# 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.
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 with the task ID and request ID:
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 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.
Sending Initial Replies with fm-x-reply.sh
Use 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.
# 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
For long-running tasks, 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).
# 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 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, 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:
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_TOKENin your home.envfile; leave it empty for dry-run mode. - Poll for mentions via
bin/fm-x-poll.sh, which writes new requests tostate/x-inbox/<request_id>.jsonevery 30 seconds. - Link tasks to mentions using
bin/fm-x-link.shso that replies thread correctly back to the original X or Discord post. - Post replies with
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, capped at three updates within a seven-day window by default. - Finalize chains with the
--finalflag orbin/fm-public-followup.shto 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 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 and 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 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. To continue the conversation, you must finalize the current thread and prompt the user to create a new mention.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →