Open-source AI-native call center: bot-first voice agents on FreeSWITCH, single Go binary.
362
The application image of aicc, an open-source call center where the AI is the default answer, not an add-on. Every inbound call is answered by a realtime speech-to-speech voice model; a flow steers the conversation and decides when a person is needed, and the caller is then transferred into a real mod_callcenter queue where agents work in the browser. The bot phase and the human phase end as one call record, one transcript and one recording.
This image is one Go binary: the REST API, the SSE event stream, the embedded web interface, and the SIP endpoint FreeSWITCH bridges AI calls to. It is not the whole product. It needs:
PostgreSQL 18
FreeSWITCH, as rasonyang/freeswitch-aicc with the same tag
A voice provider key: OpenAI, Qwen, Doubao, Gemini, or your own OpenAI-Realtime-compatible gateway
For agents, the web-sip-phone Chrome extension
Platforms: linux/amd64 and linux/arm64
Base image: gcr.io/distroless/static-debian12:nonroot — no shell, no package manager, runs as nonroot (uid 65532)
License: Apache-2.0
Tags are aicc release tags. Exact tags only; there is no latest, so a deployment names the build it runs and a pull cannot change it.
Run the application and the switch at the same tag. They share the luacc.* contract that the switch's Lua scripts read, and a mismatched pair breaks phone registration.
| Tag | Switch image |
|---|---|
v0.1.1 | rasonyang/freeswitch-aicc:v0.1.1 |
v0.1.0 | rasonyang/freeswitch-aicc:v0.1.0 |
The supported way to run this image is the Compose stack in the repository. It wires PostgreSQL, the switch and the application together and seeds a demo dataset. Compose mounts files from the checkout, so run it from deploy/.
git clone --depth 1 https://github.com/rasonyang/ai-native-callcenter
cd ai-native-callcenter/deploy
cp .env.example .env
Set these lines in deploy/.env:
FS_EXTERNAL_IP=<the address phones reach this host at>
AICC_PROVIDER=openai
OPENAI_API_KEY=<key>
# Inside mainland China, use these two instead of the two lines above:
#AICC_PROVIDER=qwen
#ALIYUN_API_KEY=<key>
# Pull the published images instead of building from the checkout:
AICC_IMAGE=rasonyang/ai-native-callcenter:v0.1.1
AICC_FS_IMAGE=rasonyang/freeswitch-aicc:v0.1.1
Then start the stack and check it:
docker compose up -d
docker compose ps -a # three running, lua-role exited (0)
docker compose logs aicc | grep 'esl connected'
Open http://<host>:8080 and sign in as admin / aicc@123. The demo dataset includes a team, two queues, six published bilingual flows, eighteen simulated customer phones and a week of history. The main line is 800-555-0199. Every demo password is aicc@123; change them, and empty AICC_SEED, before the host faces anyone. See the production checklist.
The deployment guide covers the demo data, making a test call, recordings, upgrading and troubleshooting.
Every setting is an environment variable. The full registry, with defaults and explanations, is the repository's .env.example. Two rules apply to all of them:
= is the value, comments included.The settings a deployment usually touches:
| Variable | Description |
|---|---|
AICC_ENV | dev (text logs) or prod (JSON logs) |
AICC_DATABASE_URL | PostgreSQL connection string. Migrations run at startup, forward-only, under an advisory lock |
AICC_ESL_ADDR, AICC_ESL_PASSWORD | The switch's event socket. aicc uses port 18021, not the stock 8021 |
AICC_SWITCH_DOMAIN | Must equal FreeSWITCH's $${domain} |
AICC_SIP_DOMAIN, AICC_SIP_WSS_URL | The realm and the WebSocket URL handed to an agent's browser phone at sign-in. Behind TLS, AICC_SIP_WSS_URL is the proxy's wss:// URL |
AICC_PROVIDER | openai, qwen, gateway, doubao or gemini. One provider answers every call, chosen at startup; a call's language never selects it |
OPENAI_API_KEY, ALIYUN_API_KEY, REALTIME_API_KEY, DOUBAO_API_KEY, GEMINI_API_KEY | The credential of the selected provider. Without it the application starts, but the bot does not answer and calls go to the number's fallback queue |
AICC_PROVIDER_ENDPOINT, AICC_PROVIDER_MODEL | Override the provider profile's endpoint and model, e.g. a proxy or regional host |
AICC_BOT_SIP_HOST, AICC_BOT_SIP_PORT | The SIP endpoint the switch bridges AI calls to. Default 0.0.0.0:6060 |
AICC_BOT_BACKEND_BASE | Base URL a flow's HTTP tools call. Empty makes those tools fail, and the bot offers a transfer instead of inventing facts |
AICC_RECORDING_BACKEND | FS (serve from AICC_RECORDING_DIR) or S3 (any S3-compatible store, via AICC_S3_*) |
AICC_SEED | demo fills an empty database with the sample dataset; fresh removes only what the seed created |
AICC_METRICS_ADDR | /metrics, /healthz, /readyz. No authentication, so it defaults to loopback |
| Port | Purpose |
|---|---|
| 8080/tcp | REST API (/api/v1), SSE event stream, web interface |
| 6060/udp | SIP endpoint of the AI leg. Reached by the switch, not by phones |
| 40000-40999/udp | RTP of the AI leg |
| 9090/tcp | Metrics and health. Closed until AICC_METRICS_ADDR opens it deliberately |
Only 8080 needs to be reachable from outside. The AI leg's SIP and RTP stay on the network shared with the switch. In the Compose stack the switch dials the application at a fixed IP (AICC_APP_IP), because dialling by name makes the switch advertise its external address for the bot's media.
| Path | Contents |
|---|---|
/var/log/aicc | Application logs (AICC_LOG_DIR) |
AICC_RECORDING_DIR | With AICC_RECORDING_BACKEND=FS, mount the volume the switch records into, read-only. The switch writes as its own group (999 in freeswitch-aicc), so add that group to this container (group_add: ["999"]) |
Without the demo seed the database has no accounts. The image's entrypoint is the binary itself, so:
docker compose exec aicc /usr/local/bin/aicc useradd -username admin -password '…' -role ADMIN
API keys are issued at runtime through POST /api-keys, not configured through the environment.
The human path, the AI path, the product surface and the packaging are built and verified against live FreeSWITCH and live providers. Performance is not yet a claim this project makes: the capacity budget and latency target in the design are intentions until the benchmark campaign has run.
Content type
Image
Digest
sha256:2a6b076e8…
Size
10.9 MB
Last updated
about 11 hours ago
docker pull rasonyang/ai-native-callcenter:v0.1.1