No description
  • TypeScript 99.9%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-06-09 09:27:06 -04:00
data System Prompt Refactor 2025-09-15 12:42:51 -04:00
src Kagi API v1 2026-06-09 09:27:06 -04:00
.dockerignore Docker Hub Image 2025-05-21 11:56:46 -04:00
.env.example /ask - Any LLM + Kagi Search 2025-09-16 13:07:29 -04:00
.gitignore System Prompt Refactor 2025-09-15 12:42:51 -04:00
bun.lock Kagi API v1 2026-06-09 09:27:06 -04:00
docker-compose.yml query limiting 2025-05-19 09:24:47 -04:00
Dockerfile inital release 2025-04-30 09:28:16 -04:00
index.ts inital release 2025-04-30 09:28:16 -04:00
package.json Kagi API v1 2026-06-09 09:27:06 -04:00
README.md Kagi API v1 2026-06-09 09:27:06 -04:00
tsconfig.json inital release 2025-04-30 09:28:16 -04:00

Kagi Discord Bot

A Discord bot that integrates with the Kagi API to provide powerful search capabilities directly within Discord.

Test the discord bot and kagi api in this server: https://discord.gg/km4rpZBZfM

image image

Features

This bot provides slash commands to interact with Kagi API:

  1. /fastgpt - Query the Kagi FastGPT API for AI-powered answers
  2. /ask - Let an OpenRouter/OpenAI-compatible LLM plan searches and craft an answer with citations
  3. /websearch - Search small-web and web results using the Kagi Search API
  4. /newssearch - Search news results using the Kagi Search API
  5. /summarize - Summarize URLs, text, or channel conversations using the Kagi Universal Summarizer API
  6. /search - Search Kagi with workflows, filters, lenses, personalization, and result extraction
  7. /extract - Extract markdown content from up to 10 URLs using the Kagi Extract API
  8. /limits - Check your remaining query limits

Prerequisites

Setup

Environment Configuration

Create a .env file in the root directory with the following content:

# Discord Bot Token
DISCORD_TOKEN=your_discord_token_here

# Discord Client ID
CLIENT_ID=your_client_id_here

# Kagi API Key
KAGI_API_KEY=your_kagi_api_key_here

# LLM Provider (OpenRouter or any OpenAI-compatible API)
# Leave blank when using providers that do not require authentication (e.g., local Ollama)
LLM_API_KEY=your_llm_api_key_here
# LLM_API_BASE_URL=https://openrouter.ai/api/v1
LLM_MODEL=openrouter/auto
# ASK_MODEL=meta-llama/llama-3.1-8b-instruct:free
# ASK_REWRITE_MODEL=openai/gpt-4o-mini
# ASK_RESULTS_PER_QUERY=4
# ASK_MAX_TOTAL_RESULTS=8
# ASK_MAX_TOKENS=4000
# ASK_TEMPERATURE=1.0
# ASK_REWRITE_TEMPERATURE=0.2
# LLM_HTTP_REFERER=https://your-site.example
# LLM_APP_NAME=Kagi Discord Bot



# Message Content Intent (set to 'true' to enable channel summarization)
# Note: For bots in more than 100 servers, Discord requires verification
# and approval to use this intent. Set to 'false' for large-scale bots.
MESSAGE_CONTENT_ENABLED=true

# Allow Commands in Direct Messages (set to 'true' to allow commands in DMs)
ALLOW_DM_COMMANDS=false

# Allow the expensive Muriel engine ($1 per summary)
ALLOW_MURIEL_ENGINE=false

# Create threads for results when needing to send more than one message (set to 'true' to automatically create threads)
CREATE_THREADS_FOR_RESULTS=true

# Comma-separated list of Discord user IDs that have unlimited queries (bypass all limits)
UNLIMITED_QUERY_USERIDS=

# Query Limits Configuration
# Limits are per Discord user. Use -1 for unlimited.
# Available periods: hourly, daily, weekly, monthly

# Global query limit (applies to all commands combined)
QUERY_LIMIT_GLOBAL=50
QUERY_LIMIT_GLOBAL_PERIOD=daily

# Command-specific limits (optional)
QUERY_LIMIT_FASTGPT=20
QUERY_LIMIT_FASTGPT_PERIOD=daily

QUERY_LIMIT_WEBSEARCH=15
QUERY_LIMIT_WEBSEARCH_PERIOD=daily

