Cogitator
Channels

Wizard Setup

Interactive assistant setup with cogitator wizard.

Overview

The cogitator wizard command provides an interactive TUI to configure a personal AI assistant. It generates a cogitator.yml config and .env file with all required secrets.

Quick Start

npx @cogitator-ai/cli wizard

The wizard walks you through:

  1. Names — your name and the assistant's name (used in the default personality)
  2. LLM provider and model — Google, Anthropic, OpenAI, or Ollama (local, or a remote/cloud URL with an optional API key); models are fetched live
  3. Channels — Telegram, Discord, Slack: bot token and owner user IDs (Slack also asks for the signing secret and an optional xapp- app token for Socket Mode). The terminal channel is always on
  4. Capabilities — web search, file system (allowed paths), GitHub (token), device tools, browser (visible window / stealth), scheduler, RAG (paths to index), self-config, self-tools
  5. MCP servers — any command line, quoted arguments supported
  6. Memory — SQLite database path
  7. Personality — the system prompt, pre-filled from the names above

The wizard sets up only Telegram, Discord and Slack. Add WhatsApp and WebChat to cogitator.yml by hand; --edit keeps those entries.

Secrets are merged into .env (written with mode 0600) without removing your other variables or comments. If cogitator.yml already exists, the wizard asks before overwriting it.

After setup, start the assistant:

cogitator up

cogitator up finds cogitator.yml (or cogitator.yaml, or --config <path>) in the current directory, reads .env next to it, builds the runtime with RuntimeBuilder and starts every channel. up runs the assistant in a child process and restarts it whenever it exits with code 78 — the owner /restart command and self-config updates; --no-restart-loop runs it in-process without that supervisor, so /restart just stops it.

Editing an Existing Config

Re-run the wizard with --edit to modify an existing cogitator.yml:

cogitator wizard --edit

This loads the current config and pre-fills every prompt. Leaving a secret blank keeps the value already in .env; existing MCP servers and settings the wizard does not ask about (security, rate limits, stream tuning, compaction) are preserved. The wizard only sets up SQLite memory, but a memory.adapter: postgres config is kept as is (the SQLite path prompt is skipped). channels.whatsapp and channels.webchat, which the wizard does not ask about, are kept too.

Generated Files

cogitator.yml

cogitator.yml
name: jarvis
personality: |-
  You are jarvis, a personal AI assistant for Alex.
  Be concise, friendly, and proactive. Use tools when they can help.
  Remember important things about Alex using memory tools.
llm:
  provider: google
  model: google/gemini-3.8-flash
channels:
  telegram:
    ownerIds:
      - '123456789'
capabilities:
  webSearch: true
  scheduler: true
memory:
  adapter: sqlite
  path: ~/.cogitator/memory.db
  autoExtract: true
  knowledgeGraph: true
  compaction:
    threshold: 50
stream:
  flushInterval: 600
  minChunkSize: 30

.env

.env
GOOGLE_API_KEY=your-api-key
TG_TOKEN=your-telegram-bot-token

Programmatic Equivalent

Instead of the wizard, you can use RuntimeBuilder directly. It validates the config with AssistantConfigSchema and fills in the schema defaults, so only name, personality and llm are required:

import { RuntimeBuilder } from '@cogitator-ai/channels';

const builder = new RuntimeBuilder(
  {
    name: 'jarvis',
    personality: 'You are Jarvis, a personal AI assistant for Alex.',
    llm: { provider: 'google', model: 'google/gemini-3.8-flash' },
    channels: { telegram: { ownerIds: ['123456789'] } },
    capabilities: { webSearch: true, scheduler: true },
    memory: { path: '~/.cogitator/memory.db', compaction: { threshold: 50 } },
  },
  process.env
);

const runtime = await builder.build();
await runtime.gateway.start();

process.on('SIGTERM', async () => {
  await runtime.cleanup(); // stops the scheduler and gateway, closes memory, MCP and browser
  process.exit(0);
});

build() returns { agent, cogitator, gateway, scheduler, cleanup }; scheduler is null unless capabilities.scheduler is on. An invalid config throws a ZodError from the constructor. The optional third argument takes:

OptionDescription
configPathPath of cogitator.yml, needed (with configHelpers) for the selfConfig tools
configHelpers{ parseYaml, stringifyYaml, validateConfig } used by the config_read / config_update tools
onRestartCalled on /restart or after a config update; default process.exit(78) (RESTART_EXIT_CODE)
hooksHookRegistry passed to the gateway (see Lifecycle Hooks)
approvalsGatewayApprovalsConfig merged over the config's approvals block; the code value wins, so use it for what YAML cannot hold, such as a custom format

The second argument is the environment the runtime reads keys and tokens from; it is not copied into process.env.

Config Reference

cogitator.yml is validated by AssistantConfigSchema (exported from @cogitator-ai/channels, with AssistantConfigInput / AssistantConfigOutput types).

