Skip to content

nlink-jp/sai

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

62 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

SAI β€” Slack AI Command Interpreter

πŸ‡―πŸ‡΅ ζ—₯本θͺžη‰ˆ: README.ja.md

A context-aware Slack bot that remembers your team's conversations, answers questions grounded in history, and executes commands via natural language β€” all powered by a local LLM.


What SAI Can Do

1. Answer questions from conversation history

SAI silently reads every message posted in its joined channels and stores them in memory. When you @mention SAI, it retrieves relevant past conversations and uses them as context for its answer.

Alice  β”‚ @SAI What did Bob say about the deployment schedule last week?
───────┼────────────────────────────────────────────────────────────────
SAI    β”‚ Based on the conversation from Tuesday, Bob mentioned that the
       β”‚ deployment is planned for Friday at 2:00 PM JST, but noted
       β”‚ there may be a delay if the staging tests don't pass by Thursday.
Alice  β”‚ @SAI Has anyone discussed the Redis migration?
───────┼────────────────────────────────────────────────────────────────
SAI    β”‚ Yes β€” Carol brought it up on Monday. She suggested migrating
       β”‚ from Redis 6 to Redis 7 during the maintenance window on the
       β”‚ 25th. Dave replied that he wanted to review the breaking changes
       β”‚ first and would share a summary by end of week.

2. Execute commands via natural language

SAI can run pre-registered shell scripts in response to natural language requests. You don't need to remember command names β€” just describe what you want.

Bob    β”‚ @SAI Can you check the server status?
───────┼────────────────────────────────────────────────────────────────
SAI    β”‚ βœ… `server_status`:
       β”‚ ```
       β”‚ Hostname : prod-server-01
       β”‚ Uptime   : up 14 days, 3 hours
       β”‚ Load avg : 0.42, 0.38, 0.35
       β”‚
       β”‚ Memory:
       β”‚ total   used   free
       β”‚ 32Gi    12Gi   18Gi
       β”‚ ```
Carol  β”‚ @SAI How much disk space is left on /var/log?
───────┼────────────────────────────────────────────────────────────────
SAI    β”‚ βœ… `disk_usage`:
       β”‚ ```
       β”‚ Filesystem  Size  Used  Avail  Use%
       β”‚ /dev/sda1    50G   31G    19G   62%
       β”‚
       β”‚ Top directories:
       β”‚ 8.2G  /var/log/nginx
       β”‚ 4.1G  /var/log/app
       β”‚ 1.3G  /var/log/syslog
       β”‚ ```
Dave   β”‚ @SAI ping google.com for me
───────┼────────────────────────────────────────────────────────────────
SAI    β”‚ βœ… `ping_host`:
       β”‚ ```
       β”‚ PING google.com: 4 packets, 0% loss
       β”‚ min/avg/max = 4.2/4.8/5.3 ms
       β”‚ ```

3. Pin important messages permanently

Add a πŸ“Œ reaction (or ⭐ πŸ”– πŸ“) to any message and SAI will store it in pinned memory β€” it will never be summarized, never be archived, and will always be available as context for future answers.

Eve    β”‚ The production DB password rotation is scheduled for Dec 1st.
       β”‚ All services must update their credentials by Nov 30th 5PM.
       β”‚
       β”‚  [someone adds πŸ“Œ reaction]
       β”‚
Alice  β”‚ @SAI When is the DB password rotation?
───────┼────────────────────────────────────────────────────────────────
SAI    β”‚ The production DB password rotation is scheduled for December
       β”‚ 1st. All services need to update credentials by November 30th
       β”‚ at 5:00 PM.

Even months later, pinned messages remain available β€” unlike regular messages which are gradually summarized and eventually archived.


4. Smart memory with automatic forgetting

SAI manages its own memory so it doesn't grow forever. Regular messages follow this lifecycle:

HOT    (< 24h)    Full original text β€” every detail preserved
  ↓
WARM   (1–7 days) LLM-generated summary β€” key points kept
  ↓
COLD   (> 7 days) Marked for removal from active memory
  ↓
ARCHIVE           Moved to cold storage, no longer retrieved

PINNED            Reaction-triggered β€” never ages, never archived

This means SAI has good recall for recent events and useful summaries for older ones, while staying within the LLM's context window.

Message edits and deletions

SAI tracks changes to stored messages:

  • Edit β€” When a message is edited, the original record is kept unchanged. A new HOT record is added with the updated text (prefixed [edited by <user>]), so RAG retrieval can surface the corrected content going forward.
  • Delete β€” When a message is deleted:
    • HOT or PINNED record: deleted from memory immediately, including its embedding. The author may have removed sensitive content.
    • WARM or COLD record: already summarised β€” the summary cannot be undone, so the record is left as-is.

5. Thread continuation

Reply to any thread that SAI has already participated in β€” without needing to @mention SAI again β€” and the conversation continues naturally. SAI detects that the parent message is in memory and treats the reply as a mention automatically.


6. On-demand channel / thread summarisation

Ask SAI to summarise what happened in a channel or thread:

@SAI summarise this channel
@SAI summarise this thread

SAI retrieves all stored memory records for the requested scope, generates a summary, and clearly states the time range covered by the records:

## Summary of #general β€” 2026-03-20 10:00 UTC to 2026-03-24 15:30 UTC

β€’ The team discussed the Q1 release plan ...
β€’ Bob and Alice agreed on the API design ...

Note: Records older than 24 hours may already be LLM-generated summaries (WARM/COLD state). Long-range summaries are therefore "summaries of summaries" and may be less precise for older periods. SAI notes this in the response.


