Skip to content

Latest commit

Β 

History

History
258 lines (199 loc) Β· 30.6 KB

File metadata and controls

258 lines (199 loc) Β· 30.6 KB

Configuration & Tuning Parameter Reference

ThinkMate reads its runtime configuration from environment variables β€” values supplied through the .env file in the project root and loaded once at startup by app/config.py. This guide is the reference for every one of those variables: what each one does, the value it falls back to when you leave it unset, and how to adjust it safely. Use it to tune conversational behavior, API budgets, batching speeds, memory limits, and security rate limits without changing any application code.

Every setting below is documented in a table with four columns: Parameter (the environment-variable name), Type (the value's shape β€” String, Integer, Float, Bool, URL, or Path), Default (the value used when the variable is unset), and Description & How to Adjust (what the setting controls and the trade-offs of changing it). A handful of terms recur throughout, so they are defined once here:

  • Environment variable β€” a key/value pair read from the process environment (populated here from .env); a change takes effect on the next restart.
  • TTL (time-to-live) β€” an expiry window after which a stored value is automatically dropped, bounding how much state can accumulate.
  • Backoff β€” a deliberately growing wait between retries, so a struggling service is not hammered.
  • Master switch β€” a single setting that, at its default, keeps an optional subsystem turned off entirely.

The variables are grouped by the subsystem they govern, in the order they appear below:

  • πŸ”‘ Credentials & Connection Settings β€” Telegram and MongoDB connection details plus audit-log retention.
  • 🧠 LLM Server Settings β€” the inference endpoint, model selection, and retries.
  • πŸ“ Memory Tuning & Budget Constraints β€” buffer sizes and the character budgets that drive extraction and compression.
  • ⏱️ Queue & Message Batching β€” how the bot groups rapid-fire messages and evicts idle per-user state.
  • πŸ›‘οΈ Input & Output Security Guards β€” rate limits and length caps that protect against spam and abuse.
  • πŸ‘€ Persona Settings β€” the persona-file path, the name the bot answers to, and the emoji-reaction switch.
  • πŸ‘₯ Group Chat & Ambient Replies β€” how the bot behaves in groups and supergroups.
  • πŸ—£οΈ Group Chat / Implicit Addressing & Spam β€” implicit follow-up detection and mass-tag/greeting-burst defenses.
  • πŸ“Š Observability / ops β€” in-process metrics and the admin /health and /metrics commands.
  • ⌨️ Commands (rename / disable) β€” remap any slash command to a custom trigger or turn it off.
  • πŸŒ™ Consolidation (Phase 11) β€” the optional background "dreaming" pass over a user's whole profile.
  • πŸ’ž Engagement / Mood History (Phase 12) β€” the bounded mood-trend history.
  • πŸ”” Proactive Check-ins (Phase 12) β€” the optional, memory-grounded "thinking of you" scheduler.
  • πŸ”Œ Connection Pool (advanced) β€” MongoDB driver connection-pool tuning.

πŸ”‘ Credentials & Connection Settings

Parameter Type Default Description & How to Adjust
TELEGRAM_BOT_TOKEN String Required Purpose: Authenticates your application connection with Telegram's Bot API.
How to Tune: Obtained from @BotFather on Telegram. Update if keys are regenerated or compromised.
TELEGRAM_PUBLISH_COMMANDS Boolean True Purpose: Controls whether the bot registers its command menu with Telegram on startup.
How to Tune: Set to True (default) to publish the / command menu (containing the /start entry point) automatically. Set to False to prevent the bot from making startup set_my_commands API calls to Telegram.
MONGODB_URI String mongodb://localhost:27017 Purpose: The connection string pointing to your MongoDB database server.
How to Tune: Point to mongodb://localhost:27017 for local execution. Use mongodb+srv://... cluster URIs for cloud databases.
MONGODB_DB String thinkmate_db Purpose: The target database namespace where profiles and logs are stored.
How to Tune: Change to separate testing (thinkmate_test_db), development (thinkmate_dev_db), or production (thinkmate_prod_db) collections.
AUDIT_LOG_RETENTION_DAYS Integer 30 Purpose: Audit-log entries in llm_audit_log auto-expire after this many days via a TTL index, bounding storage growth.
How to Tune: Lower (e.g. 7) for tighter retention, raise for longer forensic history.

🧠 LLM Server Settings

Parameter Type Default Description & How to Adjust
LLM_BASE_URL URL http://localhost:1234/v1 Purpose: The root endpoint of the OpenAI-compatible HTTP inference server.
How to Tune: Point to local hosts (http://localhost:11434/v1 for Ollama, http://localhost:1234/v1 for LM Studio) or cloud providers (https://api.openai.com/v1, https://openrouter.ai/api/v1).
LLM_API_KEY String none Purpose: The authorization bearer token passed in API headers.
How to Tune: Set to your provider API key. For local servers that do not require auth, set to mock values like none or lm-studio.
LLM_MODEL String gpt-4o Purpose: Identifies the primary LLM model for conversational chat responses.
How to Tune: Set to a highly conversational, creative model (e.g. gpt-4o, gemma-4-31b-it).
LLM_EXTRACTION_MODEL String (blank β†’ uses LLM_MODEL) Purpose: Identifies the model for memory extraction and compression tasks.
How to Tune: Leave blank to reuse LLM_MODEL. A smaller, cheaper, faster model (e.g. gpt-4o-mini) keeps token costs minimal; .env.example ships gpt-4o-mini as a suggested value.
LLM_STRUCTURED_MODE String json_object Purpose: Strategy for structured (JSON) outputs.
How to Tune: Keep json_object for Gemini proxies, Ollama, LM Studio, OpenRouter, and most non-OpenAI backends (they reject the additionalProperties field that native parsing emits). Use native_parse only on a true OpenAI endpoint to get strict schema validation via beta.chat.completions.parse.
LLM_MAX_RETRIES Integer 2 Purpose: Retries for transient LLM errors (timeout, connection, 429, 5xx).
How to Tune: Raise for flaky endpoints; keep low to protect chat responsiveness.
LLM_RETRY_BASE_DELAY_SECS Float 0.5 Purpose: Base delay for exponential backoff between retries (delay = base * 2^attempt).
LLM_REQUEST_TIMEOUT_SECS Float 610.0 Purpose: Per-request client timeout, in seconds. Must sit ABOVE the proxy's own request ceiling (currently 600s for non-streaming) so the proxy is always the first to give up.
How to Tune: Raise it if your proxy/inference engine supports longer non-streaming generations (e.g. reasoning models).

πŸ“ Memory Tuning & Budget Constraints

Parameter Type Default Description & How to Adjust
CHAT_BUFFER_MAX_CHARS Integer 4000 Purpose: The character threshold of the active conversation buffer before extraction runs.
How to Tune: Lowering this triggers extraction sooner, saving smaller chunks to memory. Raising this keeps a longer history in active context before background trim runs.
NEW_USER_EXTRACTION_CHARS Integer 1000 Purpose: A lower buffer-char trigger used only for new/sparse users (see NEW_USER_MEMORY_THRESHOLD) so a fresh profile starts capturing memories quickly instead of waiting for the full CHAT_BUFFER_MAX_CHARS. Effective value is capped at CHAT_BUFFER_MAX_CHARS.
How to Tune: Lower for even faster first-profile building; raise toward CHAT_BUFFER_MAX_CHARS to reduce early extraction calls.
NEW_USER_MEMORY_THRESHOLD Integer 10 Purpose: Defines "new/sparse": a user whose stored memory items (facts + beliefs + events) number fewer than this uses NEW_USER_EXTRACTION_CHARS as the extraction trigger; at or above it, the normal CHAT_BUFFER_MAX_CHARS applies.
How to Tune: Raise to keep the faster cadence for longer; set to 0 to disable the new-user fast path entirely.
CHAT_BUFFER_TRIM Integer 8 Purpose: The count of latest messages preserved in active history when a buffer trim is executed.
How to Tune: Lower to keep prompts concise, or increase to retain a longer dialogue tail right after extraction.
CHAT_BUFFER_HARD_CAP Integer 200 Purpose: Absolute maximum number of messages retained in the buffer array, enforced via $slice. A safety net so a stalled extractor (e.g. LLM outage) can never let the array grow without bound.
How to Tune: Keep comfortably above CHAT_BUFFER_TRIM and normal buffer sizes.
USER_MEMORY_BUDGET_CHARS Integer 10000 Purpose: Caps the compiled memory profile text length. Exceeding this budget triggers compression.
How to Tune: Lowering forces high-level profiles earlier; raising retains more concrete detail. Keep β‰₯ ~600 β€” the empty section-header template alone is ~380 chars, so a budget near/below that can never be satisfied.
COMPRESSION_COOLDOWN_SECS Float 300 Purpose: Minimum seconds between compression runs for a given user.
How to Tune: Prevents repeated compression if a run can't immediately fit the budget. Works alongside deterministic post-compression trimming.
CHARS_PER_TOKEN Integer 4 Purpose: Character-to-token ratio. No longer used to derive output limits (the max_tokens cap was removed); retained for config compatibility.
How to Tune: Changing it no longer affects generation.

⏱️ Queue & Message Batching

Parameter Type Default Description & How to Adjust
MESSAGE_BATCH_DELAY_SECS Float 2.0 Purpose: Delay (in seconds) the bot waits after your last message before replying.
How to Tune: Set higher (e.g. 2.5) if you type rapid-fire messages. Set lower (e.g. 0.5) for instant replies.
MAX_BATCH_DELAY_SECS Float 6.0 Purpose: Hard deadline from first message in a batch, forcing reply generation.
How to Tune: Prevents infinite postpone loops from spammers. Keep around 6.0 seconds to maintain conversational responsiveness.
USER_STATE_TTL_SECS Float 1800 Purpose: Idle per-user in-memory state (locks, queues, batch timers) is evicted after this many seconds of inactivity. Bounds memory at large user counts (50k+) on a single instance.
How to Tune: Lower to reclaim memory faster; raise if you expect long conversational pauses.

πŸ›‘οΈ Input & Output Security Guards

Parameter Type Default Description & How to Adjust
RATE_LIMIT_MAX_REQUESTS Integer 10 Purpose: Maximum message requests allowed per user in the rate-limit window.
How to Tune: 10 in 5s tolerates fast Telegram typing while still blocking floods. Lower for public/high-risk deployments.
RATE_LIMIT_WINDOW_SECS Float 5.0 Purpose: Rate-limit cooling window duration in seconds.
How to Tune: Increase (e.g. 10.0 or 20.0) to restrict flooding users further.
STALE_MESSAGE_SECS Float 60.0 Purpose: Drops Telegram messages that predate the process start by more than this many seconds (backlog built up while bot was offline).
How to Tune: Keep at 60.0 to avoid processing old command queues on start; set 0 to disable.
MAX_QUEUED_MESSAGES Integer 10 Purpose: Caps the batch queue size. Incoming messages beyond this are ignored.
How to Tune: Restricting this protects your server from memory/concurrency exhaustion under spam attacks.
MAX_INPUT_CHARS Integer 4000 Purpose: Inbound messages longer than this are ignored (anti-abuse β€” blocks pasted logs/essays), not a normal chat cap.
How to Tune: 4000 sits just under Telegram's message limit, so users can share one full useful message without turning the bot into a pasted-log processor.
MAX_RESPONSE_CHARS Integer 4000 Purpose: App-level cap applied before sending LLM-generated replies and proactive check-ins. Text is then split into Telegram-safe chunks below the 4096-character message limit.
How to Tune: Raise for more detailed answers, lower for tighter chat. Set 0 or a negative value to disable the app-level cap; Telegram chunking still applies.

πŸ‘€ Persona Settings

Parameter Type Default Description & How to Adjust
PERSONA_FILE Path persona.md Purpose: Path to the Markdown file defining the bot's tone and traits.
How to Tune: Default is persona.md. Tune if you are hosting multiple bot instances with distinct personalities.
BOT_NAME String (blank β†’ ThinkMate) Purpose: The bot's universal display name. It is (a) the name the bot answers to in group chats, matched as a standalone, case-insensitive, word-boundary token (in addition to its auto-detected @username mention and reply-to-bot), and (b) the user-facing name shown everywhere else β€” greetings (/start), onboarding (/onboard), admin /health and /metrics headers, and the assistant's attribution in group transcripts. Resolved via config.bot_display_name (BOT_NAME if set, else ThinkMate).
How to Tune: Set to your bot's name (e.g. Nova) to rebrand it everywhere at once. For group addressing only, a blank value falls back to the Telegram first name from get_me(); the universal display name falls back to ThinkMate. The @username mention is always auto-detected regardless of this value.
ENABLE_MESSAGE_REACTIONS Bool True Purpose: Master switch for Telegram emoji reactions on user messages. When False, the reaction field of the combined reply call is ignored.
How to Tune: Disable if a deployment's chats forbid reactions or to save nothing extra (reactions ride the existing reply call, so there is no LLM-cost saving β€” this is purely behavioral).

πŸ‘₯ Group Chat & Ambient Replies

These tune ThinkMate's behavior in groups/supergroups. They have no effect in DMs. See group_chat.md for the full design.

Parameter Type Default Description & How to Adjust
GROUP_AMBIENT_COOLDOWN_SECS Float 30 Purpose: Minimum seconds between ambient (un-addressed) chime-ins per group. Caps how often the bot speaks up unprompted.
How to Tune: Raise to make the bot quieter in busy groups; lower for chattier behavior. The bot still always replies when directly addressed.
GROUP_AMBIENT_BASE_RATE Float 0.25 Purpose: Base probability the bot chimes in when a cheap trigger fires, before affinity weighting. Final chance = base Γ— affinity Γ— mode_factor.
How to Tune: Lower for restraint; keep ≀ ~0.4 to avoid feeling spammy.
GROUP_CONTEXT_SCAN_EVERY Integer 12 Purpose: Once per cooldown window, after this many group messages, a single affinity-gated context-scan call may run to catch subtler moments keywords miss.
How to Tune: Raise to reduce ambient LLM calls; lower to make the bot more contextually aware.
AFFINITY_DEFAULT Float 0.5 Purpose: Starting affinity (0–1) for a new {chat_id}:{user_id} member, scaling how readily the bot engages that person.
How to Tune: Raise for a friendlier default; lower for a more reserved default.

πŸ—£οΈ Group Chat / Implicit Addressing & Spam

These tune how ThinkMate recognizes follow-up messages that are implicitly addressed to it (without a fresh @mention) and how it defends against mass-tag and greeting-burst spam in groups. They have no effect in DMs. See group_chat.md for the full design.

Parameter Type Default Description & How to Adjust
GROUP_IMPLICIT_RECENCY_SECS Float 120.0 Purpose: Maximum seconds after the bot speaks for a follow-up to still count as implicitly addressed.
How to Tune: Raise to keep treating follow-ups as directed at the bot for longer; lower to require a fresh mention sooner.
GROUP_IMPLICIT_RECENCY_MAX_MSGS Integer 5 Purpose: Maximum intervening human messages since the bot last spoke for an implicit follow-up to still count.
How to Tune: Raise to tolerate busier interleaving; lower to require a tighter back-and-forth.
GROUP_IMPLICIT_COOLDOWN_SECS Float 15.0 Purpose: Minimum seconds between implicit direct replies per group (anti-noise throttle).
How to Tune: Raise to make implicit replies rarer; lower for snappier follow-ups.
GROUP_MASS_TAG_SPAM_THRESHOLD Integer 5 Purpose: Distinct @mentions above which a single message is classified as mass-tag spam (strict >).
How to Tune: Lower to flag mass-tagging sooner; raise to allow more legitimate multi-mentions.
GROUP_SPAM_BURST_SIMILARITY Float 0.85 Purpose: Mention-stripped similarity ratio (0–1) at/above which messages are treated as near-identical.
How to Tune: Raise to require closer matches before flagging; lower to catch looser repeats.
GROUP_SPAM_BURST_COUNT Integer 3 Purpose: Near-identical messages within the window that classify a greeting burst.
How to Tune: Raise to tolerate more repeats before flagging; lower to react sooner.
GROUP_SPAM_BURST_WINDOW_SECS Float 60.0 Purpose: Time window (seconds) for counting near-identical greeting-burst messages.
How to Tune: Raise to count repeats over a longer span; lower to require a tighter burst.
GROUP_SPAM_BURST_TRACK_MAX Integer 20 Purpose: Hard cap on tracked recent messages per chat, bounding memory used for burst detection.
How to Tune: Raise to track more history per chat; lower to bound memory more tightly.

πŸ“Š Observability / ops

These tune the Phase 10 observability layer (in-process metrics, the /health and /metrics admin commands, and the optional periodic metrics logger). Both keys have safe defaults so the bot runs unchanged when they are unset. See observability.md for the full metric catalog and runbook.

Parameter Type Default Description & How to Adjust
ADMIN_USER_IDS String (CSV) (blank β†’ DM-only) Purpose: Comma-separated list of Telegram user ids allowed to use the /health and /metrics admin commands. Blanks are ignored and each id is coerced to int.
How to Tune: Leave empty to apply the safe default β€” the commands answer only in private chats (DMs) so a status report is never broadcast to a group. Set to specific ids (e.g. 123456789,987654321) to restrict the commands to those operators in any chat.
METRICS_LOG_INTERVAL_SECS Float 0.0 Purpose: Interval, in seconds, for the optional background task that logs the metrics-snapshot summary (no DB/LLM call).
How to Tune: Keep 0 (or any value ≀ 0) to disable the periodic logger entirely. Set a positive value (e.g. 60) to emit one summary log line per interval for a lightweight time series in the logs.
METRICS_PERSIST_INTERVAL_SECS Float 300.0 Purpose: Interval, in seconds, for flushing the metrics registry to the metrics_state MongoDB document so /health and /metrics survive restarts/crashes (a cheap single-document upsert).
How to Tune: Keep the default 300 for a 5-minute crash window. Lower it for tighter durability at the cost of more writes; set 0 to disable the periodic flush β€” the startup-load and shutdown-flush still run, so a graceful restart keeps its totals regardless. See observability.md.
LOGS_CHANNEL_ID Integer None Purpose: The Telegram channel ID where operational events (startup, shutdown, memory extraction saves/skips, and user profile backups before /reset) are forwarded.
How to Tune: If unset/not present in the environment (default), logging/forwarding to the channel is disabled. Provide a valid integer channel ID (e.g. -1003933328659) to enable forwarding.
FORWARD_DIAGNOSTICS Boolean False Purpose: Early-phase verbose tracing: forwards per-message routing decisions (group addressed/implicit/ambient/spam, throttle, blocked) to LOGS_CHANNEL_ID. Noisy by design.
How to Tune: Set to True during testing to verify routing live; set to False (default) for production.

⌨️ Commands (rename / disable)

Every built-in slash command can be renamed to a custom trigger or disabled entirely, all from the environment β€” no code change. This is useful for white-labeling the bot (e.g. mapping /start to /chatbot), avoiding command clashes with other bots in a group, or hiding capabilities you don't want exposed. Both settings have safe defaults (the trigger equals the command key and the command is enabled), so you only set the ones you want to change.

The in-chat command list opened from /start is generated from this configuration, so a renamed command appears under its new trigger and a disabled command is hidden and unregistered (it draws no response at all). The same configuration drives the native Telegram "/" command menu, which is published at startup via set_my_commands (see telegram_bot.md): personal commands are scoped to DMs and group moderation toggles to group chats, while admin-only /health and /metrics are omitted from the public menu.

The built-in command keys (in help-display order) are: start, help, onboard, checkins, profile, reset, reactions, quiet, chatty, groupbot, groupmode, health, metrics.

Parameter Type Default Description & How to Adjust
CMD_<KEY>_NAME String (the key) Purpose: The trigger the command is bound under. <KEY> is the upper-cased command key (e.g. CMD_START_NAME). A leading / is stripped; the name must be 1–32 characters of letters, digits, or underscores (Telegram's command rule).
How to Tune: Set e.g. CMD_START_NAME=chatbot to expose /start as /chatbot. An invalid name, or one that duplicates another enabled command's trigger, safely falls back to the default key with a logged warning (startup never crashes).
CMD_<KEY>_ENABLED Boolean True Purpose: Whether the command is registered at all.
How to Tune: Set e.g. CMD_RESET_ENABLED=False to remove /reset β€” it is left unregistered and omitted from the inline command list and the "/" menu. Admin-only commands (/health, /metrics) remain admin-gated regardless of any rename.

Examples

CMD_START_NAME=chatbot      # /start is now /chatbot (the bot's main entry point)
CMD_HELP_NAME=commands      # /help is now /commands
CMD_PROFILE_NAME=memories   # /profile is now /memories
CMD_RESET_ENABLED=False     # /reset is removed entirely

πŸŒ™ Consolidation (Phase 11)

These tune the periodic background consolidation ("dreaming") pass β€” a long-horizon review of a user's whole profile that refreshes the summary/style, merges/de-duplicates items, and synthesizes a small bounded set of durable behavioral insights. The pass runs entirely off the hot path under the shared memory_lock and is enabled by default on a daily cadence. See memory_engine.md for the full design.

Parameter Type Default Description & How to Adjust
CONSOLIDATION_INTERVAL_SECS Float 86400.0 Purpose: The minimum age of a user's last consolidation before they become "due" again β€” and the master switch for the whole feature. Default is daily.
How to Tune: Set 0 (or any value ≀ 0) to disable the dreaming pass entirely (the scheduler is never started). Use 86400 for daily, 604800 for weekly, or a larger value for lower LLM cost.
CONSOLIDATION_SCAN_INTERVAL_SECS Float 3600 Purpose: How often the scheduler wakes to scan for due users (one scan per interval).
How to Tune: Lower for tighter cadence/quicker pickup; raise to scan less often. Independent of the per-user interval above β€” a scan only consolidates users who are actually due.
CONSOLIDATION_MAX_USERS_PER_SCAN Integer 50 Purpose: Upper bound on how many due users a single scan processes, keeping each scan's work (and LLM volume) bounded.
How to Tune: Raise to drain a large due backlog faster; lower to spread consolidation cost across more scans.
CONSOLIDATION_MIN_ITEMS Integer 8 Purpose: Minimum stored items (facts + beliefs + events) a user must have before they are eligible, so the pass never "dreams" over a profile too thin to yield a durable pattern.
How to Tune: Raise to consolidate only richer profiles; lower to start synthesizing insights sooner.
MAX_INSIGHTS Integer 5 Purpose: Hard cap on the dedicated insights list. Both the apply step and the prompt honor it, so the list can never grow unbounded.
How to Tune: Raise for more synthesized observations per user; lower to keep the behavioral-insights section terse.

πŸ’ž Engagement / Mood History (Phase 12)

This single key tunes emotional continuity β€” the bounded mood_history list that lets ThinkMate render a short mood trend (not just the latest mood) in the memory profile. The history is appended whenever a new emotional_state is extracted and is exempt from budget-driven shedding. See memory_engine.md for the full design.

Parameter Type Default Description & How to Adjust
MAX_MOOD_HISTORY Integer 10 Purpose: Cap on the number of stored mood_history entries per user. Each new emotional state appends one entry and the oldest are dropped once the cap is reached, so the list (and the rendered trend line) stays small and bounded.
How to Tune: Raise for a longer mood trend, lower for a terser one. Safe at any positive value β€” it only ever bounds a tiny list.

πŸ”” Proactive Check-ins (Phase 12)

These tune the optional background proactive check-in scheduler β€” a periodic pass that occasionally sends a single, memory-grounded "thinking of you" nudge to users who have gone quiet for a while. Like consolidation, it runs entirely off the hot path, costs at most one LLM call per due user per cadence, never sends anything it can't ground in a real, known detail, and is enabled by default (PROACTIVE_INTERVAL_SECS = 3600, an hourly scan). Users can opt out at any time with /checkins off (and back in with /checkins on); see telegram_bot.md. Full design in memory_engine.md.

Quiet hours are UTC-only. PROACTIVE_QUIET_START_HOUR / PROACTIVE_QUIET_END_HOUR are interpreted against the server's UTC clock, not each user's local timezone β€” this is a documented limitation. Set the window to suit your audience's dominant timezone, or set start == end to disable the quiet window entirely.

Parameter Type Default Description & How to Adjust
PROACTIVE_INTERVAL_SECS Float 3600.0 Purpose: How often the scheduler wakes to scan for due users β€” and the master switch for the whole feature. Default is hourly; actual sends are still gated by inactivity, minimum interval, quiet hours, grounding, and unanswered-check-in limits.
How to Tune: Set 0 (or any value ≀ 0) to disable proactive check-ins entirely (the scheduler is never started). Raise it to scan less often.
PROACTIVE_INACTIVITY_SECS Float 86400 (1 day) Purpose: How long a user must have been silent (no interaction) before they become eligible for a check-in.
How to Tune: Lower to reach out sooner after a lull; raise to wait longer before nudging.
PROACTIVE_MIN_INTERVAL_SECS Float 172800 (2 days) Purpose: Minimum time between proactive nudges per user, so an inactive user is never pestered repeatedly.
How to Tune: Raise to space nudges further apart; keep comfortably above the scan interval.
PROACTIVE_MAX_PER_SCAN Integer 50 Purpose: Upper bound on how many check-ins a single scan sends, keeping each scan's work (and LLM volume) bounded.
How to Tune: Raise to drain a large due backlog faster; lower to spread the cost across more scans.
PROACTIVE_MIN_ITEMS Integer 3 Purpose: Minimum stored items (facts + beliefs + events) a user must have before a check-in is attempted, so a nudge is always grounded in something genuine rather than generic filler.
How to Tune: Raise to reach out only to richer profiles; lower to start nudging sooner.
PROACTIVE_MAX_UNANSWERED Integer 3 Purpose: Auto-pause proactive check-ins for a user after this many consecutive delivered check-ins with no reply (chat or command).
How to Tune: Set to 0 to disable auto-pause; increase to allow more unanswered check-ins before pausing.
PROACTIVE_QUIET_START_HOUR Integer 16 Purpose: Start of the daily quiet window (UTC hour, 0–23) during which scans are skipped so no one is messaged late at night. 16β†’2 approximates 21:30–07:30 IST.
How to Tune: Set with PROACTIVE_QUIET_END_HOUR to bracket your audience's night hours in UTC. The window may wrap midnight. Set equal to the end hour to disable quiet hours.
PROACTIVE_QUIET_END_HOUR Integer 2 Purpose: End of the daily quiet window (UTC hour, 0–23). Scans resume at this hour.
How to Tune: See PROACTIVE_QUIET_START_HOUR.

πŸ”Œ Connection Pool (advanced)

The motor client uses a connection pool (driver default maxPoolSize=100). The concurrently active user working set is far smaller than total users, so the default is typically sufficient even at 50k+ users. If you observe connection saturation under extreme concurrency, raise maxPoolSize in connection.py and document the change here. See performance_and_scaling.md.