Skip to content

agent-chatbot

Chat platform agent — Discord/Slack integration

agent-chatbot is a consolidated KĀDI agent that handles inbound event listening and outbound message sending for Discord and Slack. It centralizes functionality that was previously split across multiple repos (Discord & Slack listeners and tools), connects to one or more KĀDI brokers, loads secrets from vaults, and exposes platform-specific tools for use by other agents in the ecosystem.

  • Broker connection: The agent connects to a primary KĀDI broker (local or remote) and can optionally configure an additional broker. The connection is created via agents-library/BaseAgent which exposes a KadiClient used for tool registration and messaging.
  • Platform clients: Two platform client modules implement protocol-specific behavior:
    • DiscordPlatformClient (platforms/discord/client.js)
    • SlackPlatformClient (platforms/slack/client.js)
  • Listeners: For each enabled platform the agent spins up a Listener:
    • DiscordListener (platforms/discord/listener.js)
    • SlackListener (platforms/slack/listener.js) Listeners handle incoming platform events and publish them to the broker as events/messages.
  • Tools: registerDiscordTools and registerSlackTools register platform tools with the Kādi broker (so other agents can send messages or perform platform actions).
  • Secrets/vaults: Secrets (tokens, signing secrets, DB creds) are loaded at startup using loadVaultCredentials; agent.json config contains vault definitions and required keys.
  • Logging & metrics: agents-library utilities setLogLevel, setAgentTag, logger and timer provide consistent logging and startup timing.

Data flow

  1. Startup: readConfig -> loadVaultCredentials -> create BaseAgent -> obtain KadiClient.
  2. Tool registration: platform tools registered against the broker so other agents can call them.
  3. Runtime: Platform listeners translate platform events into internal events and publish them to broker; tools accept inbound requests from broker and send messages through platform clients.
  4. Optional: agent writes logs to an ArcadeDB instance (configurable).

How it fits in AGENTS ecosystem

  • Acts as a platform gateway agent: both publishes platform events and exposes platform APIs as Kādi tools for other agents/clients.
  • Depends on secret-ability for vault access and ability-log for structured logging (declared in agent.json).
  • Provides reusable platform tools so other agents (e.g., bots, automation agents) can send messages to Slack/Discord without owning tokens.

The source registers/imports a set of tool registration functions and utilities. The table below documents the main functions/modules referenced in the codebase and what they provide.

Tool / FunctionLocation (module)Purpose / DescriptionKey parameters (usage)
registerDiscordTools./platforms/discord/tools.jsRegisters Discord-related tools (send message, manage reactions, etc.) with the Kādi broker so other agents can invoke them.Called during startup after DiscordPlatformClient and KadiClient are available.
registerSlackTools./platforms/slack/tools.jsRegisters Slack-related tools (post message, open modal, etc.) with the Kādi broker.Called during startup after SlackPlatformClient and KadiClient are available.
DiscordPlatformClient./platforms/discord/client.jsEncapsulates Discord API logic and websocket/client lifecycle for sending messages and receiving client-level actions.Constructed when Discord platform is enabled and token is present.
SlackPlatformClient./platforms/slack/client.jsEncapsulates Slack Bolt / Web API logic and HTTP listener lifecycle (for slash commands / events).Constructed when Slack platform is enabled and token + signing secret are present.
DiscordListener./platforms/discord/listener.jsListens for Discord events and translates them into broker events/messages.Started when Discord is ready.
SlackListener./platforms/slack/listener.jsListens for Slack events (HTTP port) and translates them into broker events/messages.Started when Slack is ready.
loadVaultCredentialsagents-libraryLoads secrets from configured vaults (used for DISCORD_TOKEN, SLACK_BOT_TOKEN, SLACK_SIGNING_SECRET, etc.).No args; returns an object with vault keys.
readConfigagents-libraryReads and exposes config.toml values via typed accessors (string/number/bool/strings).Use cfg.string(‘path’), cfg.bool(‘path’), cfg.number(‘path’), cfg.strings(‘path’)
BaseAgent / KadiClientagents-library / @kadi.build/coreBaseAgent constructs the broker client; KadiClient is used for registering tools and publishing events.BaseAgent({ agentId, agentRole, version, brokerUrl, networks, additionalBrokers? })
logger, timer, setLogLevel, setAgentTagagents-libraryLogging and timing helpers used across agent lifecycle.setLogLevel(level), setAgentTag(id), logger.info/error(id, msg, ms)

