← All guides AI Release
RU Subscribe to @ai_release1

Step-by-Step Guide: How to Deploy a Self-Hosted Lampline Voice Agent and Import from Dialogflow CX

Updated: 20.10.2026 · AI Release · @ai_release1
Step-by-Step Guide: How to Deploy a Self-Hosted Lampline Voice Agent and Import from Dialogflow CX

TL;DR

- A Linux host (Ubuntu 22.04 LTS or similar) with 2 vCPU / 4 GB RAM / 20 GB free disk as a starting point

- Docker Engine + the Compose plugin

- A domain or subdomain with an A record pointing to the host, e.g. voice.example.com

- A Dialogflow CX agent and permission to export it (dialogflow.agents.export)

- API keys for the LLM, STT (speech-to-text) and TTS (text-to-speech) providers your Lampline build supports

Requirements and setup

Illustration: Requirements and setup
Illustration: Requirements and setup

Check the basics before installing anything:

docker --version && docker compose version
df -h /opt
dig +short voice.example.com

Example: dig must return your server IP. If it returns nothing, fix DNS first — TLS issuance will fail otherwise.

If you are deploying on a home machine instead of a VPS, the network part differs (NAT, port forwarding, dynamic IP) — see How to add AI to your home server: self-hosted services guide.

Step 1. Prepare the host and export the Dialogflow CX agent

Illustration: Step 1. Prepare the host and export the Dialogflow CX agent
Illustration: Step 1. Prepare the host and export the Dialogflow CX agent

What to do: create the working directory, install Docker if it is missing, then export your Dialogflow CX agent to a ZIP file.

Why: Lampline is a containerised service, so it needs Docker and a persistent directory. Dialogflow CX is the source of your intents, flows and training phrases — the export is the only portable artefact you can move into a self-hosted runtime.

sudo apt-get update && sudo apt-get install -y docker.io docker-compose-v2 unzip
sudo usermod -aG docker "$USER"   # log out and back in afterwards
sudo mkdir -p /opt/lampline && sudo chown "$USER" /opt/lampline
cd /opt/lampline && mkdir -p data import

Export the agent in the Google Cloud console: open Dialogflow CX → your project → your agent → Agent settings (gear icon) → Export agent → Export as ZIP → Download. The browser saves something like agent-export.zip.

The REST equivalent, if you prefer scripting, is the exportAgent method on an agent resource. The API version and the exact resource path change over time, so copy the URL from the Dialogflow CX REST reference rather than from memory:

gcloud auth print-access-token > /tmp/token
curl -X POST \
  -H "Authorization: Bearer $(cat /tmp/token)" \
  -H "Content-Type: application/json" \
  "https://dialogflow.googleapis.com/v3/projects/<project-id>/locations/<location>/agents/<agent-id>:exportAgent" \
  -d '{"agentUri":"gs://<bucket>/agent-export.zip"}'

Example: a successful call returns a long-running operation object {"name": "projects/.../operations/..."} — the ZIP then appears in the bucket you named.

Copy the file to the host and unpack it only for inspection:

scp agent-export.zip <user>@voice.example.com:/opt/lampline/import/
cd /opt/lampline/import && unzip -l agent-export.zip | head -20

How to check: unzip -l lists agent.json, a flows/ directory and intent/test-case entries. If the listing is empty or the archive is 0 bytes, the download failed — repeat the console export.

Export itemWhat it holdsWhat you will do with it
`agent.json`agent-level settings: default language, time zone, speech settingscopy these values into the Lampline agent config so recognition matches
`flows/`pages, routes, parameters, conditionsthe flow logic you must re-create or verify after import
intents / training phrasesexample utterances per intentthey become the utterance examples for the Lampline agent
webhooksfulfillment URLs pointing at your backendreplace with URLs reachable from the Lampline host
test casesregression scenariosre-run them as scripted test calls in Step 3

Step 2. Deploy Lampline and import the agent

What to do: write .env and compose.yaml, start the container, then run the importer against the uploaded archive.

Why: the container is the runtime that hosts the agent; the import converts Dialogflow CX artefacts into the internal format Lampline serves over voice.

