> ## Documentation Index
> Fetch the complete documentation index at: https://docs.brainstormer.io/llms.txt
> Use this file to discover all available pages before exploring further.

# HITL Service

> Human-in-the-Loop service — escalation routing, operator management, approval workflows.

# HITL Service

Port **4006**. Manages operator oversight of AI agent conversations.

## Endpoints

| Route                            | Method | Purpose                                 |
| -------------------------------- | ------ | --------------------------------------- |
| `/health`                        | GET    | Health check                            |
| `/hitl/escalations`              | POST   | Create escalation                       |
| `/hitl/escalations`              | GET    | List escalations (filter: status, mine) |
| `/hitl/escalations/:id`          | GET    | Get escalation + notes                  |
| `/hitl/escalations/:id/claim`    | POST   | Claim from queue                        |
| `/hitl/escalations/:id/respond`  | POST   | Send operator message                   |
| `/hitl/escalations/:id/handback` | POST   | Hand back to AI                         |
| `/hitl/escalations/:id/close`    | POST   | Close escalation                        |
| `/hitl/escalations/:id/notes`    | POST   | Add internal note                       |
| `/hitl/approvals`                | GET    | List approvals (filter: status)         |
| `/hitl/approvals/:id/approve`    | POST   | Approve response as-is                  |
| `/hitl/approvals/:id/edit`       | POST   | Edit and approve response               |
| `/hitl/approvals/:id/reject`     | POST   | Reject with reason                      |
| `/hitl/operators`                | GET    | List org operators                      |
| `/hitl/operators/me`             | GET    | Current operator session                |
| `/hitl/operators/status`         | PUT    | Update operator status                  |
| `/hitl/operators/schedule`       | PUT    | Update working hours                    |
| `/hitl/operators/heartbeat`      | POST   | Heartbeat + Redis refresh               |
| `/hitl/operators/availability`   | GET    | Check operator availability             |
| `/hitl/ws`                       | WS     | WebSocket for real-time operator feed   |

## Architecture

### Redis Pub/Sub Channels

| Channel Pattern                           | Direction  | Purpose                                |
| ----------------------------------------- | ---------- | -------------------------------------- |
| `hitl:escalation:{orgId}`                 | Bot → HITL | Escalation requests                    |
| `hitl:approval:{orgId}`                   | Bot → HITL | Approval requests                      |
| `hitl:message:{conversationId}`           | HITL → Bot | Operator messages to end users         |
| `hitl:user_message:{conversationId}`      | Bot → HITL | User messages to operators             |
| `hitl:resolution:{botId}`                 | HITL → Bot | Handback/close/expire events           |
| `hitl:approved:{conversationId}`          | HITL → Bot | Approval results (approved/rejected)   |
| `hitl:escalation_result:{conversationId}` | HITL → Bot | Assignment result for synchronous flow |

### WebSocket Events

All WS broadcasts use the `event` key (not `type`).

| Event                   | Direction       | Purpose                  |
| ----------------------- | --------------- | ------------------------ |
| `escalation.created`    | Server → Client | New escalation           |
| `escalation.claimed`    | Server → Client | Operator claimed         |
| `escalation.resolved`   | Server → Client | Handback/close/expire    |
| `escalation.assigned`   | Server → Client | Auto-assigned from queue |
| `approval.created`      | Server → Client | New approval request     |
| `approval.resolved`     | Server → Client | Approval processed       |
| `presence.update`       | Server → Client | Operator online/offline  |
| `escalation.claim`      | Client → Server | Claim an escalation      |
| `conversation.respond`  | Client → Server | Send message to user     |
| `escalation.handback`   | Client → Server | Hand back to AI          |
| `escalation.close`      | Client → Server | Close escalation         |
| `operator.availability` | Client → Server | Update status            |

### Key Services

| Service                   | Purpose                                                                                                     |
| ------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `orchestrator.service.ts` | Core routing brain — handles escalation/approval events, claim/handback/close, timeout checker, queue drain |
| `assignment.service.ts`   | Finds available operators (round-robin by load, agent scope, working hours)                                 |
| `notification.service.ts` | Dispatches alerts to email/Slack/Discord/webhook channels                                                   |
| `schedule.service.ts`     | Timezone-aware working hours check                                                                          |
| `redis.service.ts`        | Pub/sub + operator presence tracking                                                                        |

### Database Tables

* `escalation_requests` — Escalation lifecycle (7 statuses: pending → queued → assigned → active → resolved/expired)
* `operator_sessions` — Operator availability, load, agent scope, working hours
* `escalation_events` — Append-only audit log
* `approval_queue` — Response approval workflow
* `notification_channels` — Multi-channel notification config
* `escalation_notes` — Internal operator notes

### Concurrency

All claim and approval operations use atomic `UPDATE ... WHERE status IN (...) RETURNING *` to prevent TOCTOU race conditions. If two operators claim simultaneously, only one succeeds.

## Bot Service Integration

The bot service connects via `hitl-bridge.service.ts`:

* Subscribes to `hitl:resolution:*`, `hitl:message:*`, `hitl:approved:*`
* Escalation tool (`escalate-to-human.ts`) has 4 lifecycle hooks: `preResponse`, `postResponse`, `onToolCall`, `promptInjection`
* Escalation requests are synchronous — bot waits up to 5s for assignment result to customize user messages
* All user-facing messages are configurable per-agent via tool config

## Environment Variables

* `HITL_SERVICE_PORT` (default: 4006)
* `DATABASE_URL`
* `REDIS_HOST`, `REDIS_PORT`, `REDIS_PASSWORD`
* `LOG_LEVEL`
