OpenAI just chose Elixir to orchestrate AI agents. So I ran their code through mine

March 5, 2026  —  elixirbeamgiuliaopenaisymphonyai-agents  — 4 min read

Yesterday, OpenAI open-sourced Symphony — an autonomous agent orchestration framework. It monitors Linear issues in real time, dispatches Codex agents, handles CI testing, code review, and merges PRs. Without humans supervising every step.

They built it in Elixir/OTP.

Their reasoning, straight from the README: BEAM is exceptional at supervising long-running processes, OTP gives you fault tolerance for free, and hot code reloading lets you update a running system without killing active agents mid-task.

The Elixir community has known this for years. It’s just that now it has an OpenAI logo on it.

I’ve been building the same thesis — from a different angle

Meet Giulia

Giulia is an Elixir code intelligence daemon I’ve been developing as infrastructure for AI coding agents — exactly the kind of agents Symphony is designed to orchestrate.

AST-level analysis. ETS-based knowledge graphs. Sub-millisecond query times. 44+ REST and MCP endpoints. The idea is simple: before an agent touches a codebase, it should understand it — dependency graphs, module boundaries, blast radius of any change, complexity hotspots, dead code, struct coupling, semantic duplicates.

Giulia gives agents that understanding.

So when Symphony dropped yesterday, I did the obvious thing.

I ran Symphony through Giulia

What the analysis found

Symphony’s Elixir implementation: 34 files, 37 modules, 592 functions. Compact, focused, ships fast. Exactly what you’d expect from an engineering preview.

Giulia’s knowledge graph: 628 vertices, 668 edges, 153 components.

Here’s the health distribution:

Health distribution by zone

The three RED modules — Config, Orchestrator, StatusDashboard — are the structural core of the entire system. And none of them have tests.

The God Module problem

God module analysis

StatusDashboard — the observability component — is ironically the least maintainable part of the system. 117 functions. Complexity score of 331. It handles terminal rendering, TPS calculation, Codex message humanization, and snapshot management. That’s four distinct responsibilities in one module.

Orchestrator is carrying polling, dispatching, retry logic, token accounting, issue reconciliation, and rate limiting — all inside a single GenServer. 83 of its 95 functions are private.

The blast radius problem

Config has a fan-in of 10 — ten modules depend directly on it. Any change to its API ripples through 15 modules total, which is 40% of the entire codebase.

Giulia calls this the blast radius. It’s one of the most important metrics when you’re letting agents modify code autonomously. An agent that doesn’t know the blast radius of a change is an agent that’s going to break things.

Two dependency cycles

HttpServer → Orchestrator → StatusDashboard → HttpServer

Triangular cycle. Startup ordering risk. Potential initialization deadlock.

Workflow ↔ WorkflowStore

Bilateral. Lower severity — common GenServer + accessor pattern — but worth watching.

High struct coupling across consumers

Every shared struct in Symphony is directly pattern-matched by multiple modules. This is idiomatic Elixir — the compiler enforces struct shape at compile time — but it means field-level changes propagate widely. At 37 modules this is manageable; at scale it’s worth watching.

What they did well

This isn’t a hit piece. Symphony is an engineering preview and OpenAI explicitly says so — they literally invite you to “implement your own hardened version based on SPEC.md.”

Giulia just quantified exactly what hardening means in practice.

What’s solid:

  • Zero dead code. Clean, intentional codebase.
  • Config is fully spec’d — 31/31 public functions have typespecs. The highest-risk module is also the most documented.
  • Clean behaviour abstraction for the Tracker — Linear.Adapter and Tracker.Memory make the issue tracker swappable.
  • Behaviour integrity is consistent — no broken contracts anywhere.
  • Workflow-driven configuration via WORKFLOW.md is elegant. Runtime flexibility without recompilation.

Why this matters beyond Symphony

Symphony is OpenAI’s bet that BEAM/OTP is the right runtime for agentic AI systems.

I agree. Completely.

But orchestration is only half the problem. The other half is giving agents the structural awareness to operate safely inside a codebase — to know what’s coupled, what’s fragile, what’s the blast radius of every function they’re about to rewrite.

That’s what Giulia does.

The timing is not a coincidence. It’s a convergence.

What’s next

The full Giulia analysis report for openai/symphony is attached.

Giulia is currently in active development. If you’re building agent infrastructure on Elixir — or if you’re OpenAI and you just open-sourced an Elixir orchestrator and want to know what AST-level code intelligence looks like as a first-class citizen in your agent pipeline — let’s talk.

The Elixir ecosystem is about to become the backbone of autonomous agent infrastructure. The foundation is already here.


Giulia v0.1.0.114 (Build 114) — AST analysis + Knowledge Graph (628 vertices, 668 edges)