64 lines
3.2 KiB
Markdown
64 lines
3.2 KiB
Markdown
# 03 — KB / FAQ auto-reply (agent 3/10)
|
|||
|
|
|
||
|
|
## Goal
|
||
|
|
|
||
|
|
Platform knowledge base + reply templates with a **sync lexical matcher** that can post a labeled `author_role=system` first response when confidence clears the threshold. No LLM on this path (agent 4 owns `TryAutoReplyLLM`).
|
||
|
|
|
||
|
|
## Schema
|
||
|
|
|
||
|
|
Migration: `apps/api/sql/schema/032_support_kb_auto_reply.sql`
|
||
|
|
|
||
|
|
| Table | Purpose |
|
||
|
|
|-------|---------|
|
||
|
|
| `support_kb_articles` | Published FAQ articles (`slug`, `title`, `body_md`, `keywords`, `intent_keys`, `category_slugs`, `priority_weight`) |
|
||
|
|
| `support_reply_templates` | Canned replies with same match fields; placeholders allowlist: `{{subject}}`, `{{category}}` |
|
||
|
|
| `support_auto_config` | Singleton: `enabled`, `faq_enabled`, `match_confidence_threshold` (default **0.78**), `retry_on_first_customer_reply` |
|
||
|
|
|
||
|
|
Ticket/message auto columns (`auto_reply_*`, `is_auto_reply`, …) come from **`031_support_ticket_detail.sql`** (agent 5). Do not re-ALTER them here.
|
||
|
|
|
||
|
|
## Service API
|
||
|
|
|
||
|
|
Package: `apps/api/internal/support`
|
||
|
|
|
||
|
|
| Symbol | Role |
|
||
|
|
|--------|------|
|
||
|
|
| `MatchAutoReply(ctx, ticket) → MatchAutoReplyResult` | Scores corpus; `{matched, confidence, reply_body, article_id, template_id, kind}` — never posts, never LLM |
|
||
|
|
| `PostMatchedAutoReply` | Posts system message when `confidence >= threshold`; sets status `pending`, `auto_reply_status=matched`; notifies `auto_reply` |
|
||
|
|
| `MaybeAutoReplyOnCreate` | Stage A after create (respects config) |
|
||
|
|
| `MaybeAutoReplyOnCustomerReply` | Optional retry when `retry_on_first_customer_reply`; handoff if prior public auto exists |
|
||
|
|
| KB / template CRUD | `Create/Update/Delete/List/Get` for articles + templates |
|
||
|
|
| `GetAutoConfig` / `UpdateAutoConfig` | FAQ switchboard |
|
||
|
|
|
||
|
|
Matching: keyword overlap (0.70) + intent phrase (0.15) + category boost (0.15) + small priority weight. Secrets redacted before score (`RedactSecretsForMatch`). Corpus cached ~60s; invalidated on admin writes.
|
||
|
|
|
||
|
|
## HTTP (platform admin)
|
||
|
|
|
||
|
|
Mounted under `RequirePlatformAdmin`:
|
||
|
|
|
||
|
|
| Method | Path |
|
||
|
|
|--------|------|
|
||
|
|
| GET/POST | `/api/admin/support/kb/articles` |
|
||
|
|
| GET/PATCH/DELETE | `/api/admin/support/kb/articles/{id}` |
|
||
|
|
| GET/POST | `/api/admin/support/templates` |
|
||
|
|
| GET/PATCH/DELETE | `/api/admin/support/templates/{id}` |
|
||
|
|
| GET/PUT | `/api/admin/support/auto-config` |
|
||
|
|
|
||
|
|
Customer create (`POST /api/support/tickets`) calls `MaybeAutoReplyOnCreate` after successful create. Customer reply calls `MaybeAutoReplyOnCustomerReply` (no-op unless retry flag).
|
||
|
|
|
||
|
|
## Defaults / ops
|
||
|
|
|
||
|
|
- Master `enabled=false` until admin turns FAQ auto on.
|
||
|
|
- Enable + publish articles/templates + set threshold → create a ticket whose subject/body hits keywords → expect system message with footer “Automated answer from help center”.
|
||
|
|
- Below threshold → `auto_reply_status=skipped` (agent 4 may enqueue AI).
|
||
|
|
|
||
|
|
## Tests
|
||
|
|
|
||
|
|
- Unit: `apps/api/internal/support/match_auto_reply_test.go` (scoring, redaction, placeholders, footer).
|
||
|
|
- Auth probes include KB/template/auto-config paths in `support_auth_test.go`.
|
||
|
|
|
||
|
|
## Coordination
|
||
|
|
|
||
|
|
- Agent 4: on match miss / low confidence → `TryAutoReplyLLM` async; reuse message auto_* columns.
|
||
|
|
- Agent 5: ticket detail fields + activity; FAQ posts `ActivityAutoReply` via `insertActivity`.
|
||
|
|
- Agent 6: admin UI for KB + auto-config.
|
||
|
|
- Agent 10: migrate `032_*`, end-to-end verify.
|