You have heard that WorkingAgents is built on Erlang/OTP and Elixir. You have heard that WhatsApp, Discord, and Cisco use it too. But what is it, actually? Why not just use Python or JavaScript like everyone else? And why should you care?
Here is the entire thing explained without a single line of code.
Start With a Hospital
Imagine a hospital. Thousands of things happening simultaneously. Patients being admitted. Surgeries in progress. Nurses administering medication. Lab results coming back. Ambulances arriving. Cafeteria serving lunch.
Now imagine the hospital is designed so that:
-
Every task happens in its own room. Surgery happens in an operating room. Lab work happens in the lab. Admissions happen at the front desk. No task shares space with another task. If someone spills coffee in the cafeteria, it does not affect the surgery happening on the third floor.
-
Every room has a supervisor. The head of surgery watches the operating rooms. The lab director watches the labs. The nursing supervisor watches the floors. If something goes wrong in one room, the supervisor handles it – without disturbing anyone else.
-
If a room has a problem, it gets cleaned up and reopened. A piece of equipment fails in Operating Room 3? The supervisor closes that room, resets it to a clean state, and reopens it. The patient is moved to Operating Room 4. Surgeries in rooms 1 and 2 continue without interruption. Nobody panics. The system handles it.
-
The hospital never closes for maintenance. Need to upgrade the MRI machine? A new one is installed while the old one is still running. Patients are transitioned to the new machine without anyone being sent home.
-
Adding more patients does not slow down existing patients. A bus crash brings 50 new patients to the emergency room. The ER gets busier, but the cardiology ward, the maternity ward, and the outpatient clinic continue at normal speed. New arrivals do not degrade service for people already being treated.
That is Erlang/OTP. Not a hospital – a way of building software that works like one.
Now imagine building a hospital in Python or JavaScript. All the doctors, nurses, and patients work in one big open room. Everyone shares the same table. If one doctor spills coffee on the table, every chart gets wet. If one patient’s procedure takes a long time, every other patient has to wait because there is only one table. If the room catches fire, everyone is affected – there are no walls. And to upgrade anything, you have to ask everyone to leave, close the entire hospital, do the work, and reopen.
That is the difference. Not a small difference. A fundamentally different design for how work gets done.
What the Words Mean
Erlang is a programming language created by the Swedish telecom company Ericsson in the 1980s. They needed software for telephone switches – systems that handle millions of phone calls simultaneously and cannot ever go down. You cannot tell a country “the phone network is restarting, please try your call again in 5 minutes.”
OTP stands for Open Telecom Platform. It is a set of design patterns, libraries, and tools that come with Erlang. Think of Erlang as the language and OTP as the instruction manual for building reliable systems with that language. OTP is what gives you the supervisors, the isolated rooms, and the self-healing behavior.
BEAM is the virtual machine that runs Erlang (and Elixir) programs. It is the actual engine underneath. Think of it as the foundation and plumbing of the hospital – the infrastructure that makes all the rooms, supervisors, and recovery mechanisms possible.
Elixir is a newer language (created in 2012) that runs on the same BEAM virtual machine. It has all of Erlang’s reliability but with a more modern, developer-friendly syntax. WorkingAgents is written in Elixir, which means it inherits 40 years of Erlang/OTP reliability.
Python is the most popular programming language in the world, used for most AI and machine learning projects. It is excellent for data science, prototyping, and building AI models. It was not designed for handling thousands of simultaneous operations reliably.
JavaScript (Node.js) is the language of the web. It runs most websites and many backend services. It is excellent for building web applications quickly. It was designed for browsers, not for mission-critical infrastructure that cannot go down.
The Five Things That Make It Different (And Why Python and JavaScript Cannot Do Them)
1. Everything Runs in Its Own Isolated Space
In most software, everything shares the same space. If one part of the program has a problem, it can corrupt other parts. A bug in the email feature can crash the payment feature. A slow database query can freeze the entire application.
In Erlang/OTP, every task runs in its own isolated “process” – like a room in the hospital. These are not heavy, expensive things. They are incredibly lightweight – you can have millions of them running at the same time on a single computer. Each one has its own memory, its own state, and its own lifecycle. They communicate by passing messages, like nurses passing charts through a window – never by reaching into each other’s space.
How Python does it: Python runs one thing at a time. Seriously. Python has something called the Global Interpreter Lock (GIL) – imagine a hospital with one hallway and a rule that only one person can walk through it at any moment. Everyone else waits. To do multiple things “simultaneously,” Python has to start entirely separate copies of itself (separate processes with separate operating system overhead), each using tens of megabytes of memory. Running 10,000 separate Python processes to handle 10,000 simultaneous agents would require enormous amounts of memory and CPU. Erlang handles the same workload with lightweight processes that each use about 2.5 kilobytes – roughly 10,000 times less memory per task.
How JavaScript does it: Node.js uses a single thread with an event loop – imagine one very fast doctor who runs between patients, doing a little work on each one before moving to the next. This works well for simple web requests. But if that one doctor gets stuck on a complicated procedure (a CPU-intensive guardrail check, a complex permission calculation), every other patient waits. There is no isolation. An uncaught error in one operation can crash the entire Node.js process, taking down every connected agent simultaneously.
What this means for you: If one AI agent’s guardrail check encounters a problem, it does not affect any other agent. The problem is contained. Every other operation continues normally. In Python or JavaScript, that same problem could freeze or crash the entire system.
2. Supervisors Watch Everything and Fix Problems Automatically
Every group of processes has a supervisor – a dedicated manager whose only job is watching for failures and responding to them. If a process crashes, the supervisor restarts it in a clean state. Automatically. In milliseconds. No human intervention required.
Supervisors are organized in trees. A supervisor at the top watches supervisors below it, who watch the actual working processes. If a low-level supervisor cannot fix a problem, it escalates to the next level up. If an entire branch of the tree has a systemic issue, the higher-level supervisor can restart the whole branch.
How Python does it: Python has no built-in supervision. If a Python process crashes, it stays crashed. Someone or something external has to notice and restart it – a monitoring tool like Supervisor or systemd, a Kubernetes container restart, or an engineer getting paged at 3 AM. The application itself has no ability to heal. Developers write try/except blocks around everything, which makes the code more complex and still does not handle unexpected failures gracefully.
How JavaScript does it: Node.js has no built-in supervision either. If the process crashes, it is down. Tools like PM2 or Forever can restart a crashed Node.js process, but they are external band-aids, not architectural features. They restart the entire application, not the specific component that failed. And during the restart, every connected user is disconnected.
What this means for you: The system heals itself. A temporary glitch in one component does not require a support call, a server restart, or an engineer waking up at 3 AM. The supervisor detects the problem and resolves it before anyone notices. Python and JavaScript systems require external monitoring and manual (or externally automated) recovery.
3. One Failure Does Not Cascade
In most software systems, failures cascade. A database connection times out, which causes a request handler to hang, which fills up the thread pool, which causes every new request to queue, which causes the entire application to become unresponsive. One problem becomes everyone’s problem.
In Erlang/OTP, failures are isolated by design. A crashed process cannot corrupt another process’s memory because they do not share memory. A slow process cannot block other processes because the scheduler gives everyone fair access to the CPU. A failure in the audit logging system does not affect the permission engine because they run in separate supervision trees.
How Python does it: Python processes share memory by default. A memory corruption bug, a segmentation fault in a C extension, or an out-of-memory condition in one part of the application can take down the entire process. When Python developers need isolation, they have to use multiprocessing (separate OS processes), which is expensive and complex to coordinate. Communication between separate processes requires serialization, shared memory managers, or message queues – all of which add complexity and failure points.
How JavaScript does it: Node.js runs everything in one process, one thread. A single unhandled promise rejection, an infinite loop, or a memory leak affects every connected user. The failure model is all-or-nothing: either the process is running and serving everyone, or it has crashed and serving no one. There is no middle ground where “the audit system is down but everything else works fine.”
What this means for you: Your governance infrastructure does not have single points of failure. One component having a bad day does not mean your entire AI agent fleet loses governance. In Python or JavaScript, one bad component can cascade into a total system outage.
4. Upgrades Happen Without Downtime
The BEAM virtual machine can run two versions of the same code simultaneously. The old version keeps running while the new version is loaded. Active operations complete on the old version and seamlessly transition to the new version.
This was designed for telephone switches that serve entire countries. You cannot take down the phone network to deploy an update. So the system was built to upgrade while running.
How Python does it: You stop the application, deploy the new code, and start it again. During that window – seconds to minutes depending on the application – the system is down. Every connected user is disconnected. Every in-flight operation is interrupted. To minimize this, Python teams use rolling deployments with load balancers – running multiple copies and updating them one at a time. This adds infrastructure complexity, costs more, and still disconnects some users during each rolling restart.
How JavaScript does it: Same story. Stop, deploy, restart. Node.js has no concept of hot code swapping. Rolling deployments behind load balancers are the standard approach, with the same tradeoffs: more infrastructure, more complexity, brief interruptions during each restart.
What this means for you: New guardrail rules, new compliance requirements, new tool integrations – deployed without disconnecting a single AI agent, without dropping a single tool call, without any interruption to your operations. Python and JavaScript systems require planned downtime windows or complex rolling deployment infrastructure to achieve what Erlang/OTP does natively.
5. It Scales by Adding More Rooms, Not Bigger Rooms
When most software needs to handle more load, you make the server bigger – more CPU, more memory. This is called “scaling up.” It works until it does not – there is always a ceiling.
Erlang/OTP scales differently. Because every task is an isolated process that communicates via messages, you can spread those processes across multiple computers. The code does not change. Message passing works the same way whether the recipient process is on the same machine or on a machine in another data center. You scale by adding more machines, not by making one machine bigger.
How Python does it: Python does not have built-in distribution. To run across multiple machines, you need external tools: Celery for task queues, Redis or RabbitMQ (which is itself built on Erlang) for message passing, Kubernetes for orchestration. Each tool adds operational complexity, failure points, and engineering overhead. The application code must be rewritten to work with these external systems. Scaling a Python application from one machine to a cluster is a significant engineering project.
How JavaScript does it: Node.js can run multiple processes on one machine using its cluster module, but distribution across machines requires external tools – the same Redis, RabbitMQ, Kubernetes stack that Python needs. The application must be redesigned for distributed operation. There is no built-in way for a Node.js process on Machine A to send a message to a Node.js process on Machine B.
What this means for you: As your AI agent deployment grows from 10 agents to 100 to 10,000, the governance infrastructure grows with it. No rewrite required. No new external tools. No architecture change. Python and JavaScript require adding significant infrastructure complexity to achieve what Erlang/OTP provides out of the box.
The Comparison at a Glance
| Capability | Erlang/Elixir | Python | JavaScript (Node.js) |
|---|---|---|---|
| Simultaneous operations | Millions of lightweight processes | Limited by GIL; multiprocessing is expensive | Single-threaded event loop |
| Isolation | Complete – processes share nothing | Shared memory by default | Everything in one process |
| Self-healing | Built-in supervision trees | No – requires external tools | No – requires external tools |
| Failure cascade | Impossible by design | Common – one crash can take down everything | Common – unhandled error crashes entire process |
| Upgrades without downtime | Native hot code swapping | Stop, deploy, restart | Stop, deploy, restart |
| Distribution across machines | Built into the language | Requires Celery, Redis, Kubernetes, etc. | Requires Redis, message queues, Kubernetes, etc. |
| Memory per concurrent task | ~2.5 KB | ~30-50 MB per OS process | Shared (single process) |
| Garbage collection pauses | Per-process, microseconds | Global, can pause entire application | Global, can cause latency spikes |
| 40-year track record in telecom/finance | Yes | No | No |
Why Not Just Use Python? Everyone Else Does.
Python is the right choice for many things. Most AI models are trained in Python. Most data science happens in Python. Most AI prototypes start in Python. It is the language of AI research.
But AI governance is not AI research. AI governance is infrastructure. It runs 24/7. It handles thousands of simultaneous operations. It must never go down, because a governance system that is offline means ungoverned agents running without guardrails, without audit trails, without permission checks.
Python was designed for scientists who want to analyze data. Erlang was designed for engineers who need systems that never stop running. Both are excellent at what they were designed for. They were designed for different things.
The analogy: you would not build an airplane engine out of the same material you use for a comfortable office chair. Both materials are good. They serve different purposes. Python is the office chair – comfortable, popular, perfect for most daily work. Erlang/OTP is the airplane engine – engineered for reliability under extreme conditions, because failure is not an option.
Why Not JavaScript? It Is Everywhere.
JavaScript runs every website. It is the most widely deployed programming language in the world. Node.js made it possible to use JavaScript on servers, not just in browsers.
But Node.js was designed for web servers that handle HTTP requests – short-lived operations where a user sends a request and gets a response. AI governance is a different workload: long-lived connections (agents stay connected for hours or days), real-time message routing (guardrail checks on every tool call), and thousands of simultaneous stateful operations (each agent has its own permission set, its own audit trail, its own guardrail configuration).
Node.js handles this the way a very fast waiter handles a restaurant: running between tables, taking orders, delivering food, clearing plates – one thing at a time, very quickly. It works until the restaurant gets full and one table orders a complicated dish that takes the waiter 10 minutes to prepare. Every other table waits.
Erlang/OTP handles this the way a hospital handles patients: every patient gets their own room, their own nurse, their own doctor. One patient’s complicated surgery does not make another patient wait for a blood pressure check. The hospital does not have one very fast doctor – it has thousands of rooms operating independently.
Why This Matters for AI Governance
AI governance is a real-time, high-concurrency, failure-sensitive problem:
- Real-time because guardrail checks must happen on every tool call, every time, without adding noticeable delay.
- High-concurrency because hundreds or thousands of agents may be making tool calls simultaneously.
- Failure-sensitive because a governance system that crashes is worse than no governance at all – it gives false confidence that guardrails are in place when they are not.
Erlang/OTP was designed for exactly this class of problem. Telephone switches are real-time (calls connect in milliseconds), high-concurrency (millions of simultaneous calls), and failure-sensitive (dropped calls are unacceptable). The same properties that make Erlang/OTP the foundation of global telecom infrastructure make it the right foundation for AI agent governance.
Python and JavaScript were not designed for this class of problem. They can be made to work – with enough external tools, enough infrastructure, enough engineering effort, and enough operational overhead. But “can be made to work” is not the same as “designed to work.” When your governance infrastructure is the thing standing between your AI agents and your sensitive data, you want “designed to work.”
The Track Record
This is not theoretical. Erlang/OTP has a 40-year production track record in the most demanding environments on the planet:
| System | What It Does | Scale |
|---|---|---|
| Messaging | 3 billion users, 140 billion messages/day | |
| Discord | Real-time communication | 11 million concurrent users |
| Cisco | Network infrastructure | 90% of internet traffic |
| Ericsson | Telecom switches | 99.9999999% uptime measured |
| RabbitMQ | Message routing | World’s most deployed message broker |
| Klarna | Payment processing | 150 million consumers, millions of transactions/day |
| Goldman Sachs | Financial trading | Microsecond-latency trade execution |
| Notifications | 14,000 notifications/second, $2M/year saved vs Java | |
| Bleacher Report | Sports media | 1.5 billion page views/month on 5 servers |
| Bet365 | Real-time betting | 2 million simultaneous users |
No Python or JavaScript system appears on this list. Not because Python and JavaScript are bad languages – they are excellent at what they do. But the systems on this list require properties that Python and JavaScript were not built to provide: millions of isolated concurrent operations, automatic self-healing, zero-downtime upgrades, and built-in distribution.
WorkingAgents is built on the same foundation. When we say the governance infrastructure is reliable, scalable, and self-healing, we are not making a promise about future capabilities. We are describing the proven behavior of a platform that has been handling the world’s most critical systems for four decades.
The Simple Version
If someone asks you “why isn’t WorkingAgents built in Python or JavaScript like everything else?”, here is the answer:
Python is designed for data science and AI research. JavaScript is designed for websites. Neither was designed for infrastructure that handles thousands of simultaneous operations, heals itself when something fails, upgrades without downtime, and scales across machines without external tools. Erlang/OTP was designed for exactly that – 40 years ago, for telephone switches that serve entire countries. WhatsApp, Discord, Cisco, and Ericsson chose it for the same reason we did: when the system cannot go down, you build it on a foundation that was engineered to never go down.