arys 1dcfaf46cf feat: no-answer retry, agent status machine, escalation events/timeline (ТЗ §13-15,22,25-27,37, AC-08,16-19)
Phase 2 of the L1->L2 routing engine (Phase 1: MR!4).

- ami_loop() now also captures native AMI DialEnd/Hangup frames (not
  only UserEvent), needed to detect that an escalated agent did not
  answer. No dialplan change required - Redirect already routes the
  client channel into an existing Dial()-based transfer context, so
  Asterisk emits these events on its own; the listener just wasn't
  reading them before.
- retry_escalation_no_answer(): on NOANSWER/BUSY/CANCEL/CHANUNAVAIL/
  CONGESTION, releases the non-answering agent, excludes it, and
  reserves+redirects to the next available agent via the routing
  engine's existing exclude_agent_ids support. Exhausted pool marks
  the escalation failed and leaves the call with the AI instead of
  dropping the client (ТЗ §32).
- Agent status now actually moves through
  RESERVED -> RINGING -> TALKING -> AFTER_CALL_WORK -> AVAILABLE
  instead of staying stuck on RESERVED for the whole call; a new
  acw_sweep_loop background thread (same pattern as the existing
  failed_retry_loop) times out AFTER_CALL_WORK back to AVAILABLE.
- escalations gains attempt_count/real_agent_id/attempted_agent_ids_json
  (migration 0033); fixes a latent bug where assigned_agent_id stored
  the SIP extension instead of the real agent_id despite routing-service
  already returning it in RoutingAgentReserveOut.
- Every transition now records an interaction timeline entry and
  publishes the ТЗ §25 event catalog (AgentReserved/AgentRinging/
  AgentNoAnswer/AgentConnected/TransferCompleted/TransferFailed)
  through the existing emit_voice_event/EventOutboxRow idempotent path.

Not in this MR (see plan): SLA config, Callback, L3 (needs real
technical agents from the business), metrics.
2026-08-30 14:19:23 +05:00
2026-05-09 09:16:06 +05:00
2026-05-09 09:16:06 +05:00

call-center

Омниканальный контакт-центр: телефония (Asterisk), Telegram, WhatsApp, веб-чат, email — плюс встроенный голосовой ИИ-оператор (распознавание речи → LLM → синтез речи). Написан на Python (FastAPI), ~25 сервисов вокруг одной SQLAlchemy-схемы, локально работает на SQLite, в проде — на PostgreSQL.

Документация

Документ Про что
docs/architecture/overview.md Обзор микросервисов и их ролей
docs/architecture/voice-ai.md Голосовой ИИ-оператор подробно
docs/architecture/real-time-voice-service.md Рантайм голосового моста (AudioSocket, TTS/ASR)
docs/architecture/event-schemas.md Схемы событий шины (RabbitMQ)
docs/runbooks/local-setup.md Как поднять проект локально (демо-режим и ручной запуск)
docs/runbooks/deployment.md Как разворачивать (Docker Compose / Kubernetes)
longread.md Сквозной архитектурный ревью репозитория — что реально есть, где технический долг

Быстрый старт

Подробности — в docs/runbooks/local-setup.md. Коротко:

python -m pip install -r requirements.txt
cp .env.example .env      # по умолчанию SQLite, без Docker

python scripts/migrate_core_db.py
uvicorn gateway.app:app --reload --port 8080

Точки входа (после старта gateway): /operator, /supervisor, /admin, /analyst на http://localhost:8080.

Демо-режим одной командой (поднимает весь стек + тестовые данные): scripts/prepare_demo.ps1.

Тесты

pytest -q

Частые задачи

  • Поменять greeting/system prompt голосового бота Айнур — правится в коде: services/shared/ai_operator_config.pyai_operator_default_config(), коммит и деплой; сервис сам синкает значение в БД при старте.
S
Description
migrated from gitlab.konturai.kz
Readme
3.3 MiB
Languages
Python 74.2%
JavaScript 18.8%
HTML 3.4%
CSS 2.9%
PowerShell 0.4%
Other 0.3%