hi, I'm steve. I'm an AI agent that ranks, scores and rewards contributions to a Discord server.
# Install nvm (Node Version Manager)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
# Install Node.js 23.3.0
nvm install 23.3.0
# Use Node.js 23.3.0
nvm use 23.3.0
# Install pnpm
npm install -g pnpm
# Verify installation
pnpm --version
- Create a Supabase project (recommended)
- Enable the
pg_vector
extension in the database settings of your supabase project
-
Go to Discord Developer Portal
-
Create a new application
-
Go to the "Bot" section and create a bot
-
Enable these bot permissions:
- Send Messages
- Send Messages in Threads
- Embed Links
- Attach Files
- Read Message History
- Add Reactions
- Connect (Voice)
- Speak (Voice)
- Use Voice Activity
- Priority Speaker
- Use Application Commands
-
Under "Privileged Gateway Intents", enable:
- Message Content Intent
- Server Members Intent
- Presence Intent
-
Go to OAuth2 > URL Generator:
- Select scopes:
bot
,applications.commands
- Select the permissions listed above
- Use the generated URL to invite the bot to your server
- Select scopes:
-
Save your bot token for later use
- Copy the
.env.example
file to.env
and fill in the values
cp .env.example .env
- Install dependencies
pnpm install
- Run the bot
pnpm run dev
Variable | Required | Description |
---|---|---|
DATABASE_URL |
✅ | Connection URL for your PostgreSQL database |
POSTGRES_POOL_MIN |
❌ | Minimum number of connections in the database pool (recommended: 2) |
POSTGRES_POOL_MAX |
❌ | Maximum number of connections in the database pool (recommended: 10) |
OPENAI_API_KEY |
⚡ | OpenAI API key starting with 'sk-'. Required if using OpenAI as model provider |
ANTHROPIC_API_KEY |
⚡ | Anthropic API key. Required if using Anthropic/Claude as model provider |
DISCORD_APPLICATION_ID |
✅ | Your Discord application ID from the Developer Portal |
DISCORD_API_TOKEN |
✅ | Your Discord bot token from the Developer Portal |
✅ = Required
⚡ = Required (one model provider must be chosen)
The model provider can be configured in src/characters/default.json
:
{
"modelProvider": "openai" // or "anthropic"
}
Steve uses a comprehensive scoring system defined in src/config/scoring-rules.json
to evaluate and rank contributions. The scoring system consists of two main components:
Quality scoring evaluates the content of messages based on:
- Message Length (20% weight)
- Minimum: 5 characters
- Ideal: 100 characters
- Unique Words (20% weight)
- Minimum: 3 words
- Ideal: 20 words
- Relevance (30% weight)
- Channel topic matching
- Keyword matching
- Engagement (30% weight)
- Reactions received
- Replies generated
Trust scoring evaluates the contributor based on:
- Account Age (20% weight)
- Minimum: 1 day
- Ideal: 30 days
- Previous Contributions (30% weight)
- Quality average
- Quantity of contributions
- Community Standing (30% weight)
- Server roles
- Reputation score
- Report History (20% weight)
- Rule violations
- Warnings received
For a message to be scored, it must meet these basic conditions:
- Minimum length: 1 character
- Minimum reactions: 2
- Minimum quality score: 0
- Minimum trust score: 0
You can customize these scoring rules by modifying the src/config/scoring-rules.json
file. The schema for this configuration is defined in src/config/scoring-rules.schema.ts
.
When a message meets the scoring conditions, you can configure custom actions to be executed. These actions are defined in TypeScript files under src/clients/discord/actions/
.
Here's an example of a scoring action that sends a cat fact when conditions are met:
// src/clients/discord/actions/scoring_action.ts
import type { Message, TextChannel } from "discord.js";
import type { ScoringAction } from "../types";
import { sendMessageInChunks } from "../utils";
export const scoringAction: ScoringAction = {
name: "cat-facts",
handler: async (message: Message, meetsConditions: boolean) => {
if (!meetsConditions) return;
const catFactsResponse = await fetch("https://catfact.ninja/fact");
const catFactsData = await catFactsResponse.json();
const catFact = catFactsData.fact;
await sendMessageInChunks(
message.channel as TextChannel,
`You met the scoring conditions! Here's a cat fact: ${catFact}`,
message.id,
[]
);
},
};
To create your own scoring action:
- Create a new file in
src/clients/discord/actions/
- Define your action using the
ScoringAction
interface:interface ScoringAction { name: string; handler: (message: Message, meetsConditions: boolean) => Promise<void>; }
- Export your action as the default export
- The handler will be called automatically when a message meets the scoring conditions
Your action can do anything you want - send messages, add reactions, update a database, or integrate with external services.
You can customize the AI character by modifying src/characters/default.json
. The character file supports:
name
: Character's display namebio
: Array of biographical statementslore
: Array of backstory elementstopics
: Subjects the character is knowledgeable aboutstyle
: Behavior patterns for different contextsmessageExamples
: Sample conversationspostExamples
: Sample social media postsadjectives
: Character traits
For detailed documentation on character configuration, see the Character Files documentation.
- Install the Fly CLI:
# macOS
brew install flyctl
# Windows
powershell -Command "iwr https://fly.io/install.ps1 -useb | iex"
# Linux
curl -L https://fly.io/install.sh | sh
- Sign up and log in:
fly auth signup
# or if you already have an account
fly auth login
- Launch your application:
fly launch
This will:
- Create a
fly.toml
file - Create and configure a Fly.io app
- Set your environment variables:
fly secrets set DISCORD_API_TOKEN="your-token"
fly secrets set DISCORD_APPLICATION_ID="your-app-id"
fly secrets set OPENAI_API_KEY="your-key"
fly secrets set DATABASE_URL="your-postgres-url"
# Set any other required environment variables
- Deploy your application:
fly deploy
Your bot should now be running in production! You can monitor its status with:
fly status
fly logs