What SAI Does NOT Do

  • SAI does not proactively send messages β€” it only replies when @mentioned
  • SAI does not run arbitrary shell commands β€” only pre-registered scripts in scripts/commands.json
  • SAI does not have internet access β€” it uses a locally running LLM

Requirements


Quick Start

# 1. Install dependencies
uv sync

# 2. Copy and fill in your credentials
cp .env.example .env
# Edit .env with SAI_SLACK_BOT_TOKEN and SAI_SLACK_APP_TOKEN

# 3. (Optional) Copy and customize the full config
cp sai.toml.example sai.toml
# Edit sai.toml β€” set workspace_name, response_language, model names, etc.
# sai.toml is read from the current directory where you run `uv run sai start`

# 4. Initialize the database
uv run sai init-db
# To wipe all data and start fresh (prompts for confirmation):
# uv run sai init-db --reset

# 5. Verify LLM connectivity
uv run sai check

# 6. Start the bot
uv run sai start

Configuration

Settings are loaded from sai.toml (read from the current directory by default, override with --config) and SAI_* environment variables. Environment variables override the config file.

Variable Default Description
SAI_SLACK_BOT_TOKEN (required) Slack bot token (xoxb-...)
SAI_SLACK_APP_TOKEN (required) Socket Mode app token (xapp-...)
SAI_SLACK_RESPONSE_LANGUAGE (auto-detect) Language for bot replies (e.g. Japanese, English)
SAI_LLM_BASE_URL http://localhost:1234/v1 LM Studio endpoint
SAI_LLM_API_KEY lm-studio API key
SAI_LLM_MODEL openai/gpt-oss-20b Chat model
SAI_LLM_EMBED_MODEL text-embedding-nomic-embed-text-v1.5 Embedding model
SAI_LLM_MAX_CONCURRENT_REQUESTS 4 Max parallel LLM requests
SAI_MEMORY_PIN_REACTIONS pushpin,star,bookmark,memo Reactions that pin memory
SAI_LOG_LEVEL INFO Log level

For all available settings with descriptions and defaults, see sai.toml.example. Secrets (tokens, API keys) can be placed in .env β€” see .env.example.


Adding Custom Commands

1. Write a shell script in scripts/. Parameters arrive as JSON on stdin:

#!/usr/bin/env bash
# scripts/my_command.sh
params=$(cat)
target=$(echo "$params" | python3 -c "
import json, sys
print(json.load(sys.stdin)['args']['target'])
")
echo "Running check on: $target"
# ... your logic here

2. Register it in scripts/commands.json:

{
  "name": "my_command",
  "description": "Check the health of a given service",
  "script_path": "my_command.sh",
  "required_args": ["target"],
  "max_runtime_seconds": 30
}

SAI's LLM will automatically map user requests like "check the health of nginx" to this command.


Security

SAI is designed with multiple layers of defense:

  • ACL β€” whitelist/blacklist by Slack user ID
  • Rate limiting β€” per-user sliding window (configurable per minute and per hour)
  • Prompt injection defense β€” per-request nonce XML encapsulation, input sanitizer, role-separated prompts
  • Command sandboxing β€” only pre-registered scripts run; parameters via stdin JSON (never CLI args); resource limits applied
  • Response sanitization β€” model internal tags (<think>, [THINK], <reasoning>, etc.) are stripped before posting to Slack

See docs/development-rules.md for the full security policy.


Memory Monitoring

While SAI is stopped, you can inspect the memory database from the CLI:

# Record counts by state
uv run sai memory stats

# List recent records (supports --state / --user / --channel / --limit filters)
uv run sai memory list
uv run sai memory list --state pinned
uv run sai memory list --channel C09BLA40DFY --limit 50

# Full detail of one record (use the ID prefix shown in list)
uv run sai memory show <id-prefix>

Memory states: hot (< 24h, full text) β†’ warm (1–7 days, summarized) β†’ cold β†’ archived; pinned never ages.


Running Tests

uv run pytest
uv run pytest --cov=sai --cov-report=term-missing

Project Structure

sai/
β”œβ”€β”€ config/              # Configuration schema and loader
β”œβ”€β”€ sai/
β”‚   β”œβ”€β”€ app.py           # Application orchestrator β€” event pipeline
β”‚   β”œβ”€β”€ db/              # DuckDB + VSS repository layer (async interface)
β”‚   β”œβ”€β”€ llm/             # LLM client, prompts, nonce, sanitizer
β”‚   β”œβ”€β”€ memory/          # Memory models, lifecycle state machine, scheduler
β”‚   β”œβ”€β”€ rag/             # Embedding generation and retrieval
β”‚   β”œβ”€β”€ security/        # ACL, rate limiter, injection detection
β”‚   β”œβ”€β”€ slack/           # Socket Mode handler, event parser, cache
β”‚   β”œβ”€β”€ commands/        # Registry, NL interpreter, executor
β”‚   └── utils/           # Logging, time helpers, ID generation
β”œβ”€β”€ scripts/             # Command scripts + commands.json manifest
β”œβ”€β”€ tests/               # Unit and integration tests
└── docs/                # Setup guides, architecture, development rules

Documentation

Document Description
docs/slack-setup.md / ja Step-by-step Slack app setup guide
docs/development-rules.md / ja Coding standards, security rules, git conventions

About

A context-aware Slack bot with RAG memory and natural language command execution, powered by a local LLM

Topics

Resources

License

Stars

Watchers

Forks

Contributors