Lore
README.md
# Lore — the org-memory agent for Slack
> "What did we decide about pricing?" · "Who owns the hospital pilot?" · "When did we flip the go-live date?"
> Every team has these questions. Nobody has a fast, sourced answer.
Lore is a Slack agent that captures decisions, commitments, and facts **as they happen** — then answers questions about them with **provenance**: every answer links the exact Slack messages (and the GitHub PR, Jira issue, or Notion doc) where the fact was established.
Built for the [Slack Agent Builder Challenge 2026](https://slackhack.devpost.com) · **New Slack Agent track** · Apache-2.0
---
## Qualifying technologies
| Slack Agent Builder Challenge tech | How Lore uses it | File |
|---|---|---|
| **Slack AI / Assistant API** | `assistant_thread_started` + `assistant_thread_context_changed` events; Assistant-thread surface for contextual Q&A; AI digests power the research synthesis pass | `src/lore/slackio/events.py` |
| **MCP server integration** | Lore *is* an MCP server (`org_memory_search`, `org_memory_remember`, `org_memory_forget`) AND an MCP client (per-tenant CRM/Jira/Linear/GitHub integrations) | `src/lore/mcpio/server.py`, `src/lore/mcpio/client.py`, `src/lore/integrations.py` |
| **Real-Time Search API** | `assistant.search.context` called at answer-time to inject fresh Slack context in assistant threads (gracefully skipped on channel `@mentions`, where the action token doesn't apply); used in the 5-phase research pipeline's public-search stage | `src/lore/runner.py`, `src/lore/rts.py` |
All three technologies are active simultaneously on every question.
---
## How it works
```
Slack event ──▶ durable intake Redis-stream exactly-once admission;
survives restarts, deduplicates retries
──▶ armor scan PII + credential regex screen before
any LLM call; blocks prompt injection
──▶ intent classification simple / research / complex /
high_consequence routing
──▶ fact extraction decision? commitment? owner? date?
attributed to the Slack user who said it
──▶ memory store hybrid vector (Qdrant) + keyword (Postgres)
reinforcement/decay: confirmed = stronger,
untouched = fades, corrected = superseded
──▶ retrieval (at ask-time) 3-tier grounding: context → history → RAG
+ Real-Time Search API freshness layer
──▶ answer + provenance Block Kit card, source permalinks,
Confirm / Correct / Forget buttons
──▶ (if high_consequence) Approval gate: asyncio.Future bridge,
Block Kit card, 5-minute timeout
```
Questions route to one of four dispatch paths — `simple` (direct retrieval), `research` (5-phase pipeline), `complex` (multi-agent router/council/auto team), `high_consequence` (council deliberation + human approval). An admin console (React/TypeScript, `src/console/`) exposes memory, conflicts, runs, agents, teams, integrations, and routing over `/api/v1` + SSE.
---
## Repository structure
```
src/lore/
├── main.py entry point: wires all deps, starts Socket Mode + worker
├── config.py all env-var config (dataclass, validated at startup)
├── runner.py orchestrator: intent → dispatch → retrieval → answer
├── intake.py durable Redis-stream admission (exactly-once)
├── store.py memory CRUD: Postgres (facts) + Qdrant (vectors)
├── mcpio/client.py MCP client: MCPResolver, stdio/http/sse, per-query construction
├── mcpio/server.py MCP server: org_memory_search/remember/forget over stdio/http/sse
├── integrations.py per-tenant MCP integration store + builder
├── rts.py Real-Time Search API wrapper (assistant.search.context)
├── api.py aiohttp REST API + SSE + CSRF guard
├── agent/ ReAct tool loop: tools, provider, FakeToolProvider
├── approval/ approval gateway: Future bridge + Block Kit + Bolt actions
├── slackio/ Bolt event/action/shortcut handlers, Block Kit builders
├── teams/ router/council/auto team modes + harness
└── db.py asyncpg pool + schema (CREATE TABLE IF NOT EXISTS)
src/console/src/ React 18 / TypeScript / Vite SPA
├── api/client.ts typed API client, CSRF cookie, error handling
├── pages/ admin screens: Memory, Conflicts, Runs, Agents, Teams…
└── nav.ts navigation manifest (path, label, icon, crumb)
scripts/ operational scripts (seed data, memory curator, dev console)
agents/ default agent persona (SOUL.md + lore.yaml)
```
---
## Run it
Requires Python 3.12+, Node 18+, and Redis + PostgreSQL + Qdrant running locally.
```bash
git clone <repo>
cd lore
bash scripts/dev-setup.sh # creates DBs, venv, installs deps
cp .env.example .env # fill in Slack tokens
. .venv/bin/activate
lore db-init # idempotent schema
lore run # Socket Mode listener + worker
# Console: http://127.0.0.1:8096/console
```
Create the Slack app from `slack-app-manifest.yml` (Socket Mode), install to workspace, and set in `.env`:
```env
LORE_SLACK_BOT_TOKEN=xoxb-…
LORE_SLACK_APP_TOKEN=xapp-…
LORE_MODEL_PROVIDER=openai_compat # or: anthropic | fake
LORE_OPENAI_BASE_URL=http://127.0.0.1:8000/v1
LORE_OPENAI_API_KEY=…
# Capability flags (intent routing, RTS, vision, web search, digest, passive
# capture) are ON by default; each stays inert until its endpoint/channels are
# set. Add LORE_EMBEDDINGS_BASE_URL / LORE_VISION_BASE_URL etc. to light them up.
```
Expose org memory to Claude Desktop / Cursor:
```bash
lore mcp # MCP server (stdio default; --transport http|sse): org_memory_search / remember / forget
```
---
## License
Apache-2.0 — see [LICENSE](LICENSE).
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues