---
title: "Build a Discord AI Bot with Agno (Teams, Memory, Knowledge Base)"
description: "A production-ready Discord AI bot with streaming responses, vector knowledge base, Cognee memory, team orchestration, and self-improvement tools."
date: 2026-02-06
categories: ["AI"]
tags: ["ai-tools","self-hosted","discord"]
---

import Notice from "@components/widgets/Notice.astro";
import Button from "@components/widgets/Button.astro";
import ListCheck from "@components/widgets/ListCheck.astro";
import Accordion from "@components/widgets/Accordion.astro";
import YouTubeEmbed from "@components/widgets/YouTubeEmbed.astro";

This guide walks through building a Discord AI bot using [Agno](https://github.com/agno-agi/agno). The bot streams responses in real-time, remembers conversations, searches a knowledge base, and can delegate work to specialized agents.

<Button text="View on GitHub" link="https://github.com/bitdoze/bitdoze_bot" variant="solid" color="purple" size="md" icon="github" />

<YouTubeEmbed
  url="https://www.youtube.com/embed/yoWGFO7tvpc"
  label="I Built a Personal AI Assistant in 90 Minutes"
/>

## What This Bot Does

- Responds when you `@mention` it in Discord
- Streams responses (you see the message update as it generates)
- Stores memories and learns your preferences over time
- Searches a knowledge base (LanceDb or PgVector)
- Runs scheduled tasks via cron
- Delegates complex work to agent teams

## Prerequisites

<ListCheck>
<ul>
<li>Python 3.12+</li>
<li>Discord bot token</li>
<li>Model API key (any OpenAI-compatible provider)</li>
<li>Optional: GitHub token for GitHub tools</li>
</ul>
</ListCheck>

If you're new to Python packaging, check out [UV](/uv-get-start/).

## Quick Start

```bash
git clone https://github.com/bitdoze/bitdoze_bot.git
cd bitdoze_bot
uv sync
python scripts/setup_bot.py
```

The setup wizard asks for your Discord token, API keys, and optional settings. It creates `~/.bitdoze-bot/` with everything you need.

## Discord Bot Setup

1. Go to [discord.com/developers](https://discord.com/developers)
2. Create an application, add a bot
3. Copy the token
4. Enable **Message Content Intent** (required)
5. Invite to your server with appropriate permissions

## Project Structure

```text
bitdoze-bot/
  main.py
  config.example.yaml
  docker-compose.yml
  bitdoze_bot/
    agents.py
    discord_bot.py
    cron.py
    heartbeat.py
    discovery_tools.py
    tool_permissions.py
    run_monitor.py
  scripts/
    setup_bot.py
    generate_soul.py
    setup_knowledge.py
  tests/
```

## Core Features

**Streaming**: Messages update in Discord as the agent generates content. You see progress instead of waiting for a complete response.

**Memory**: SQLite-backed storage for conversations. Optional Cognee integration for long-term memory with semantic search.

**Knowledge Base**: Vector search using LanceDb (no setup) or PgVector (requires PostgreSQL). Add documents to `workspace/knowledge/` and the bot can reference them.

**Teams**: Multiple agents that can collaborate. The delivery team might have an architect plan and a software engineer implement.

**Self-improvement**: Discovery tools let the bot save and search its own learnings. Combined with `learned_knowledge: agentic`, it decides when to store new insights.

**Automation**: Heartbeat checks every 30 minutes. Cron jobs run on a schedule from `workspace/CRON.yaml`.

**Tool permissions**: Runtime allow/deny rules with audit logging. Block shell access in public channels, allow it in private ones.

## Configuration

### Environment Variables

```env
DISCORD_BOT_TOKEN=your_discord_token
OPENAI_API_KEY=your_api_key
GITHUB_ACCESS_TOKEN=optional_github_token
```

### Basic Config

```yaml
model:
  provider: openai_like
  id: stepfun/step-3.5-flash:free
  base_url: https://openrouter.ai/api/v1
  api_key_env: OPENAI_API_KEY
  structured_outputs: false

discord:
  token_env: DISCORD_BOT_TOKEN

runtime:
  streaming_enabled: true
  streaming_edit_interval: 1.5
  agent_timeout: 600

memory:
  mode: automatic
  db_file: data/bitdoze.db
  enable_session_summaries: true

learning:
  enabled: true
  mode: always
  stores:
    user_profile: true
    user_memory: true
    learned_knowledge: agentic
```

### Streaming

Set `runtime.streaming_enabled: true` to see responses update in real-time. The bot edits the Discord message as content arrives. Falls back to non-streaming for team runs.

### Knowledge Base

```yaml
knowledge:
  enabled: true
  backend: lancedb  # or pgvector
  embedder: text-embedding-3-small
  lance_uri: data/lancedb
  table_name: bitdoze_knowledge
```

Run `python scripts/setup_knowledge.py` after adding documents to `workspace/knowledge/`.

### Cognee Memory (Optional)

```yaml
memory:
  cognee:
    enabled: true
    base_url: http://localhost:8000
    auto_sync_conversations: true
    auto_recall_enabled: true
    auto_recall_limit: 5
```

Start Cognee with `docker compose up -d`.

### Agents and Routing

```yaml
agents:
  default: main
  workspace_dir: workspace/agents
  definitions:
    - name: main
      tools: [web_search, website, github, file, discoveries]
    - name: research
      tools: [web_search, website, github]
      skills: [web-research]
  routing:
    rules:
      - agent: delivery-team
        starts_with: ["team:"]
      - agent: research
        contains: ["research:"]
```

### Teams

```yaml
teams:
  definitions:
    - name: delivery-team
      members: [architect, software-engineer]
      respond_directly: true
      determine_input_for_members: true
      delegate_to_all_members: false
      add_team_history_to_members: true
      num_team_history_runs: 5
```

<Notice type="warning" title="Team Configuration">
Avoid setting both `delegate_to_all_members: true` and `respond_directly: true` unless you want broadcast behavior. The bot will warn you.
</Notice>

## Add New Agents

Create a folder in `workspace/agents/<name>/`:

**agent.yaml**
```yaml
name: product-manager
enabled: true
model:
  id: glm-4.7
  base_url: https://api.z.ai/api/coding/paas/v4
  api_key_env: GLM_API_KEY
tools: []
skills: []
```

**AGENTS.md**
```md
# Product Manager Agent

Focus on scope, priorities, and delivery risk.
```

Add to a team in `config.yaml`:
```yaml
teams:
  definitions:
    - name: delivery-team
      members: [architect, software-engineer, product-manager]
```

## Use in Discord

Normal mention:
```text
@YourBot help me design a migration plan
```

Force a specific agent or team:
```text
@YourBot agent:research find papers on distributed systems
@YourBot agent:delivery-team Build and validate this feature
@YourBot team: implement the API with tests
```

## Heartbeat and Cron

**workspace/CRON.yaml**
```yaml
enabled: true
timezone: Europe/Bucharest
channel_id: 123456789012345678
jobs:
  - name: daily-status
    cron: "0 9 * * *"
    agent: main
    message: "Send a daily status update."
    session_scope: isolated
```

Heartbeat runs every 30 minutes using `workspace/HEARTBEAT.md`. If it returns `HEARTBEAT_OK`, the message is suppressed.

## Docker (PgVector + Cognee)

Optional PostgreSQL with pgvector and Cognee API:

```bash
docker compose up -d
```

This starts PostgreSQL on port 5532 and Cognee on `127.0.0.1:8000`.

## Tool Permissions

Control which tools can run where:

```yaml
tool_permissions:
  enabled: true
  default_effect: deny
  rules:
    - effect: allow
      tools: [shell]
      role_ids: [123456789012345678]
  audit:
    enabled: true
    path: logs/tool-audit.jsonl
```

## Production (systemd)

`~/.config/systemd/user/bitdoze-bot.service`
```ini
[Unit]
Description=Bitdoze Bot
After=network.target

[Service]
WorkingDirectory=/home/you/.bitdoze-bot
ExecStart=/home/you/.local/bin/uv run main.py
Restart=always
RestartSec=5
Environment=PYTHONUNBUFFERED=1
EnvironmentFile=/home/you/.bitdoze-bot/.env

[Install]
WantedBy=default.target
```

```bash
systemctl --user daemon-reload
systemctl --user enable --now bitdoze-bot
journalctl --user -u bitdoze-bot -f
```

## Scripts

| Script | Purpose |
|--------|---------|
| `scripts/setup_bot.py` | Interactive setup wizard |
| `scripts/generate_soul.py` | Generate SOUL.md personality |
| `scripts/setup_knowledge.py` | Initialize knowledge base |

## Tests

```bash
uv run pytest -q
```

## Related

- [UV Python Package Manager](/uv-get-start/)
- [Agno Getting Started](/agno-get-start/)

<Notice type="success" title="Ready to Run">
You now have a Discord AI bot with memory, knowledge search, team orchestration, and scheduled tasks. Clone the repo, run the setup wizard, and start chatting.
</Notice>