Commit Graph
4 Commits
Author SHA1 Message Date
Hermes Agent 92095ff5d6 fix: release reserved L2 agent when AMI redirect fails during escalation
deploy / deploy (push) Successful in 32s
Found during production smoke test: if the AMI Redirect call in
create_escalation() raises (channel gone, AMI hiccup), the agent stays
RESERVED forever with no owning call — orphaned out of the pool until
someone fixes it by hand. Now releases the agent and marks the
escalation failed before re-raising as a 502.
2026-08-29 14:01:40 +05:00
Hermes Agent 8c131440fc config: route voice_lab_ai / ivr_aimaq_ai_ru queues through L2 agent pool
deploy / deploy (push) Successful in 28s
Enables the new Routing Engine for the Tele2 Kazgaz DID +77476456048
(lands on queue 7100/voice_lab_ai): AI handoff now reserves a real L2
agent from the pool instead of the static extension redirect.
2026-08-29 13:37:30 +05:00
Hermes Agent 1ad4e1ec6e feat: surface L2 agent pool and escalations on supervisor screen
- routing-service: GET /escalations (list recent escalation attempts)
- supervisor UI: new panel showing the real agent pool (status, level,
  tenant, skills, calls handled) fed by GET /agents, with a form to add
  operators to the pool
- supervisor UI: new live escalation feed (AI->L2 handoffs, status,
  assigned operator), auto-refreshed every 5s alongside live calls
2026-08-29 13:28:14 +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