Контекст: модерация (AI-агенты)
NOTE
Статус: Target design. Документ описывает целевую доменную модель. Соответствующий код реализован частично (см.
backend/internal/core/) или пока не начат. Правила маркировки — в50-processes/documentation-standard.md.
Назначение
Принимает все кейсы, которые в классической архитектуре требовали бы решения человека (probable match без второго сигнала, weak match, orphan resolution, inferred SupplierRelationship, AI-предложенные characteristics для critical attribute, overlap Price Rules, candidate для CredentialGroup, ИНН-verification edge cases).
В Tracium по умолчанию эти кейсы автоматически разруливаются AI-агентами с детерминированным pipeline (gather context → LLM → validate → emit). Человек подключается только при escalation: confidence ниже порога, противоречивые сигналы, security/compliance scope (security break-glass — единственное место, где человек обязателен по политике).
Главный смысл
Очередь модерации — не «to-do для оператора», а input для AI-агента. Агент работает в детерминированном sandbox: одинаковый input + одинаковая модель + одинаковый prompt → одинаковое решение. Каждое решение объяснимо (cite of evidence) и отзываемо (replay).
Агрегаты / сущности / value objects
| Имя | Тип | Назначение |
|---|---|---|
ModerationCase | 🟨 Aggregate | Кейс модерации. Корень: case_id. Lifecycle: queued → analyzing → decided → applied или → escalated. |
CaseKind | VO enum | match_review / orphan_resolution / inferred_relationship_review / enrichment_critical_attr_review / priority_overlap_review / credential_group_candidate / legal_info_verification_edge / manufacturer_alias_proposal / identity_profile_proposal. |
CaseSource | VO | (bc, aggregate_ref, event_id) — откуда пришло. |
CaseEvidence | VO | Структурированный input агенту: relevant data из source BC + ссылки. |
AgentRunner | E | Конфигурация агента per CaseKind: model, prompt template, tools, decision schema, confidence threshold, SLA. |
AgentDecision | VO | (verdict, confidence, reasoning, citations[], proposed_action). |
Verdict | VO enum | accept / reject / escalate / defer (нужны доп. данные). |
ProposedAction | VO | Что должно произойти в source BC (например, MatchUpgrade{from: probable, to: strong}). |
EscalationPolicy | E | Конфигурация: когда escalate (confidence < X / repeat fail / security flag) + куда (Slack channel, ticket system). |
AgentRun | E | Append-only запись одного выполнения агента: input hash, output, latency, model_ref, tokens. |
LlmModelRef | VO | (model_name, version, prompt_hash). Shared Kernel с Enrichment. |
HumanEscalation | E | Запись escalation: case_ref, reason, assigned_to, resolved_at. |
Поддерживаемые типы кейсов
CaseKind | Источник | Что делает агент | Default action |
|---|---|---|---|
match_review | Matching: probable без second signal | Сравнить offer characteristics с canonical, проверить embedding similarity, classification tag, packaging fingerprint, multi-supplier consensus. | accept → MatchUpgrade(probable→strong) или reject → leave probable + log |
orphan_resolution | Matching: OrphanItemAssigned | Попробовать классифицировать в существующий Identity Profile или предложить новый. | accept → ResolveOrphan или defer → ждать больше offers |
inferred_relationship_review | Supplier Network: InferredRelationshipProposed | Проверить inference: пересечение SKU, источники, бизнес-логика. | accept → upgrade source declared или reject |
enrichment_critical_attr_review | Enrichment: EnrichmentReviewRequired для critical attr | Перепроверить LLM-извлечение через альтернативный prompt + embedding sanity check. | accept → publish для Catalog или reject |
priority_overlap_review | Pricing: validator при создании rule | Проверить, какой порядок дат лучший результат на 100 sample-контекстов; предложить explicit priority. | accept → суггестировать priority operator’у при create или escalate |
credential_group_candidate | Credentials: partial fingerprint match | Проверить контекст (одна организация / один customer / разные пароли) → решение объединить / нет. | accept → MergeIntoGroup или reject |
legal_info_verification_edge | Customer: ИНН-verify вернул ambiguous | Сверить с открытыми источниками, проверить consistency reg-данных. | accept → LegalInfoVerified или escalate |
manufacturer_alias_proposal | Catalog/Matching: новое написание manufacturer | Сверить с существующими aliases, embedding similarity, бренд-каталоги. | accept → ManufacturerAliasAdded или reject |
identity_profile_proposal | Matching: повторяющиеся orphans с похожими characteristics | Предложить новый Identity Profile с critical_attribute_keys. | defer (всегда) → выписка в admin UI для финального review (структурное решение, не auto). |
Доменные события
| Событие | Причина |
|---|---|
КейсМодерацииСоздан (ModerationCaseCreated) | Source BC опубликовал кейс |
КейсАнализируется (ModerationCaseAnalyzing) | Агент начал работу |
СобраныСвидетельства (EvidenceGathered) | Pre-LLM фаза: контекст собран из source BC |
АгентВынесРешение (AgentDecisionEmitted) | LLM вернул verdict + confidence + reasoning |
РешениеПримененоВИсходномBC (DecisionApplied) | Source BC получил ProposedAction через PL и выполнил |
КейсЭскалирован (CaseEscalated) | Confidence < threshold / repeat fail / security flag |
КейсРазрешёнЧеловеком (CaseResolvedByHuman) | Только после escalation |
АгентПровалил (AgentRunFailed) | Timeout / model error / validation fail |
АгентОтключёнCircuit (AgentDisabledByCircuit) | Подряд > N провалов / accuracy упала ниже SLA |
КейсПереоткрыт (CaseReopened) | Replay по новой версии модели или новому evidence |
Команды
| Команда | Актор | Целевой агрегат | Результат |
|---|---|---|---|
СоздатьКейс (CreateCase) | Source BC consumer | ModerationCase | ModerationCaseCreated |
ЗапуститьАгента (RunAgent) | Worker | ModerationCase | AgentDecisionEmitted или AgentRunFailed |
СобратьEvidence (GatherEvidence) | Worker | ModerationCase | EvidenceGathered |
ПрименитьРешение (ApplyDecision) | Worker (publishes Action) | — | DecisionApplied (после ack от source BC) |
Эскалировать (Escalate) | Policy | ModerationCase | CaseEscalated |
РазрешитьЧеловеком (ResolveByHuman) | Operator | ModerationCase | CaseResolvedByHuman |
Переоткрыть (Reopen) | Schedule / Operator | ModerationCase | CaseReopened |
Pipeline AI-агента
flowchart TD A["🟧 ModerationCaseCreated<br/>(из любого source BC)"] --> B["🟦 GatherEvidence"] B --> C["🟧 EvidenceGathered<br/>(структурированный input)"] C --> D["🟦 RunAgent (LLM call в sandbox)"] D --> E{"Output schema валиден?"} E -->|нет| F["🟧 AgentRunFailed<br/>(retry с альтернативным prompt)"] F -->|повтор N раз| G["🟪 Policy: escalate"] E -->|да| H{"confidence ≥ threshold?"} H -->|нет| G H -->|да| I{"verdict?"} I -->|accept/reject| J["🟧 AgentDecisionEmitted"] I -->|escalate| G I -->|defer| K["🟪 Policy: дождаться доп. evidence"] J --> L["🟦 ApplyDecision<br/>(publish ProposedAction в source BC)"] L --> M["🟧 DecisionApplied"] G --> N["🟧 CaseEscalated → human queue"]
Шаги
GatherEvidence— детерминированный код (не LLM) собирает structured input:- Read-only запросы в source BC (Catalog, Offers, etc.) через query API.
- Embeddings, classification tags, manufacturer aliases.
- Исторические похожие кейсы (RAG: top-K cases с outcome).
- Метаданные:
case.kind,case.source.event_id, timestamps.
RunAgent(LLM call):- Sandbox: timeout 30 сек, no network outside whitelisted RAG store, no creds.
- Prompt =
AgentRunner.prompt_template+EvidenceGatheredpayload. - Function calling: enforce JSON schema на output (verdict + confidence + reasoning + citations + proposed_action).
- Validation:
- JSON schema валиден?
confidence ∈ [0, 1].proposed_actionсоответствует ожидаемому дляcase.kind.citations[]ссылаются на existing IDs из source BC.- Если что-то не так → retry с альтернативным prompt (max 2 retry); потом
AgentRunFailed.
- Decision routing:
accept/reject+confidence ≥ threshold→ emitAgentDecisionEmitted.confidence < thresholdилиverdict = escalate→CaseEscalated(даже если verdict = accept — низкая уверенность важнее).defer→ ставим waiting; reopen триггер на новые события из source BC.
ApplyDecision— publishesProposedActionevent сcase_idcorrelation:- Source BC consumer применяет (например, Matching:
MatchUpgrade(probable→strong)). - Source BC отвечает
DecisionApplied{case_id, ack}через kafka — Moderation marks complete.
- Source BC consumer применяет (например, Matching:
Idempotency
- Каждый
AgentRunхешируется по(case_id, evidence_hash, model_ref). Повторный запуск с тем же — идентичный output (model_ref включает temperature=0 для агентов). ApplyDecisionидемпотентен: source BC проверяетcase_idcorrelation, не применяет дважды.
Политики
| Триггер | Реакция |
|---|---|
ModerationItemAdded (Matching / Catalog / Pricing / Credentials / Supplier Network / Enrichment / Customer) | → CreateCase |
ModerationCaseCreated | → GatherEvidence |
EvidenceGathered | → RunAgent |
AgentDecisionEmitted + threshold ok | → ApplyDecision |
AgentDecisionEmitted + confidence < threshold | → Escalate |
AgentRunFailed подряд N раз для агента | → AgentDisabledByCircuit + escalate в #tracium-ai-ops |
Daily scheduled (для defer) | → reopen + повторить gather |
| Новая версия модели (RolesUpdatedAt-аналог для модели) | → schedule replay открытых deferred кейсов |
CaseEscalated + case.kind ∈ security_critical | → mandatory human (см. invariants) |
Read-модели
- 🟩
moderation_queue(PG) — текущие кейсы по статусам. - 🟩
moderation_decisions_log(CH) — append-only история всех решений: case, evidence, verdict, confidence, model_ref, latency, applied_outcome. - 🟩
agent_accuracy_dashboard(CH) — per-agent metrics: accuracy vs human escalation outcomes, drift detection. - 🟩
agent_runs_audit(CH) — full input/output для каждого AgentRun. - 🟩
human_escalation_queue(PG) — для UI операторов (только escalated кейсы).
Инварианты
- Каждое
AgentDecisionEmittedимеет(model_ref, prompt_hash, evidence_hash, confidence, reasoning, citations[]). Без них —AgentRunFailed. - Detalism: при тех же
(evidence, model_ref, prompt)+ temperature=0 — идентичный output. Replay воспроизводим. Verdict ≠ acceptеслиconfidence < thresholdагента (configurable perCaseKind, default 0.85).- Security-critical кейсы НЕ автоматизируются:
credential_break_glass_decrypt,security_incident_review,legal_compliance_block— здесь только человек (4-eyes), AI выступает только как анализатор/предупредитель. Эти кейсы имеютcase.kind ∈ security_criticalиEscalationPolicy.always_human=true. ApplyDecisionидемпотентен — source BC дедуплицирует поcase_id.- AI-агент не имеет прямого write-доступа к source BC. Только через published
ProposedActionevent → source BC consumer → policy → команда. - Каждый
AgentRunnerимеет SLA p95 latency < 30 сек. При нарушении — circuit breaker. - Drift detection: если accuracy агента (vs последующих human override / customer complaints) падает ниже X% за окно — auto-disable + alert.
AgentRunappend-only. Старые runs архивируются после 90 дней; aggregate accuracy сохраняется.
Конфигурация AgentRunner
AgentRunner
├── case_kind — для какого CaseKind
├── model_ref — (model_name, version)
├── prompt_template_ref — версионируется
├── temperature — фиксировано 0 для детерминизма
├── max_tokens
├── confidence_threshold — 0.85 default, configurable per kind
├── max_retries — 2 default
├── tools[] — function calling: lookup_canonical, lookup_supplier, search_similar_cases, embedding_similarity
├── rag_collection_ref — какая база похожих кейсов
├── evidence_query — какие данные собирать в GatherEvidence
├── output_schema — JSON schema для verdict
├── escalation_policy_ref
├── enabled
└── version
Изменение prompt / модели / threshold = breaking для accuracy → требует pre-prod evaluation на референсном наборе из 200 ранее resolved кейсов; deploy через blue-green (старый агент не отключается, пока новый не показал ≥ accuracy).
Эскалация на человека (минимизация)
Default — escalation отключена для большинства CaseKind. Включается только если:
EscalationPolicy.always_human = true(для security-critical).- Confidence ниже floor (0.5 default, ниже даже не пытаемся применить).
- Circuit breaker сработал (агент disabled).
- Repeat retries исчерпаны.
Эскалация выписывает в human_escalation_queue + push в #tracium-ai-ops (Slack/Telegram) с full context. Человек разрешает через admin UI; решение записывается в moderation_decisions_log как source=human для последующего обучения / дрифт-метрики.
Интеграционные события (публикуем)
Топик: moderation.events.v1. Partition key: case_id.
| Имя | Когда |
|---|---|
ModerationCaseCreated | Создание кейса (для аналитики) |
AgentDecisionEmitted | Каждое решение |
DecisionApplied | Подтверждение применения |
CaseEscalated | Эскалация |
CaseResolvedByHuman | Финал escalation |
AgentDisabledByCircuit | Для алертов |
И — главное: ProposedAction events в типизированных топиках (например, moderation.actions.matching.v1, moderation.actions.catalog.v1) — на них подписаны source BC consumer’ы.
Подписанные интеграционные события
| Источник | Событие | Реакция |
|---|---|---|
| Matching | ModerationItemAdded(match_review) / OrphanItemAssigned | CreateCase |
| Catalog | ModerationItemAdded(manufacturer_alias_proposal/identity_profile_proposal) | CreateCase |
| Enrichment | EnrichmentReviewRequired | CreateCase(enrichment_critical_attr_review) |
| Supplier Network | InferredRelationshipProposed | CreateCase(inferred_relationship_review) |
| Pricing | PriceRuleConflictDetected | CreateCase(priority_overlap_review) |
| Credentials | CredentialGroupCandidateOpened | CreateCase(credential_group_candidate) |
| Customer | LegalInfoVerificationEdge | CreateCase(legal_info_verification_edge) |
| Source BC | DecisionApplied{case_id} | Mark case applied |
Связи в context map
| BC | Паттерн | Назначение |
|---|---|---|
| Matching / Catalog / Enrichment / Supplier Network / Pricing / Credentials / Customer | Customer/Supplier (источники → Moderation) | Источники публикуют кейсы; не зависят от деталей агентов |
| Source BC (downstream) | PL (Moderation → source) | ProposedAction events с case_id correlation |
| Enrichment | SK (LlmModelRef) | Общий kernel для model versioning |
| External LLM provider | ACL | Sandbox-обёртка; смена провайдера не задевает Moderation domain |
Мини event storming
flowchart LR SRC["🟧 ModerationItemAdded<br/>(из source BC)"] subgraph MOD["Moderation"] CMD1["🟦 CreateCase"] MC["🟨 ModerationCase"] E1["🟧 ModerationCaseCreated"] CMD2["🟦 GatherEvidence"] E2["🟧 EvidenceGathered"] CMD3["🟦 RunAgent"] AR["🟨 AgentRun"] E3["🟧 AgentDecisionEmitted"] DEC{"🟪 confidence + verdict?"} CMD4["🟦 ApplyDecision"] E4["🟧 DecisionApplied"] ESC["🟧 CaseEscalated"] HQ["🟩 human_escalation_queue"] end subgraph EXT["External LLM"] LLM["⚙️ Sandboxed LLM call"] end SRCBC["🟧 ProposedAction → Source BC"] SRC --> CMD1 --> MC --> E1 --> CMD2 --> E2 --> CMD3 CMD3 --> LLM LLM --> AR --> E3 --> DEC DEC -->|accept ≥ threshold| CMD4 --> SRCBC --> E4 DEC -->|low confidence / security| ESC --> HQ
Связанные файлы
- Сценарий:
../scenarios/ai-moderation-flow.md. - Контексты-источники:
matching.md,catalog.md,enrichment.md,supplier-network.md,pricing.md,credentials.md,customer.md. - ADR (TBD) — LLM provider абстракция, sandbox isolation, model versioning policy.
- Архитектура:
../../20-architecture/(TBD: AI-runtime).