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

# Architecture

> End-to-end architecture of the lead ingestion, calling, qualification, and CRM push pipeline.

## High-Level Flow

```text theme={null}
IndiaMART / Facebook / CSV
  -> lead_fetcher.py or streamlit_app.py
  -> leads table
  -> scheduler.py
  -> calls table row created
  -> LiveKit SIP participant created
  -> Vobiz dials the phone network
  -> lead answers the phone
  -> LiveKit room carries audio
  -> AI voice agent joins room
  -> qualification JSON saved
  -> talkingshops_pusher.py creates CRM task
```

## Runtime Services

| Service      | Command                                                     | Responsibility                                                                 |
| ------------ | ----------------------------------------------------------- | ------------------------------------------------------------------------------ |
| Agent        | `python agent_realtime.py start` or `python agent.py start` | Joins LiveKit rooms and conducts calls                                         |
| Scheduler    | `python scheduler.py`                                       | Finds eligible leads, creates call records, starts SIP calls, pushes CRM tasks |
| Lead fetcher | `python lead_fetcher.py`                                    | Polls IndiaMART and receives Facebook webhooks                                 |
| Dashboard    | `streamlit run streamlit_app.py`                            | Shows leads/calls and imports CSV leads                                        |
| Token server | `python token_server.py`                                    | Issues LiveKit JWT tokens for local browser testing                            |
| Database     | PostgreSQL                                                  | Stores leads, call attempts, durations, statuses, and qualification data       |

## Call Room Contract

The scheduler creates one LiveKit room per lead:

```text theme={null}
ignitech-lead-{lead_id}
```

The SIP participant identity must be:

```text theme={null}
sip-lead-{lead_id}
```

The agents use this identity format to detect that the participant is a phone caller and to extract the lead ID.

## Concurrency Control

The scheduler limits active outbound calls using:

```env theme={null}
MAX_CONCURRENT_CALLS=1
```

Active calls are rows in `calls` with `status='calling'`. Before starting more calls, the scheduler also fails stale `calling` rows older than:

```env theme={null}
STALE_CALL_MINUTES=5
```

This prevents stuck call records from permanently blocking the queue.

## Calling Window

Calls only start when the local time is inside the configured window:

```env theme={null}
CALL_TIMEZONE=Asia/Kolkata
CALL_HOURS_START=9
CALL_HOURS_END=20
CALL_ALLOWED_WEEKDAYS=monday,tuesday,wednesday,thursday,friday,saturday
```

The end hour is exclusive. With the values above, calls can start from 09:00 through 19:59.

## Deployment Shape

`docker-compose.yml` runs:

* `db`: PostgreSQL 16
* `agent`: defaults to `python agent_realtime.py start`
* `lead_fetcher`: lead ingestion service
* `scheduler`: call scheduler and CRM push loop
* `dashboard`: Streamlit dashboard on container port `8501`, bound to host `127.0.0.1:8502`
* `web`: token server
