Hazel

Configuration

Environment variables and configuration options

Configure your bot using environment variables or explicit options.

Environment Variables

VariableRequiredDefaultDescription
BOT_TOKENYes-Bot authentication token
ELECTRIC_URLNohttps://electric.hazel.sh/v1/shapeElectric SQL proxy URL
BACKEND_URLNohttps://api.hazel.shBackend API URL
REDIS_URLNoredis://localhost:6379Redis URL for commands

Example .env

# Required
BOT_TOKEN=your-bot-token-here

# Optional: For local development
ELECTRIC_URL=http://localhost:8787/v1/shape
BACKEND_URL=http://localhost:3003
REDIS_URL=redis://localhost:6379

runHazelBot Options

interface RunBotConfig<Commands> {
	// Slash commands
	commands?: Commands

	// Additional Effect layers
	layers?: readonly Layer[]

	// Setup function
	setup: (bot: HazelBotClient) => Effect<void>

	// Override config (optional)
	config?: Partial<HazelBotConfig>

	// Service name for tracing
	serviceName?: string
}

Example

runHazelBot({
	commands: myCommands,
	layers: [MyDatabaseLayer, MyApiLayer],
	setup: (bot) =>
		Effect.gen(function* () {
			// Register handlers
		}),
	config: {
		// Override defaults if needed
		electricUrl: "http://localhost:8787/v1/shape",
	},
	serviceName: "my-task-bot",
})

createHazelBot Options

For full control, use createHazelBot:

interface HazelBotConfig<Commands> {
	// Required
	botToken: string

	// URLs (with defaults)
	electricUrl?: string // Default: https://electric.hazel.sh/v1/shape
	backendUrl?: string // Default: https://api.hazel.sh
	redisUrl?: string // Default: redis://localhost:6379

	// Slash commands
	commands?: Commands

	// Queue configuration
	queueConfig?: EventQueueConfig

	// Dispatcher configuration
	dispatcherConfig?: EventDispatcherConfig

	// Tracing service name
	serviceName?: string
}

Example

const runtime = createHazelBot({
	botToken: process.env.BOT_TOKEN!,
	electricUrl: "http://localhost:8787/v1/shape",
	backendUrl: "http://localhost:3003",
	redisUrl: "redis://localhost:6379",
	commands: myCommands,
	serviceName: "my-bot",
})

Queue Configuration

Configure the event queue behavior:

interface EventQueueConfig {
	// Max events in queue
	capacity: number // Default: 1000

	// What to do when queue is full
	backpressureStrategy: "sliding" | "dropping" // Default: "sliding"
}
StrategyBehavior
slidingDrops oldest events when full
droppingDrops new events when full

Example

runHazelBot({
	config: {
		queueConfig: {
			capacity: 5000,
			backpressureStrategy: "sliding",
		},
	},
	// ...
})

Dispatcher Configuration

Configure event handler execution:

interface EventDispatcherConfig {
	// Max retry attempts
	maxRetries: number // Default: 3

	// Base delay for exponential backoff (ms)
	retryBaseDelay: number // Default: 100

	// Max concurrent handlers per event type
	maxConcurrentHandlers?: number | "unbounded" // Default: 10
}

Example

runHazelBot({
	config: {
		dispatcherConfig: {
			maxRetries: 5,
			retryBaseDelay: 200,
			maxConcurrentHandlers: 20,
		},
	},
	// ...
})

Adding Custom Layers

Provide additional Effect layers for dependency injection:

import { Effect, Layer } from "effect"
import { runHazelBot } from "@hazel/bot-sdk"

// Your custom service
class DatabaseService extends Effect.Service<DatabaseService>()("DatabaseService", {
	effect: Effect.succeed({
		query: (sql: string) => Effect.succeed([]),
	}),
}) {}

runHazelBot({
	layers: [DatabaseService.Default],
	setup: (bot) =>
		Effect.gen(function* () {
			const db = yield* DatabaseService

			yield* bot.onCommand(MyCommand, (ctx) =>
				Effect.gen(function* () {
					const results = yield* db.query("SELECT * FROM tasks")
					// ...
				}),
			)
		}),
})

Local Development

For local development, override the URLs:

# .env
BOT_TOKEN=dev-bot-token
ELECTRIC_URL=http://localhost:8787/v1/shape
BACKEND_URL=http://localhost:3003
REDIS_URL=redis://localhost:6379

Or in code:

runHazelBot({
	config: {
		electricUrl: "http://localhost:8787/v1/shape",
		backendUrl: "http://localhost:3003",
		redisUrl: "redis://localhost:6379",
	},
	// ...
})

On this page