FieldTypeDefaultDescription
namestringrequiredAssistant name (also the agent name and memory namespace)
personalitystringrequiredSystem prompt; date, core facts and capability notes are appended
llm.providergoogle | openai | anthropic | ollamarequiredLLM provider
llm.modelstringrequiredModel id; the provider prefix is added when missing (e.g. google/gemini-3.8-flash)
channels.telegram / discord / slack{ ownerIds?: string[] }—Enables the channel; the first owner id gets owner commands and self-config access
channels.whatsapp{ ownerIds?: string[], sessionPath?: string }session ~/.cogitator/whatsapp-sessionWhatsApp; owner ids are phone numbers without @s.whatsapp.net
channels.webchat{ port?: number, path?: string }port: 8080, path: '/ws'WebChat; starts only with WEBCHAT_TOKEN set, has no owners
capabilities.webSearchboolean—web_search tool, added only when a Tavily, Brave or Serper key is set
capabilities.fileSystem.pathsstring[]home dirfile_* tools, restricted to these paths
capabilities.githubboolean—github_api tool (needs GITHUB_TOKEN)
capabilities.deviceToolsboolean—Clipboard, system info and screenshot tools
capabilities.browserboolean | { headless, stealth }headless: truePlaywright browser tools via @cogitator-ai/browser (Chromium is installed on first run)
capabilities.schedulerboolean—Scheduler tools and heartbeat
capabilities.rag.pathsstring[]—Index these paths with @cogitator-ai/rag (needs an embedding key for the provider)
capabilities.selfConfigboolean—Config/env tools — usable only by channel owners and the local terminal
capabilities.selfToolsboolean | { path }~/.cogitator/toolscreate_tool & co.; created tools load on restart, create_tool asks for approval in chat
mcpServers.<name>{ command, args, env? }—Stdio MCP servers whose tools are added (needs @cogitator-ai/mcp)
memory.adaptersqlite | postgressqliteMemory storage backend
memory.pathstring~/.cogitator/memory.dbSQLite file (also holds core facts with Postgres)
memory.connectionStringstringDATABASE_URLPostgres connection (or POSTGRES_URL; the graph needs pg)
memory.knowledgeGraphbooleantrueKnowledge graph and remember / recall / forget tools
memory.autoExtractbooleantrueAuto-extract entities from conversations
memory.compaction.thresholdnumber—Messages in a conversation before compaction (keeps the 10 newest)
security.dmPolicyopen | allowlist | pairing | disabledopenWho may DM the assistant (see DM Policy)
security.allowliststring[]—Allowed users, telegram:42 or bare ids
security.groupPolicyopen | allowlist | disabledopenWhich group chats the assistant answers
security.groupAllowliststring[]—Allowed group/chat ids
security.storePathstring~/.cogitator/dm-allowlist.jsonWhere paired users are saved
security.commandAccess.authorizedstring[]—Users who may run /status, /sessions, /help
security.commandAccess.publicCommandsstring[]—Owner commands anyone may run
stream.flushIntervalnumber600Stream flush interval (ms)
stream.minChunkSizenumber30Minimum buffered text before a flush
rateLimit.maxPerMinutenumber30Per-user rate limit, applied only when rateLimit is set
approvals.approveWords / denyWordsstring[]approve, yes, да, одобряю / deny, no, нет, отклоняюReplies that answer a tool approval prompt; replace the defaults
approvals.notAllowedMessagestringEnglish noticeSent when someone other than the run's user answers

Without a security block no DM policy is applied and everyone can talk to the assistant. Owner commands are enabled when at least one channel has ownerIds. Tool approvals in chat use the default reply words unless the approvals block sets others; a custom prompt format can only be set in code (RuntimeBuilder's approvals option).

WhatsApp and WebChat

cogitator.yml
channels:
  whatsapp:
    ownerIds:
      - '15551234567'
    sessionPath: ~/.cogitator/whatsapp-session
  webchat:
    port: 8080
    path: /ws
approvals:
  approveWords: [approve, yes, ok]
  denyWords: [deny, no]
  notAllowedMessage: Only the requester can answer this.

WhatsApp needs @whiskeysockets/baileys (and qrcode-terminal to print the pairing QR) and pairs on the first cogitator up. WebChat needs ws and WEBCHAT_TOKEN in .env; without the token the channel is skipped with a warning, since an open socket would give anyone the assistant's tools. Clients connect to ws://host:8080/ws?token=<WEBCHAT_TOKEN>.

Environment Variables

RuntimeBuilder reads these from the environment it is given (cogitator up: the process environment plus .env):

VariableUsed for
GOOGLE_API_KEY (or GEMINI_API_KEY), OPENAI_API_KEY, ANTHROPIC_API_KEYLLM provider (and RAG embeddings; Anthropic uses OPENAI_API_KEY for them)
OLLAMA_URL (default http://localhost:11434), OLLAMA_API_KEYOllama, local or remote
TG_TOKEN (or TELEGRAM_TOKEN), DISCORD_TOKENTelegram and Discord bots
SLACK_BOT_TOKEN, SLACK_SIGNING_SECRET, SLACK_APP_TOKEN, SLACK_PORTSlack (Socket Mode with the app token, else HTTP mode on SLACK_PORT)
WEBCHAT_TOKENWebChat client token (?token=); WebChat does not start without it
DATABASE_URL / POSTGRES_URLPostgres memory without memory.connectionString
DEEPGRAM_API_KEY, GROQ_API_KEY, OPENAI_API_KEYVoice message transcription, first one found wins (else local Whisper)
TAVILY_API_KEY, BRAVE_API_KEY, SERPER_API_KEYWeb search
GITHUB_TOKENGitHub tool

cogitator up loads the .env next to cogitator.yml into process.env without overriding variables that are already set, so tools that read process.env when they run (web_search, github_api) see the keys the wizard wrote. With RuntimeBuilder in your own code, put those keys in process.env yourself — the builder's env argument is not copied there.

On this page