46elks API + clarifai API = talk to LLM over SMS
  • TypeScript 97%
  • JavaScript 2.7%
  • Dockerfile 0.3%
Find a file
2026-05-13 00:21:11 +02:00
docs better weather forecasts 2026-05-13 00:21:11 +02:00
patches bigint for calc tool 2026-05-12 21:18:06 +02:00
scripts now with better diagrams using d2 2026-05-12 22:17:17 +02:00
src better weather forecasts 2026-05-13 00:21:11 +02:00
.dockerignore init commit (working!) 2026-05-12 00:37:13 +02:00
.env.example init commit (working!) 2026-05-12 00:37:13 +02:00
.gitignore remove .env.prod from tracking 2026-05-12 23:49:03 +02:00
Dockerfile now with better diagrams using d2 2026-05-12 22:17:17 +02:00
fly.toml remove .env.prod from tracking 2026-05-12 23:49:03 +02:00
ideas.md more tools (web_fetch, directions...) + docs 2026-05-12 08:17:53 +02:00
package.json now with better diagrams using d2 2026-05-12 22:17:17 +02:00
pnpm-lock.yaml neat diagrams 2026-05-12 21:38:45 +02:00
pnpm-workspace.yaml bigint for calc tool 2026-05-12 21:18:06 +02:00
README.md better weather forecasts 2026-05-13 00:21:11 +02:00
tsconfig.json init commit (working!) 2026-05-12 00:37:13 +02:00

SMS LLM Agent

A lightweight Node.js server that receives SMS via 46elks, queries Kimi K2.6 via Clarifai with web search, and replies via SMS.

How It Works

  1. User texts your 46elks virtual number
  2. 46elks POSTs to your /elks/sms?token=SECRET webhook
  3. Server calls Kimi K2.6 via Clarifai with a web_search tool
  4. Server sends the reply back via 46elks API

Prerequisites

  • 46elks account with a virtual number
  • Clarifai account with a Personal Access Token
  • fly.io account (or any host with a public URL)

Setup

1. Configure Your 46elks Number

In the 46elks dashboard:

  • Go to Numbers
  • Set sms_url to: https://your-app.fly.dev/elks/sms?token=YOUR_SECRET_TOKEN

2. Set Secrets

If you have a .env file, import it directly:

fly secrets import < .env

Or set them individually:

fly secrets set \
  ELKS_USERNAME="your_46elks_username" \
  ELKS_PASSWORD="your_46elks_password" \
  CLARIFAI_PAT="your_clarifai_pat" \
  WEBHOOK_TOKEN="your_random_secret_token"

Note: fly secrets import can choke on quoted values (e.g. KEY="value"). Remove quotes from .env values if you hit issues.

3. Deploy

fly deploy

4. Test

Text your 46elks number. You should get an LLM-powered reply within a few seconds.

Local Development

cp .env.example .env
# Fill in your credentials
pnpm install
pnpm dev

Testing Without Sending SMS (Free)

You can test the LLM and web search logic without spending money on SMS messages. Only CLARIFAI_PAT and WEBHOOK_TOKEN are required.

# Start without 46elks credentials — SMS sending is automatically disabled
CLARIFAI_PAT="..." WEBHOOK_TOKEN="test" pnpm dev

curl -X POST "http://localhost:8080/elks/sms?token=test" \
  -d "from=+4712345678" \
  -d "to=+46766861001" \
  -d "message=what is the weather in Oslo"

The reply is logged to console as [SMS DISABLED] Reply to +4712345678: ... — no actual SMS is sent.

Available Tools

The agent has access to these tools:

Tool Description Default
calculate Math expressions and unit conversions
get_weather Current weather + forecast via Open-Meteo 7 days (up to 16)
convert_currency Live exchange rates via ECB/Frankfurter
get_directions Turn-by-turn directions via OpenRouteService foot-walking
web_search DuckDuckGo/Brave web search
web_fetch Fetch full text of a URL

Weather understands natural language like "tomorrow", "next week", or "2 weeks" and requests the appropriate forecast length automatically.

Full Integration Test (With SMS)

Use ngrok to expose localhost:

ngrok http 8080

Then temporarily set your 46elks sms_url to the ngrok URL.

Architecture Notes

  • One-shot: No conversation history (stateless). Each SMS is independent.
  • Synchronous processing: The webhook handler waits for the LLM response before returning HTTP 200. This keeps the fly.io machine alive for the duration (~2-4 seconds).
  • Auto-stop enabled: Machines stop after idle to save ~$5/mo. Cold start with Node.js is typically 1-2 seconds.
  • Retry safety: 46elks retries webhooks for 6+ hours if non-200. If a cold start causes a timeout, the retry will likely succeed.
  • Web search: Uses DuckDuckGo HTML interface directly (no API key, no browser). Inspired by open-websearch.

Costs (Estimated)

Component Monthly Cost
46elks Swedish VMN €3
fly.io (shared-cpu-1x, 256MB, auto-stop) ~$1-2
Clarifai/Kimi API usage-based (~$0.95/1M input tokens)
46elks SMS (Norway) €0.064 per message

System Prompt

The agent is instructed to:

  • Keep replies under 300 characters
  • Avoid markdown, URLs, emojis
  • Use plain text only
  • Search the web when needed
  • Be conversational

License

MIT