Things to ask for
Everything below is copy-and-paste. Take an ask, paste it where you added Kelam — Claude, your coding agent, or the browser builder — and it happens. There is no syntax to get right; if something's ambiguous it asks you first.
Haven't added it yet? Add the connector to Claude (two minutes) or install the skill into whatever coding agent you already use.
Ask it to make a call
Hand it something you'd otherwise do yourself with a phone and fifteen minutes.
It tells you the number it's about to dial before it dials, and you can watch the transcript as it happens. Calls cost cents a minute; one nobody answers is free.
Ask for something that answers your line
Your workspace comes with a phone number. This is you describing who picks it up.
Ask it to work a list
Over-asking is safe: calls beyond the concurrency limit queue up and dial themselves as slots free. "Stop everything" works at any point.
Ask about what happened
Ask it to fix itself
Say what was wrong and it ships a new version in seconds. The old one stays callable.
Five agents to copy
Each is a complete, working setup. Copy the ask; what it builds is folded underneath if you want to see it.
Front desk
Answers your line, books, texts a confirmation, takes a message when it can't help. The most common agent people build.
What it writes
# agent.yaml name: front-desk description: Answers the main line, books appointments, texts confirmations. language: en languages: [en, es, fr] background_audio: office greeting: en: "Brightside Dental, this is the front desk — how can I help?" es: "Brightside Dental, ¿en qué puedo ayudarle?" fr: "Brightside Dental, bonjour — comment puis-je vous aider ?" phone: inbound: true outbound: true tools: - type: end_call - type: dtmf - type: hold - type: transfer number: "+16175550142" - type: fetch_context
# scenarios/01-instructions.md
You are the front desk for Brightside Dental. You answer the main line.
- Greet warmly, then find out what they need in one question. Keep every
turn to one or two short sentences.
- To book: get the patient's name, the reason, and a day. Offer the two
nearest open slots. Read the booking back and get a yes.
- Spell names back if there is any doubt. Getting it wrong costs a visit.
- Severe pain, swelling or bleeding is urgent: offer to put them through
to the on-call dentist right away.
- Never quote a price. Say the office confirms costs on arrival.
Errand caller
Calls businesses on your behalf, asks one question, hands back typed answers you can sort.
What it writes
# agent.yaml name: errand-runner description: Calls businesses to ask one question and report the answer back. language: en languages: [en] greeting: en: "Hi there — sorry to bother you, I've got a quick question." phone: inbound: false outbound: true outbound: listen_first: true # work out who picked up before speaking voicemail: leave # or `hangup` to leave nothing tools: - type: end_call - type: dtmf # so it can get through phone menus - type: hold
There's a ready-made preset for this shape, so in practice the agent building it just picks that and tunes the wording.
Switchboard
One front desk in front of several specialists. It hands the live caller over — nobody gets called back.
What it writes
# agent.yaml — the front desk name: reception description: Answers the main line and routes callers to the right colleague. languages: [en, es, fr] phone: inbound: true tools: - type: end_call - type: dtmf - type: hold - type: handoff any_agent: true # route to ANY colleague, discovered live
Routing quality lives in each specialist's own one-line description — write those like job descriptions ("handles invoices, refunds and payment plans") and the front desk routes well without ever being updated. Specialists need no phone number of their own.
Follow-up caller
Rings yesterday's no-shows, reschedules, and leaves a decent voicemail when nobody picks up.
What it writes
# agent.yaml (the parts that matter)
outbound:
listen_first: true
voicemail: leave
voicemail_message: >
Hi, this is Brightside Dental calling about your missed appointment.
Give us a ring back when you have a moment and we'll find you a new
time. Thanks very much.
Setting the message records those exact words every time. Leave it empty and the agent composes one from that call's instructions instead — better when the ask differs per call, worse when every message must read identically.
One that checks your real systems
Everything above is conversation. This one does something: it reads your actual calendar mid-call and books into it.
What it writes
# tools/booking.py from kelam import tool, secret, context import httpx @tool async def open_slots(day: str) -> str: """Appointment slots still open on a given day, e.g. 'Saturday'.""" async with httpx.AsyncClient(timeout=5) as c: r = await c.get( context("BOOKING_API") + "/slots", params={"day": day}, headers={"authorization": "Bearer " + secret("BOOKING_KEY")}, ) r.raise_for_status() return r.text
The secret is stored encrypted and never readable back; the base URL is an ordinary setting, so you can repoint it at staging without touching code. Keep tools fast — they run inside a conversational turn, so anything slow is audible as dead air.
Want the field-by-field version? The agent.yaml reference documents everything above, and how it works explains the model underneath. Neither is required reading.