Voice AI platform · SIP PBX · contact centre
The agent talks on the phone. You see every millisecond.
A voice agent that answers calls, calls tools, searches your documents and hands the call to a person when it runs out of road. With everything it did, written down to the millisecond.
- The Starter plan has no subscription
- You can bring your own provider keys
- It installs on your own server
A build in progress. The site says page by page what works and what does not. What is proven, and what is not.
- 7.772 endpoint.detected the budget starts here
- 7.772 llm.started
- 8.272 transcript.final
- 9.857 llm.first_token target 600 ms
- 10.443 tts.started
- 10.862 tts.first_audio target 400 ms
- 10.863 assistant.speech.started 3,091 ms against a target of 1,200
The offsets are copied from the call events. The turn ran two and a half times over budget and the console flagged it. This call is here precisely because it did not go well.[2]
Six things that happen on a company phone line today
None of them is a software problem. They are what anyone who has spent a day next to a company phone already knows. The section below says what we do about each one, and where we have not got there yet.
People ring when you are closed
After six, on a Saturday, during the holidays. The phone rings out, the caller hangs up and rings the next name on their list. You never find out they called.
The same five questions, all day
What do I owe, where is my parcel, what time do you open, can I move my appointment. People paid to read out loud what the system already says.
Nobody knows what was said
The recordings exist somewhere on a server. Nobody listens to them. You find out what someone promised on the phone when the customer complains and asks you to play it back.
The cost of a call is a guess
You know the monthly total. You do not know what Tuesday at eleven cost you, or which campaign is eating the budget.
The robot sounds like a robot
Press-one menus, voices that break words in half, and Romanian treated as one language on a list rather than the language the caller is speaking.
Asking for a person loses everything
A transfer moves the call, not the context. A colleague picks up and asks again for the name, the contract number and what the caller wanted three minutes ago.
Below: what the product does about each one, with a link to the page that proves it
One call, six things to do with it. All in the same product.
These are not modules sold separately. The number, the assistant, the tools, the operator queue, the recording and the cost breakdown are the same objects, in the same console, on the same invoice.
Answer the call
A number bought or imported through Twilio reaches an assistant and it answers. Twilio is the only path proven end to end today; what sits around it — our own switch, a SIP trunk — is written up separately, with what works and what does not.
Understand and look things up
Transcription, model and voice are chosen per assistant, not per platform. The assistant searches your indexed documents and answers from what it found rather than from what the model remembers.
Call your own tools
Your own HTTP tools with a JSON schema, MCP servers, and 25 ready-made connectors — from Google Calendar and HubSpot to Shopify and WhatsApp Business.
Hand the call to a person
Queues, skills, a softphone in the browser, and a human taking the call over without the caller being rung again: their call is never hung up, the operator joins it. The contact centre is not another product; it is the same one.
Write down everything that happened
Two-channel recording, transcription, 66 event types with millisecond offsets, and personal data — card, IBAN, Romanian CNP — masked in transcripts and in logs.
Show you what it cost
Every call carries a per-stage breakdown: what the transcription, the model, the speech and the telephony cost, plus the platform margin. A row with no published price stays at zero and is visibly empty.
- transport audio in and out
- stt speech to text
- endpoint the caller stopped
- llm the model answers
- tool tools and MCP
- tts text to speech
- playback audio to the caller
A call is an ordered ledger of events, and you get all of it.
Every call writes an append-only stream of typed events with millisecond offsets, covering transport, transcription, endpointing, the model, tools, MCP, speech, DTMF, SIP signalling, transfers, queueing, recording and provider fallbacks. The whole vocabulary is printed on the next page.
That stream is what the console draws, what the API returns from the events endpoint, and what a webhook delivers. There is no second, prettier version of the truth — the debug timeline is a straight render of the same rows.
callerHello, I would like to move my appointment on Thursday.
assistantOf course. I can see an appointment on Thursday the fourteenth at ten —
callerSorry, make it the afternoon.
assistantThursday afternoon. I have half past two and half past four free.
A struck-out turn is one the caller never heard to the end. The console renders it that way, and so does the transcript the model is given.[1]
How you see a call, listen to it, and read what it cost
Every call leaves the same five surfaces behind: the list it appears in, the transcript with the tool calls in line, a two-channel recording you can scrub, a cost breakdown per stage, and a supervisor view while it is still running. These are screenshots of the running console, not mockups.
The transcript, with the tools in line
You see the assistant ask, the tool fire, and the answer come back — each with its own latency. That is how you find out where the silence a caller complained about actually came from, instead of guessing at it.
The recording, on two channels
The assistant and the caller are separate waveforms on one timeline, so an interruption is something you can see before you play it. The transcript underneath scrolls with the audio, and the file downloads.
What the call cost, per stage
The quantity that was counted sits next to the published tariff it was multiplied by, with the vendor's own price page linked. A stage whose price nobody verified enters at zero and stays visibly empty rather than being estimated.
The call list, with latency as a column
Time to first token and end-to-end latency are columns next to the price of the call that produced them — not a report you have to go and build. Filter, sort and open any row.
The supervisor console
Operator states, queue membership and the offered/taken/missed counters in one matrix. On a call that is running, listen, whisper and barge from the same row.
The phone numbers and the customer name in these frames were replaced with neutral values before the screenshot was taken. Everything else — the timings, the costs, the tariffs, the waveform — is a real call this installation handled.
What people use it for
Take the calls that repeat
Balance, invoice, meter reading, order status. The assistant looks it up in your system through a tool and answers from real data rather than from the model weights. What it does not know, it hands over.
- Assistant
- Tools
- Knowledge base
- Queue
callerI have an invoice I do not understand.
assistantOf course. I can see the September invoice, 312.40 lei. The difference comes from the self-read meter value on the third.
toolcrm.get_invoice({"account":"…","period":"2026-09"}) → 312.40 RON
Move, confirm, cancel
The simplest conversation to automate and the most irritating one to keep a person on. The assistant reads the calendar, offers slots and writes the change back.
- Assistant
- Tools
- Structured outputs
- Campaigns
callerI would like to move my Thursday appointment.
assistantThursday afternoon I have half past two and half past four free.
toolcalendar.find_slots({"day":"2026-09-10","after":"12:00"}) → 2
Where is my order
The most repetitive question in an online shop, with the answer already written in the database. The assistant finds the order by phone number and reads its status back.
- Shop connector
- Lookup by phone
- Ticket
- Structured output
callerHello, I ordered last week and nothing has arrived.
assistantLet me check on the number you are calling from. Can you confirm the last four digits?
toolshop.get_order({"phone":"+407…"}) → shipped, AWB 4412…
Call back in two minutes, not in two days
A form filled in on the site triggers a call. The assistant asks three qualifying questions and writes the answers as a structured output, ready to import into a CRM.
- Campaigns
- Structured outputs
- Tools
- Scorecards
callerI saw the ad. How much does it cost?
assistantIt depends on consumption. How many connection points does the company have, and at what voltage?
toolcrm.create_lead({"score":"warm","points":3}) → id 48213
Polite reminders, inside permitted hours
The campaign respects calling windows, suppression lists and consent, and every contact it did not call carries one of nineteen named reasons.
- Campaigns
- Suppression lists
- Tools
- Recordings
callerI completely forgot about that invoice.
assistantIt can be paid now through a link sent by SMS, or spread over three months.
toolbilling.send_payment_link({"channel":"sms"}) → 202
The Friday evening call
The office is shut, but the call is taken anyway: the full request, a ticket opened, and a summary sent through before morning.
- Time conditions
- Ticket
- Notification
- On-call transfer
callerI have a problem and I see you are closed. Shall I call tomorrow?
assistantI can take everything down now and a colleague will ring you first thing tomorrow.
toolhelpdesk.create_ticket({"priority":"normal"}) → id 9137
One number, the right destination
Instead of a keypad menu, an open question. The caller says what they need and reaches the right team directly, with the context carried across.
- Intent routing
- Transfer with context
- Queues
- Extensions
callerI would like to speak to somebody in sales.
assistantI will put you through. So you do not have to repeat it, what is it about, briefly?
tooltransfer({"to":"sales","context":"summary"}) → ringing
Ask an hour after the call, not a month later
Three short questions, the answers written as a structured output, and anybody who wants a person gets one straight away.
- Campaigns
- Structured outputs
- Boards
- Scorecards
callerYes, I have two minutes.
assistantFirst question: on a scale of one to ten, how easy was it to resolve?
toolsurvey.record_answer({"q":1,"value":8}) → 200
One control plane for the agent, the switch and the people.
Most voice AI stops at the agent. You still need numbers, trunks, an IVR, a queue, someone to escalate to when the agent runs out of road, and a recording you can hand to compliance. CallAgent is those things in one system: a voice agent platform, a SIP PBX and a contact centre that share one tenant, one billing ledger and one call record.
The agent side is provider-agnostic. You choose a transcriber, a model and a voice per assistant, from adapters the gateway registers at boot, and you see the latency and cost of each choice on the card you are choosing from rather than on a comparison page nobody opens.
The telephony side is a real switch, not a webhook. Numbers, SIP trunks, extensions, ring groups, time conditions, voicemail and conference rooms exist as first-class objects, so an assistant can be one destination in a dial plan instead of the whole product.
Build it and publish it
A five-step wizard, presets that pick the transcriber, model and voice together, and a publish step that refuses configurations which would drop the call.
See what happened
A millisecond timeline, the transcript, a dual-channel recording, per-stage cost and scorecards over real calls. The rows the console draws are the rows the API returns.
Wire it into everything else
221 documented paths, webhooks you can redeliver, MCP servers attached as tools, and CallAgent itself exposed as an MCP server.
18 providers you can pick today.
A transcriber, a model and a voice are configuration on an assistant rather than one choice made once for the whole platform, and a fallback chain moves to the next provider when one fails mid-call.
The list below is what can be selected today, read from the same registry the console runs on. Roughly as many again are seeded in that registry and marked not implemented; we do not count those, because a name you cannot select is not an option.
Language models 5
- OpenAI
- Anthropic
- Google Gemini
- Groq
- Custom OpenAI-compatible LLM
Transcription 12
- Deepgram
- AssemblyAI
- OpenAI
- OpenAI Realtime Transcription
- Gladia
- Speechmatics
- Soniox
- Cartesia
- ElevenLabs Scribe
- Sonix
- Talkscriber
- xAI
Speech synthesis 1
- ElevenLabs
The count is counted from the application registry rather than typed by hand, and it changes on its own when the registry changes. Three have been used on a real call: Anthropic for the model, ElevenLabs for transcription and ElevenLabs for the voice.[3]
What departments ask before a signature
The list below is what we have. The list of what we do not have — certifications, a penetration test, SAML — is on the security page and it is just as long.
multi-tenant
An organization scope applied globally, plus policies, plus tenant resolution before model binding.
roles
Ten roles over 71 permissions, scoped to the organization rather than global.
audit
Who changed what, as records readable in the console rather than as log lines.
redaction
Luhn-checked card numbers, email, phone, IBAN and national ids, masked in transcripts and logs.
your storage
Recordings can go to your own bucket on S3, R2, Azure Blob or an S3-compatible store.
region
The installation region is configurable and starts in the European Union.
The numbers we do have
We have no billions of calls and no uptime percentage. We have these, and every one can be checked in the repository.
- 2 239
- tests run, of which 2,237 passed and 2 were skipped
- 18
- provider ids registered by the gateway
- 70
- event types a call can write
- 305
- REST routes, of which 221 documented in OpenAPI
The test count comes from the build report. Providers and event types are counted when this page renders.
Nine areas, one tenant.
The console groups everything into the nine sections below. Each name is a real object with its own screens, its own API routes and its own permissions.
| Build | Assistants · Tools · MCP servers · Knowledge bases · Structured outputs · Squads |
|---|---|
| Telephony | Phone numbers · SIP trunks · Extensions · IVRs · Ring groups · Queues · Voicemail boxes · Conference rooms · Time conditions |
| Contact Center | Operators · Skills · Dispositions · Live calls · Wallboard |
| Engage | Calls · Campaigns |
| Observe | Analytics · Boards · Scorecards · Eval suites · Simulation suites · Monitors · Issues |
| Developers | API keys · Webhook endpoints |
| Platform | Provider credentials · Storage destinations · Connections · Integrations · Customers |
| Organization | Members · Roles · Audit log |
| Billing | Credits · Usage · Invoices · Prices · Products · Enterprise contracts |
What people ask first
What is CallAgent?
CallAgent is a voice AI platform with a SIP PBX and a contact centre in the same product: you build an assistant that answers the phone, give it a number, connect it to your systems through tools, and when it runs out of road it hands the call to a human operator from the same console.
Does it work in Romanian?
Yes, with one caveat we would rather state ourselves. The console, the guides and the billing are in Romanian, the personal-data masking recognises the Romanian CNP, and the language is set per assistant. On the first real calls the language was left on "multi", the transcriber labelled Romanian as Hindi and the answers came out wrong; setting Romanian explicitly on the assistant fixes it, but the default is still "multi", so it is a setting to make rather than a guarantee.
What does a minute of calling cost?
The platform charges €0.10 a minute, applied to the real billable seconds rather than to rounded-up minutes; on top of that you pay provider costs at their price, and if you bring your own provider keys you pay only the €0.10. The Starter plan has no subscription. There is no free trial yet.
Can we install it on our own servers?
Yes. Installing on your own server is documented, the whole stack runs in containers, and recordings and transcripts can be written straight into your own bucket on S3, R2, Azure Blob, Google Cloud Storage, Supabase or any S3-compatible service. What we do not offer is a managed EU region of our own: if you want the data in a particular place, you choose the server.
Is it production ready?
No, and we would rather you did not find that out later. On 5 September 2026 the first eleven real calls went out through Twilio: five ended normally, six failed, and the first turn took 3,091 ms against a 1,200 ms target. We have served no customers, taken no real payment, and no call has yet gone over a SIP trunk of our own.
The part most sites leave out.
This build has 2,237 passing tests and, since 5 September, eleven real calls through Twilio. Six of them failed, the transcriber mistook Romanian for Hindi, and the first turn came in two and a half times over the latency budget. This is on the front page because you would find out anyway.
The habit is written into the product, not only into this page: a cost derived from list prices is prefixed and says it is an estimate, an unmeasured latency says so, and a tool that would need a sandbox refuses to run rather than pretending.
- Real calls ever placed
- 11
- Ended normally
- 5
- Failed
- 6
- First turn, measured against target
- 3 091 / 1 200 ms
- Customers served so far
- 0
- Automated tests passing
- 2 239
Three of the six numbers are bad and are printed in red. They are on the front page because otherwise the sentence next to them would be worth nothing.
Notes
- 1 The exchange above is an example written for this page, not a real transcript. The strike-through marks the turn the caller never heard to the end.
-
2
The real call:
01M1RRDYJH6XAJY2M5XQX9Z6XD, tablecall_events. Twilio, ElevenLabs scribe_v2_realtime, Anthropic claude-sonnet-4-6, ElevenLabs eleven_flash_v2_5. Targets:config/callagent.php, keylatency_targets_ms. -
3
Provider ids:
apps/voice-gateway/src/providers/real-adapters.ts, mirrored inconfig/marketing.phpand returned by the gateway atGET /health.