Livebook for Intelligence Experiments
Engineering

Livebook for Intelligence Experiments: From Notebook to Production in One Step

A Livebook session connected to your running application is the fastest feedback loop Elixir has ever had. Here's how Prismatic uses it for ad-hoc DD queries, OSINT exploration, and model calibration without losing rigor.

Apr 09, 2026 Β· 7 min read Β· TomΓ‘Ε‘ Korcak (korczis)

Intelligence work has a bad feedback loop. You have a hypothesis, you want to run a query across three adapters, plot the results, and see if the pattern holds. Doing that in an IDE is slow; doing it in iex loses history; doing it in a one-off script loses context. Livebook is exactly the tool for this shape β€” and when it is connected to a running node, the loop collapses to β€œtype, shift-enter, see.”

#Attaching to a live node

# In the Livebook runtime config:
# Attached node: prismatic@localhost
# Cookie: <whatever your dev.exs says>

# Cell:
{:ok, case} = Prismatic.DD.get_case("case_01HX...")
Prismatic.DD.entities_for(case)
|> Enum.group_by(& &1.type)
|> Enum.map(fn {k, v} -> {k, length(v)} end)

The cell runs inside the Prismatic BEAM node. No mocking. No fixtures. The real data, the real GenServers, the real ETS tables. Livebook becomes a live window into the system.

#Rules for connected notebooks

Two rules keep this from becoming a production hazard:

  1. Read-only by default. Writes from a notebook should be explicit, gated, and logged. No Repo.delete_all anywhere, ever. Treat the notebook like a read replica unless you consciously opt out.
  2. Notebooks are committed. Save .livemd files into notebooks/ in the repo. A notebook that works once and then is lost is not reproducible, which defeats the point.

#From notebook to test

The best workflow: do an exploration in a notebook, find the query you want, promote it to a function in lib/, and write a test. The notebook becomes a scratch pad; the function becomes permanent. The notebook can stay in the repo as a worked example for the next person to face the same question.

# In the notebook, after exploration:
defmodule PrismaticDD.Queries.Recent do
  def active_cases_by_analyst(since) do
    from(c in Case,
      where: c.inserted_at >= ^since and c.state == "active",
      preload: [:analyst])
    |> Repo.all()
  end
end

Paste that into lib/, write a test, ship.

#When to reach for a notebook vs iex

  • iex β€” you need to poke at one value, the output is ephemeral, you will throw away the session.
  • Livebook β€” you are iterating on a query, you want history, you want a chart, you want to share the exploration with a teammate.

iex is still irreplaceable for β€œis this GenServer alive?” and β€œwhat does this module export?” β€” but the minute you want to see the output in a table or a plot, switch.

#Where to go next

The fastest feedback loop Elixir ever had. Use it.

Browse all β†’