Note: The actual tool RPC names (e.g., chat/sendMessage) are defined inside the platform tool registration modules (platforms/*/tools.js). Inspect those files to find the exact tool names and payload schemas for cross-agent calls.

This agent reads config.toml and uses environment variables and vault secrets.

Key config.toml fields (as present in repo):

  • [agent]
    • ID = “agent-chatbot”
    • ROLE = “chatbot”
    • VERSION = “0.1.0”
  • [broker.remote]
    • URL = “wss://broker.kadi.build/kadi”
    • NETWORKS = [“chatbot”]
  • [bot.discord]
    • ENABLED = true
    • USER_ID = “1438685741751210025”
    • GUILD_ID = ""
  • [bot.slack]
    • ENABLED = true
    • USER_ID = “U09SCDV78AK”
    • HTTP_PORT = 3700
  • [logging]
    • LEVEL = “debug”
  • [secrets]
    • VAULTS = [“chatbot”, “arcadedb”]
    • KEYS = [“DISCORD_TOKEN”, “SLACK_BOT_TOKEN”, “SLACK_SIGNING_SECRET”, “ARCADE_USERNAME”, “ARCADE_PASSWORD”]
  • [arcadedb]
    • HOST = “arcadedb.dadavidtseng.com”
    • PORT = 443
    • USERNAME = “root”
    • DATABASE = “agents_logs”

Environment variables (overrides / runtime toggles):

  • KADI_BROKER_URL_LOCAL, KADI_BROKER_URL_REMOTE — override broker URL(s)
  • KADI_NETWORK_LOCAL, KADI_NETWORK_REMOTE — override networks (comma-separated)
  • DISCORD_ENABLED, SLACK_ENABLED — true/false to override the config toggles
  • DISCORD_BOT_USER_ID, DISCORD_GUILD_ID — override Discord IDs
  • SLACK_BOT_USER_ID, SLACK_HTTP_PORT — override Slack config
  • DISCORD_TOKEN, SLACK_BOT_TOKEN, SLACK_SIGNING_SECRET — direct token overrides (if set, may avoid vault access)
  • NODE_ENV — production/dev
  • ARCADE_HOST, ARCADE_PORT — used in agent.json deploy environment for ArcadeDB

Secrets / Vaults (declared in agent.json deploy.secrets and config.toml):

  • Vaults: “chatbot”, “arcadedb”
  • Required keys in “chatbot” vault:
    • DISCORD_TOKEN
    • SLACK_BOT_TOKEN
    • SLACK_SIGNING_SECRET
  • Required keys in “arcadedb” vault:
    • ARCADE_USERNAME
    • ARCADE_PASSWORD These are loaded via loadVaultCredentials() at startup (see code examples).

Below are key patterns copied directly from src/index.ts showing startup, configuration, broker setup, and BaseAgent creation.

import { KadiClient } from '@kadi.build/core';
import {
readConfig,
loadVaultCredentials,
setLogLevel,
setAgentTag,
logger,
timer,
} from 'agents-library';
// Platform modules
import { DiscordPlatformClient } from './platforms/discord/client.js';
import { registerDiscordTools } from './platforms/discord/tools.js';
import { DiscordListener } from './platforms/discord/listener.js';
import { SlackPlatformClient } from './platforms/slack/client.js';
import { registerSlackTools } from './platforms/slack/tools.js';
import { SlackListener } from './platforms/slack/listener.js';

Startup and configuration parsing (direct copy):

const cfg = readConfig();
// Agent identity
const agentId = cfg.string('agent.ID');
const agentRole = cfg.string('agent.ROLE');
const agentVersion = cfg.string('agent.VERSION');
const logLevel = cfg.has('logging.LEVEL') ? cfg.string('logging.LEVEL') : 'info';
setLogLevel(logLevel);
setAgentTag(agentId);
// Broker resolution: at least one of local/remote required
const hasLocal = cfg.has('broker.local.URL');
const hasRemote = cfg.has('broker.remote.URL');
if (!hasLocal && !hasRemote) {
throw new Error('At least one broker required: set [broker.local] or [broker.remote] in config.toml');
}
const brokerUrl = hasLocal
? (process.env.KADI_BROKER_URL_LOCAL ?? cfg.string('broker.local.URL'))
: (process.env.KADI_BROKER_URL_REMOTE ?? cfg.string('broker.remote.URL'));
const networks = hasLocal
? (process.env.KADI_NETWORK_LOCAL?.split(',') ?? cfg.strings('broker.local.NETWORKS'))
: (process.env.KADI_NETWORK_REMOTE?.split(',') ?? cfg.strings('broker.remote.NETWORKS'));

Secrets loading and readiness checks (direct copy):

// Load secrets from vault
const vault = await loadVaultCredentials();
const discordToken = process.env.DISCORD_TOKEN ?? vault.DISCORD_TOKEN ?? '';
const slackBotToken = process.env.SLACK_BOT_TOKEN ?? vault.SLACK_BOT_TOKEN ?? '';
const slackSigningSecret = process.env.SLACK_SIGNING_SECRET ?? vault.SLACK_SIGNING_SECRET ?? '';
// Determine which platforms are actually usable
const isDiscordReady = discordEnabled && !!discordToken;
const isSlackReady = slackEnabled && slackBotToken.startsWith('xoxb-');

BaseAgent creation and KadiClient access (direct copy):

// Step 1: Create KĀDI client via BaseAgent
const { BaseAgent } = await import('agents-library');
const baseAgent = new BaseAgent({
agentId,
agentRole,
version: agentVersion,
brokerUrl,
networks,
...(additionalBrokerUrl && {
additionalBrokers: {
remote: { url: additionalBrokerUrl, networks: additionalBrokerNetworks! },
},
}),
});
this.kadiClient = baseAgent.client;

Platform initialization (snippet start, direct copy):

// Step 2: Initialize enabled platforms
if (isDiscordReady) {
// Discord-specific initialization continues in source...
}

For full usage patterns for tool registration and listener lifecycle, see the platform modules:

  • platforms/discord/tools.js
  • platforms/discord/client.js
  • platforms/discord/listener.js
  • platforms/slack/tools.js
  • platforms/slack/client.js
  • platforms/slack/listener.js

Runtime packages (package.json / dependencies):

  • @kadi.build/core ^0.9.0 — Kādi client primitives
  • agents-library ^0.1.14 — helpers: BaseAgent, readConfig, loadVaultCredentials, logger, timer, setLogLevel, setAgentTag
  • discord.js ^14.16.3 — Discord API client (used by DiscordPlatformClient)
  • @slack/bolt ^4.1.0, @slack/web-api ^7.11.0 — Slack API & Bolt framework (used by SlackPlatformClient)
  • zod ^3.24.1 — runtime validations (likely used in tools/handlers)

Dev dependencies:

  • typescript, tsx, @types/node, etc.

Declared agent abilities (from agent.json):

  • secret-ability — allows the agent to access secrets/vaults (used by loadVaultCredentials)
  • ability-log ^0.1.5 — structured logging ability for centralized logs

What depends on it

  • Other agents that wish to send messages to Slack or Discord should call the tools registered by this agent (via the broker). This agent serves as the canonical platform gateway for the “chatbot” network.
  • Configuration precedence: explicit environment variables take precedence over config.toml values.
  • Vaults: production deployments should deliver secrets via Kādi secret vaults (agent.json deploy.secrets defines required keys).
  • Tool names & payload schemas are defined inside platforms/*/tools.js; modify those files to change RPC signatures exposed to other agents.
  • To add a new platform: implement a PlatformClient and Listener pair, and a registerXTools function to expose platform actions through the KadiClient.

If you need help locating a specific tool RPC name or payload schema, open the corresponding platforms/*/tools.js file — tool registration details and RPC names are defined there.