Repository navigation
Configuration
Configuration for csp-bot is driven by ccflow.
ccflow leverages Pydantic for type validation, and combines it with Hydra / OmegaConf for config-driven initialization.
The ccflow examples provide a nice overview of its functionality.
In csp-bot, this means commands, backends, and their settings are all controlled from a small set of composable yaml files.
csp-bot exposes two Hydra config groups:
-
gateway— assembles the bot module and thecsp-gatewayserver around it. -
backend— one fragment per chat platform (slack,discord,symphony,telegram), each contributing its configuration to the bot.
The backend group is what makes running against any mix of platforms easy.
Because each fragment writes to a different field of the bot config, you can select any combination of them at once.
The bare bot gateway has no backends of its own.
Add backends by listing them from the backend group:
# One backend
csp-bot-start +gateway=bot +backend='[slack]'
# Any combination — no dedicated config required
csp-bot-start +gateway=bot +backend='[slack,telegram]'
csp-bot-start +gateway=bot +backend='[slack,discord,symphony,telegram]'Each backend reads its credentials from environment variables, so nothing else is required on the command line. See Backends for the full list of variables.
For the common cases, ready-made gateway configs select the backends for you:
| Gateway | Backends |
|---|---|
+gateway=slack |
Slack |
+gateway=discord |
Discord |
+gateway=symphony |
Symphony |
+gateway=telegram |
Telegram |
+gateway=mixed |
Slack + Discord |
+gateway=all |
Slack + Discord + Symphony + Telegram |
+gateway=bot |
none — add your own with +backend
|
csp-bot-start +gateway=allSelecting backends from the command line is convenient, but a small yaml file is easier to version and share. Hydra unions configs, so a local file only needs to declare which gateway it builds on:
example/bot/slack.yaml
# @package _global_
defaults:
- /gateway: slack
- _self_
bot_name: CSP Bot
# Tokens are read from the environment: SLACK_BOT_TOKEN, SLACK_APP_TOKEN
# csp-bot-start --config-dir=example +bot=slackTo pick your own mix of backends in a file, build on the bare bot gateway and list them:
example/bot/custom.yaml
# @package _global_
defaults:
- /gateway: bot
- /backend:
- slack
- telegram
- _self_
bot_name: CSP BotRun either with:
csp-bot-start --config-dir=example +bot=slack
csp-bot-start --config-dir=example +bot=customA gateway config is built from the bare bot skeleton plus the selected backend fragments.
The bot gateway defines the bot module and an empty BotConfig:
# @package _global_
defaults:
- /modules
- _self_
bot_name: CSP Bot
modules:
bot:
_target_: csp_bot.Bot
config:
_target_: csp_bot.BotConfigEach backend fragment fills in one field of that BotConfig.
For example, the slack fragment:
# @package modules.bot.config
slack:
_target_: csp_bot.SlackConfig
bot_name: ${bot_name}
config:
_target_: chatom.slack.SlackConfig
bot_token: ${oc.env:SLACK_BOT_TOKEN}
app_token: ${oc.env:SLACK_APP_TOKEN}Selecting +backend='[slack,telegram]' merges the slack and telegram fragments into the same BotConfig, leaving the unused backends unset.
The per-platform config block is the corresponding chatom backend config, so any field that backend supports can be set here.
All of these configs live in-source under csp_bot/config; copy or extend them as the basis for your own.
Install the agent dependencies:
pip install "csp-bot[agent]"Define an agent command and its Hydra model:
from typing import Type
from pydantic_ai import Agent
from csp_bot.commands import AgentCommand, AgentCommandModel
class AskCommand(AgentCommand):
def command(self) -> str:
return "ask"
def name(self) -> str:
return "Ask"
def help(self) -> str:
return "Ask the configured model a question"
def build_agent(self, command):
toolset = self.build_toolset(command)
return Agent(
self.get_model(),
toolsets=[toolset] if toolset else [],
instructions="Answer questions using the available chat tools.",
)
def build_prompt(self, command) -> str:
return " ".join(command.args)
class AskCommandModel(AgentCommandModel):
command: Type[AgentCommand] = AskCommandSet model_name when registering the command:
gateway:
commands:
- _target_: my_bot.AskCommandModel
model_name: "github-copilot:<model>"model_name accepts PydanticAI's fully qualified model strings:
| Credential source | Model string |
|---|---|
| Anthropic API or configured gateway | anthropic:<model> |
| Codex login | openai-codex:<model> |
| GitHub Copilot token | github-copilot:<model> |
| OpenRouter API key | openrouter:<provider>/<model> |
Use codex login before selecting openai-codex:. For the other providers,
set the environment variables documented by PydanticAI for that provider.
Provider credentials are resolved by PydanticAI and are not stored by
csp-bot.
Install the separate Claude Agent SDK extra:
pip install "csp-bot[claude-agent]"Inherit from ClaudeAgentCommand when the command should run through the
Claude Agent SDK rather than a PydanticAI model provider:
from typing import Type
from csp_bot.commands import AgentCommand, AgentCommandModel, ClaudeAgentCommand
class ClaudeAskCommand(ClaudeAgentCommand):
def command(self) -> str:
return "claude"
def name(self) -> str:
return "Claude"
def help(self) -> str:
return "Ask Claude a question"
def build_prompt(self, command) -> str:
return " ".join(command.args)
class ClaudeAskCommandModel(AgentCommandModel):
command: Type[AgentCommand] = ClaudeAskCommandRegister it with a Claude model name:
gateway:
commands:
- _target_: my_bot.ClaudeAskCommandModel
model_name: "claude-sonnet-4-6"The Claude runtime exposes only the invocation backend's Chatom MCP tools. It does not enable Claude Code's file, shell, or ambient project tools. Claude Agent SDK authentication is resolved by the SDK in the bot process environment.
This wiki is autogenerated. To made updates, open a PR against the original source file in docs/wiki.
Get Started
For Developers
Coming soon!
For Contributors