QUERY_LIMIT_NEWSSEARCH=15
QUERY_LIMIT_NEWSSEARCH_PERIOD=daily

QUERY_LIMIT_SUMMARIZE=10
QUERY_LIMIT_SUMMARIZE_PERIOD=daily

QUERY_LIMIT_SEARCH=10
QUERY_LIMIT_SEARCH_PERIOD=daily

QUERY_LIMIT_ASK=10
QUERY_LIMIT_ASK_PERIOD=daily

QUERY_LIMIT_EXTRACT=10
QUERY_LIMIT_EXTRACT_PERIOD=daily

# Set to 'true' to persist query counts between bot restarts
QUERY_LIMITS_PERSIST=true

Using Docker

Option 1: Build and run using docker-compose

  1. Build and start the Docker container:
git clone https://github.com/0xgingi/kagi-discord-bot
cd kagi-discord-bot
docker compose up -d

To rebuild the container after code changes:

git pull
docker compose up -d --build

To view logs:

docker compose logs -f

To stop the container:

docker compose down

Option 2: Pull from Docker Hub

You can use the pre-built Docker image from Docker Hub:

  1. Create a .env file as described above
  2. Create the data/ directory
  3. Create the data/query_record.json file
  4. Run the container:
docker run -d --name kagi-discord-bot --restart unless-stopped --env-file .env -v $(pwd)/data:/app/data 0xgingi/kagi-discord-bot:latest

Using Bun (Local Development)

  1. Clone and Install dependencies:
git clone https://github.com/0xgingi/kagi-discord-bot
cd kagi-discord-bot
bun install
  1. Start the bot:
bun start

Adding the Bot to Your Server

  1. Go to the Discord Developer Portal
  2. Select your application
  3. Go to the "Bot" section
  4. If you want to use the channel summarization feature:
    • Enable the "Message Content Intent" under "Privileged Gateway Intents"
    • Note: For bots in more than 100 servers, Discord requires verification and approval for this intent
    • Set MESSAGE_CONTENT_ENABLED=true in your .env file
  5. For bots in many servers (>100) without verified intents:
    • Set MESSAGE_CONTENT_ENABLED=false in your .env file
    • The /summarize channel command will be disabled automatically
  6. Go to the "OAuth2" section
  7. In the URL Generator, select the following scopes:
    • bot
    • applications.commands
  8. In the bot permissions section, select:
    • Send Messages
    • Embed Links
    • Use Slash Commands
    • Read Message History
  9. Copy the generated URL and open it in your browser to add the bot to your server

Usage

Once the bot is added to your server, you can use the following slash commands:

FastGPT

/fastgpt query: Your question here [file: Optional] [cache: Optional] [prompt: Optional]

Available options:

  • file: Upload a file to include in your query (PDF, code files, text files, etc.)
  • cache: Whether to allow cached responses (default: true)
  • prompt: Name of a system prompt stored in data/prompts.json

File limitations:

  • Maximum file size: 10MB
  • Content is truncated to 8,000 characters if longer
  • For PDFs: Only text-based PDFs work (scanned/image PDFs may fail)

Ask

/ask question: Explain topic here [results: Optional] [prompt: Optional]

How it works:

  • The bot asks your configured LLM (OpenRouter/OpenAI compatible) to rewrite the question into focused web search queries.
  • Each generated query hits the Kagi Search API; snippets are passed back to the LLM with the original question.
  • The model synthesizes an answer and cites the referenced sources using [n] markers.

Options:

  • results: Limit how many links are fetched per generated search query (defaults to 4, max 8).
  • prompt: Choose a system prompt from data/prompts.json to steer tone or behaviour.

Make sure LLM_API_KEY is configured before using /ask. If you're using a local provider that doesn't require authentication (e.g., Ollama), leave LLM_API_KEY empty and point LLM_API_BASE_URL to your local endpoint. Tune the LLM creativity via ASK_TEMPERATURE (default 1.0) and the search-query planner via ASK_REWRITE_TEMPERATURE (default 0.2) in your environment settings. Increase ASK_MAX_TOKENS if you need longer answers (default 4,000; supports up to 128,000 tokens when the model allows it).

