Commit Graph
8 Commits
Author SHA1 Message Date
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
Hermes Agent 2243f305b8 feat: L1->L2 agent pool and routing engine for voice escalation
Replaces the hardcoded single-extension redirect for AI->human call
escalation with a real Agent Pool + Routing Engine:

- agents/escalations/routing_rules tables (migration 0031), asterisk_call_links
  gains tenant_id/current_level/required_skills_json/priority.
- services/routing_service/engine.py: level/tenant/skill filtered agent
  selection with atomic (CAS) reservation, no double-booking.
- routing-service: /agents CRUD + /internal/routing/reserve-agent and
  /internal/routing/release-agent.
- asterisk-bridge-service: voice_ai.request_handoff now uses the Routing
  Engine automatically for any queue_code configured in
  ASTERISK_QUEUE_LEVEL_MAP_JSON (all other queue_codes keep the existing
  static ASTERISK_TRANSFER_TARGET_MAP_JSON behavior unchanged); new
  POST /asterisk/live-calls/{call_id}/escalations entrypoint; agent is
  released back to AVAILABLE and the escalation closed when the call ends.

Targets the Tele2 Kazgaz DID +77476456048 (from-tele2-kazgaz context) as the
first queue wired to real L2 routing instead of AI-only.

Known gap (documented in docs/architecture/l1-l2-routing-engine.md):
automatic no-answer retry-to-next-agent needs a small, separately reviewed
dialplan change and is left for a follow-up MR rather than guessed at blind.

Tests: services/routing_service/engine.py covered by
tests/test_routing_engine.py (selection filtering, atomic reservation,
release); existing test_asterisk_bridge_service.py and
test_routing_service_pg_counter.py suites still pass unmodified.
2026-08-28 16:22:32 +05:00
Magzhan Zhumabayev ce3ba270aa Add configurable AI operator persona 2026-05-11 17:37:26 +05:00
Admin 8577d97356 Implement sales CRM workflow foundation 2026-05-10 20:54:01 +05:00
Magzhan Zhumabayev 866d96e560 Implement sales tenant pipeline events 2026-05-10 18:24:06 +05:00
arys f53af1f7dc sales fix 2026-05-09 09:16:06 +05:00
Yera All d959c2b2f0 Add voice name flow controls and analytics 2026-04-05 03:26:18 +05:00
Yera All 5374c202d9 Initial import with GitLab CI/CD and registry deploy flow 2026-04-02 17:05:45 +05:00