Automod is a Farcaster channel moderation service. It allows channel hosts to configure rules to automatically filter casts and manage their channel in teams.
All of automod is contained in a single repository and service. It contains the API, Queueing system, Marketing pages and all UI.
- API Framework: Remix
- Database: PostgreSQL / Prisma
- Queues: BullMQ with Redis
- Hosting: Anywhere that supports docker, node, or remix.
Automod favors less directories, less files and generally avoids DRYing things up unless its specifically required. Most code is colocated together if it can be which mean you will sometimes find components, route handlers and typings in the same file.
- /app/routes: Standard remix routes. Most routes include business logic directly only sharing code where strictly necessary.
- /app/components: UI Components.
- /app/lib: Clients, utils, and business logic.
- /validation.server.ts: All supported rules and actions, mostly config driven
- /automod.server.ts: Core business logic for validating a cast against the rules configured.
- /bullish.server.ts: Most queues and worker tasks are located here.
- /public: Static files and assets
- /prisma: Standard prisma migrations
- /bullboard: A local server to monitor queues and tasks. See package.json to run.
- /api/*: generally, private APIs used by automod ui
- /api/actions/*: cast action APIs
- /api/partners/*: partner APIs secured by partner api keys.
- To grant access, login to the /admin console and provision a token, include in header:
api-key: $TOKEN
- To grant access, login to the /admin console and provision a token, include in header:
See the Prisma Schema for an overview.
Point of note:
- ModeratedChannel inclusionRuleSet and exclusionRuleSet: These are json strings that define the moderation rules. See the zod schema in validation.server.ts for its shape. You may wonder why the shape isn't simpler. Automod supports recursive logical expressions of rules as well as multiple actions to execute but the UI at time of writing only exposes a single AND/OR and no preset actions. Even this customers get stuck on quite often.
- RuleSets: deprecated in favor of
inclusionRuleSet
andexclusionRuleSet
.
Automod does some caching but its all in process and in memory on each host. When you deploy its flushed, etc.
How a cast is moderated
- Automod registers a channel url with Neynar when a new sign up happens
- When a cast comes in to the channel, Neynar triggers a webhook to automod
- Automod adds the cast to a queue to be processed using Redis-backed BullMQ
- A worker picks up the cast, looks up the channel moderation rules and validates the cast
- If it is accepted, a like on protocol is issued and the cast will appear in the moderated feed.
Adding a new Rule
Rules are mostly config driven and so far the abstraction has not been too leaky.
- Add a
RuleName
andRuleDefinition
to validations.server.ts. There are many examples to reference. - The
RuleDefinition
args will automatically render a form, store and serialize all the inputs. - Implement the check and add it to
ruleFunctions
.
The rule will be available to all.
git clone https://github.com/yourusername/automod.git
cd automod
pnpm install
cp .env.example .env
# Update .env with your configuration, see [.env.example](/.env.example) for instructions
pnpm run dev
- Automod is a standard remix app. You can deploy it anywhere that supports Docker, Remix, or Node.
- A separate Redis and Postgres instance is required as well as other 3rd party api keys, make sure to review the environment variables required.
See Deploy Workflow for an example with Github Actions and Fly.io
Almost all modern hosting companies auto-detect Remix applications. Just run initialize prisma after you install and before you start.
pnpm exec prisma migrate deploy
pnpm exec prisma generate
pnpm run start
pnpm install
pnpm build
pnpm exec prisma migrate deploy
pnpm exec prisma generate
pnpm run start
Set your user's role as 'superadmin' and you can access the /admin dashboard.
This will allow you to:
- Login and impersonate any user to help with rule configuration issues.
- Kick off recovery flows for channels in case there is downtime.
- Show an incident banner
When Automod or other Farcaster infra goes down it means casts may not be moderated.
Login to /admin console and run a sweep or recovery
- Recovery: Moderate historical casts not yet seen, useful when there was downtime and things were missed.
- Sweep: Moderate historical casts, even if they've already been seen. Useful if you or a customer ships bad moderation logic and everything must be reprocessed.
If you want to stop, start, delete or manage queues, point your env files at production Redis and run pnpm bullboard
and open https://localhost:8888/ui
. This should be exposed and hosted remotely but never needed to.
Sentry is used for client and server errors. All other logs are emitted to stdout via console.
A home made paging service (webhook-relay.fly.dev) is used to trigger critical alerts with sync propagation or dropped webhooks. You can point this wherever you like.
At time of writing automod:
- Powers 550 channels
- ~1 request per second.
- Processes 500k+ casts per month.
All Data APIs are usage based and highly variable. Here's a snapshot of August.
Service | Provider | Cost | Notes |
---|---|---|---|
API | fly.io | $13/mo | 2 X shared-cpu-2x with 1024 MB memory |
PostgreSQL | fly.io | $35/mo | 2 X shared-cpu-2x with 4096 MB memory (over provisioned) |
Redis | railway.app | < $1/mo | |
Farcaster Data | Neynar | > $100/mo (Contact Neynar) | Used for cast metadata, webhooks, feeds, frames, etc. |
NFT Data | SimpleHash | > $100/mo (Contact SimpleHash) | Needed for 1155 token lookups and Zora Network at high concurrency. |
Ethereum JSON Data | Alchemy/Infura/Coinbase | ~$30/mo | Most ERC20/721/1155 token lookups and Sign in With Farcaster. |
Airstack Data | Airstack | Buy 1 Fan Token, free forever | Channel Following, FarRank, FarScore |
Moxie Data | The Graph | < $5/mo | |
Cast Storage | Farcaster | ~$40/mo amortized | 200 storage units for @automod reactions. Renews yearly. Deprecated |
Automod uses Hypersub for all billing and membership tracking. In short, its an NFT with some additional metadata indicating how much time in the subscription remains. Billing sync are triggered at midnight each night or manually by users.
For relevant code see subscription.server.ts