System Prompts

  • Store named prompts in data/prompts.json as a simple key-value map. Example:
{
  "helpful": "You are a helpful assistant. Answer concisely.",
  "tarantulas": "Only answer about tarantulas, refuse to answer anything else."
}
  • Default prompt: If no prompt is selected, the bot uses the default prompt from data/prompts.json. If default is missing, no system prompt is applied.
  • Use with /fastgpt ... prompt: helpful to apply the selected system prompt.
  • If an unknown prompt is provided, the bot lists available names.
  • You can add unlimited prompts by editing data/prompts.json. When running via Docker, ensure -v $(pwd)/data:/app/data is set so changes persist.
  • You can also reference a file relative to data/ for prompts by using the special value @file:<path>. Files must reside under the data/ directory. Supports Markdown/Text and PDFs (PDFs are parsed to text on demand). Example:
{
  "default": "You are a helpful assistant. Answer concisely.",
  "style_guide": "@file:example_prompt.md"
}
  • For PDFs or large documents, point to a file under data/ (e.g., @file:guide.pdf). The bot will extract text (truncated to 8,000 characters) when used.

Managing Prompts

  • Edit data/prompts.json directly to add, change, or remove prompt entries.
/websearch query: Your search query

Uses the new Kagi Search API and prioritizes interesting_finds plus regular web results.

/newssearch query: Your search query

Uses the Kagi Search API news workflow and includes news plus interesting_news results.

/search query: Your search query [workflow: Optional] [display: Optional] [limit: Optional]

Available options:

  • workflow: Result workflow to request: search, images, videos, news, or podcasts.
  • display: Number of results to show in Discord (1-10, default: 5).
  • limit: Maximum API results to request (1-1024).
  • page: Search result page (1-10).
  • timeout: Search timeout in seconds (0.5-4).
  • safe_search: Enable or disable safe search.
  • format: Request json or experimental markdown output.
  • lens_id: Built-in lens ID, shared lens ID, or full Kagi lens URL.
  • Inline lens options: sites_include, sites_exclude, keywords_include, keywords_exclude, file_type, time_after, time_before, time_relative, and search_region.
  • Result filters: region, after, and before.
  • extract_count and extract_timeout: Extract markdown into top search result snippets. This uses Extract API units.
  • domain_rules: Personalization rules like block:example.com, raise:docs.example.com.
  • regex_replacements: Regex personalization rules, one per line, like ^https?://www\.reddit\.com=>https://old.reddit.com.

Extract

/extract urls: https://example.com/article [timeout: Optional] [format: Optional]

Available options:

  • urls: One to ten HTTPS URLs, separated by spaces, commas, or new lines.
  • timeout: Bulk extraction timeout in seconds (0.5-10).
  • format: Return json summaries or experimental raw markdown.

Universal Summarizer

For URLs:

/summarize url url: The URL to summarize [engine: Optional] [summary_type: Optional] [target_language: Optional]

For text:

/summarize text text: The text to summarize [engine: Optional] [summary_type: Optional] [target_language: Optional]

For channel messages (requires MESSAGE_CONTENT_ENABLED=true):

/summarize channel [messages: Optional] [engine: Optional] [summary_type: Optional] [target_language: Optional]

Available options:

  • engine:
    • cecil (Default) - Friendly, descriptive, fast
    • agnes - Formal, technical, analytical
    • muriel - Best-in-class, enterprise-grade ($1 per summary)
  • summary_type:
    • summary - Paragraph(s) of prose
    • takeaway (Default) - Bulleted list of key points
  • target_language: Various language options (EN, ES, FR, etc.)
  • messages: Number of recent messages to include in channel summary (1-100, default: 20)

Check Query Limits

/limits

Displays your remaining query counts for all commands, based on your server's configuration.

Query Limits

The bot includes a configurable query limiting system to control API usage:

  • Per-User Tracking: All limits are applied per Discord user ID
  • Global Limits: Set a maximum number of queries across all commands
  • Command-Specific Limits: Set separate limits for each command
  • Time Period Options: Configure limits by hour, day, week, or month
  • Persistence: Optionally persist query records between bot restarts

Configure limits in your .env file. Set any limit to -1 for unlimited queries.

Pricing

The bot uses paid Kagi API endpoints. Check the current Kagi API Pricing page before enabling public access or high limits.

For convenience, the /summarize command displays estimated costs for the legacy summarizer endpoint. /search extract_count and /extract can incur Extract API charges.

License

MIT