cd /opt/lampline
cat > .env <<'EOF'
LAMPLINE_PUBLIC_URL=https://voice.example.com
LAMPLINE_ADMIN_KEY=<long-random-string>
LLM_API_KEY=<provider-key>
STT_API_KEY=<provider-key>
TTS_API_KEY=<provider-key>
EOF
chmod 600 .env
services:
  lampline:
    image: ghcr.io/<vendor>/lampline:<version>   # exact image and tag: check the documentation
    restart: unless-stopped
    env_file: .env
    ports:
      - "127.0.0.1:8080:8080"    # host port : container port — both build-specific
    volumes:
      - ./data:/app/data         # persistent agents, prompts, call logs
      - ./import:/import:ro      # read-only drop zone for CX exports
docker compose pull && docker compose up -d
docker compose logs -f --tail=50 lampline

Example: the logs end with a line announcing the HTTP listener, e.g. listening on 0.0.0.0:8080. docker compose ps shows Up (healthy).

Discover the real import command instead of guessing — every build names its subcommands differently (check the documentation):

docker compose exec lampline lampline --help
docker compose exec lampline lampline agents import --help

Then run the import, for example:

docker compose exec lampline \
  lampline agents import --from /import/agent-export.zip --name support-cx

How to check: the import prints a summary — number of intents, flows and utterances created, plus skipped items. Confirm the agent is registered:

curl -s -H "Authorization: Bearer $LAMPLINE_ADMIN_KEY" \
  http://127.0.0.1:8080/api/agents | head

You should see support-cx in the JSON. If the response is 401, the admin key in .env and the one in the request differ.

Finally, put Caddy in front so browsers get HTTPS:

sudo caddy reverse-proxy --from voice.example.com --to 127.0.0.1:8080

Example: https://voice.example.com then resolves with a valid certificate, and the Lampline UI or health endpoint responds instead of a browser warning.

Step 3. Verify the agent end to end

Illustration: Step 3. Verify the agent end to end
Illustration: Step 3. Verify the agent end to end

What to do: check the health endpoint, run a text turn through the agent, then place one real voice call.

Why: a green container does not prove the agent answers correctly — STT, the LLM, TTS and the imported flow are four separate links in one chain, and each fails differently.

curl -s https://voice.example.com/health
curl -s -X POST https://voice.example.com/api/agents/support-cx/test \
  -H "Authorization: Bearer $LAMPLINE_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text":"I want to change my delivery address"}'

Endpoint paths are build-specific (check the documentation); the shape of the test is not — send one utterance you know is covered by an imported training phrase.

Example: the response contains the matched intent or flow page plus the generated reply, e.g. {"matched":"change_address","reply":"Sure — what is the new address?"}. A reply of {"matched":null} means the import skipped that intent, so re-check the import summary.

Then do one live call from a browser or a softphone to your public URL and confirm you hear the TTS voice and the transcript appears in the logs:

docker compose logs -f lampline | grep -Ei "stt|tts|turn"

Success checklist:

Once the service is stable, add uptime alerting — How to Set Up VPS Monitoring via a Telegram Bot with Mini App covers the bot side; point its checks at /health.

Troubleshooting

Problem. The container will not start and the port is already taken

sudo ss -ltnp | grep -E ':8080|:443'
docker compose down && docker compose up -d

Problem. The export call fails with a permission error

gcloud auth login && gcloud auth print-access-token >/dev/null && echo ok

Problem. The voice widget loads but never connects

docker compose up -d && docker compose logs --tail=30 lampline

Summary and next steps

You now have a self-hosted Lampline instance behind TLS with a Dialogflow CX agent imported and verified by a text turn and a live call. Next, replace the CX webhook URLs with endpoints reachable from the Lampline host and re-run your exported test cases as scripted calls.

FAQ

Can I import a Dialogflow CX agent without a Google Cloud service account?

Yes, if you export the agent as a ZIP from the console with your own user account and upload that file to the host. A service account is only needed when you call the export API from a script.

What happens to Dialogflow CX test cases and webhooks after import?

Treat them as reference material: webhook URLs that point at Google-hosted fulfillment will not work outside CX and must be replaced, and test cases have to be re-run as scripted calls against Lampline.

Where do imported agents live, and will they survive a container restart?

They are written to the mounted ./data volume. As long as you keep that volume and do not run docker compose down -v, a restart or image upgrade keeps your agents, prompts and logs.

What latency should I expect from the voice agent?

This guide does not publish a benchmark, because end-to-end latency depends on your chosen STT, LLM and TTS providers and their network distance. Measure it on your own host against the documented timing or log fields in your build.

🤖 AI summary