<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged elixir</title>
<link>https://coderlegion.com/tag/elixir</link>
<description>Powered by Question2Answer</description>
<item>
<title>I built a Pix library for Elixir (and one cent proved it works)</title>
<link>https://coderlegion.com/28983/i-built-a-pix-library-for-elixir-and-one-cent-proved-it-works</link>
<description>&lt;p&gt;Over the last few months I became a bit of a compulsive open source contributor. Translating Linux kernel documentation into Portuguese, a merged PR in &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/uutils/coreutils&quot;&gt;uutils/coreutils&lt;/a&gt;, a few fixes in Elixir libraries I had used before. Always the same routine: find a problem in someone else's project, understand it, fix it, wait for review.&lt;/p&gt;
&lt;p&gt;Then a different itch showed up: instead of fixing other people's libraries, build my own.&lt;/p&gt;
&lt;p&gt;This post is about that. How I built &lt;code&gt;pix_brcode&lt;/code&gt;, a Pix library for Elixir, over a weekend, tested it with real money (R$ 0.01, don't judge me) and published it on Hex. And about the bug that only showed up once a real bank got involved.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/p85i9j3exahlfhcidnfb.png&quot; alt=&quot;Github print&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;what-is-pix-and-why-a-library-for-it&quot;&gt;What is Pix, and why a library for it&lt;/h3&gt;
&lt;p&gt;If you're not from Brazil, you've probably never heard of Pix. It's the instant payment system created by Brazil's Central Bank in 2020, and it took over the country: it's free for individuals, settles in seconds, works 24/7, and today it's how Brazilians pay for everything from coffee to rent.&lt;/p&gt;
&lt;p&gt;Most Pix payments start with a QR code, or with its text version, the &lt;em&gt;&quot;copia e cola&quot;&lt;/em&gt; (copy and paste) code: a long string starting with &lt;code&gt;000201&lt;/code&gt; that you paste into your bank app. Everyone uses it every day, and almost nobody knows what's inside it.&lt;/p&gt;
&lt;p&gt;In the JavaScript world this is a solved problem: &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.npmjs.com/package/pix-utils&quot;&gt;&lt;code&gt;pix-utils&lt;/code&gt;&lt;/a&gt; on npm generates and parses Pix codes and gets over 60k downloads a month. I went looking for the equivalent on &lt;a rel=&quot;nofollow&quot; href=&quot;https://hex.pm&quot;&gt;Hex&lt;/a&gt;, Elixir's package manager, and couldn't find a maintained one.&lt;/p&gt;
&lt;p&gt;So I put the two things together: a big, mature library to use as a reference, and an empty spot in the ecosystem I wanted to fill. I decided to build a &quot;pix-utils&quot; for Hex, or, as I preferred to call it, &lt;code&gt;pix_brcode&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;what-s-inside-a-pix-code&quot;&gt;What's inside a Pix code&lt;/h3&gt;
&lt;p&gt;That string is a &lt;strong&gt;BR Code&lt;/strong&gt;: an international payment QR code standard (EMVCo's QR Code Specification, Merchant-Presented Mode) with Pix-specific fields.&lt;/p&gt;
&lt;p&gt;The structure is simpler than it looks. Everything is &lt;strong&gt;TLV&lt;/strong&gt;: a 2-digit ID, a 2-digit length, then the value.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-plaintext&quot;&gt;00 02 01                       → payload format: &quot;01&quot;
26 58 0014br.gov.bcb.pix0136…  → Pix account (with subfields inside!)
52 04 0000                     → merchant category
53 03 986                      → currency: Brazilian real
54 04 0.01                     → amount
58 02 BR                       → country
59 04 Igor                     → receiver name
60 09 Sao Paulo                → city
62 07 0503***                  → txid (transaction id)
63 04 F6CE                     → CRC16
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Look at field &lt;code&gt;26&lt;/code&gt;: its value is &lt;strong&gt;another TLV&lt;/strong&gt;, holding the Pix identifier (&lt;code&gt;br.gov.bcb.pix&lt;/code&gt;) and the key. TLV inside TLV.&lt;/p&gt;
&lt;p&gt;And the last field, &lt;code&gt;63&lt;/code&gt;, is a &lt;strong&gt;CRC16&lt;/strong&gt;: a checksum over everything before it. If someone copies the code missing one character, the CRC doesn't match and the bank app rejects it.&lt;/p&gt;
&lt;p&gt;(Important side note: a CRC is not security. It catches accidental errors, not fraud. Anyone can recompute it.)&lt;/p&gt;
&lt;h3 id=&quot;the-decisions-that-made-the-weekend-worth-it&quot;&gt;The decisions that made the weekend worth it&lt;/h3&gt;
&lt;h4 id=&quot;zero-dependencies&quot;&gt;Zero dependencies&lt;/h4&gt;
&lt;p&gt;Installing &lt;code&gt;pix_brcode&lt;/code&gt; pulls in nothing else. That had a cost: Erlang only ships CRC32, so the CRC16 was written by hand in about 20 lines, using Elixir's binary pattern matching:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-elixir&quot;&gt;defp crc(&amp;lt;&amp;lt;byte, rest::binary&amp;gt;&amp;gt;, acc) do
  acc = Enum.reduce(1..8, bxor(acc, byte &amp;lt;&amp;lt;&amp;lt; 8), fn _, acc -&amp;gt; shift(acc &amp;lt;&amp;lt;&amp;lt; 1) end)
  crc(rest, acc)
end

defp crc(&amp;lt;&amp;lt;&amp;gt;&amp;gt;, acc), do: acc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Adding a dependency for 20 lines would be trading a small problem for a permanent one.&lt;/p&gt;
&lt;h4 id=&quot;money-is-never-a-float&quot;&gt;Money is never a float&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;pix-utils&lt;/code&gt; takes the amount as a JavaScript &lt;code&gt;number&lt;/code&gt;, which is a float. And floats with money are how you end up seeing &lt;code&gt;0.1 + 0.2 = 0.30000000000000004&lt;/code&gt; on someone's bill.&lt;/p&gt;
&lt;p&gt;In &lt;code&gt;pix_brcode&lt;/code&gt;, the amount is either an &lt;strong&gt;integer in cents&lt;/strong&gt; (&lt;code&gt;1050&lt;/code&gt; becomes &lt;code&gt;&quot;10.50&quot;&lt;/code&gt;) or an exact string (&lt;code&gt;&quot;10.50&quot;&lt;/code&gt;). The conversion is done on text, with no division at all.&lt;/p&gt;
&lt;h4 id=&quot;strict-in-what-you-send-liberal-in-what-you-accept&quot;&gt;Strict in what you send, liberal in what you accept&lt;/h4&gt;
&lt;p&gt;When generating, the library is strict: a name longer than 25 characters is an error instead of being silently truncated (imagine the payer's bank app showing the wrong name). When parsing, it accepts whitespace and line breaks around the code, because real copy-and-paste comes dirty from WhatsApp.&lt;/p&gt;
&lt;p&gt;That principle has a name, Postel's law. And it was about to be tested sooner than I expected.&lt;/p&gt;
&lt;h3 id=&quot;the-moment-of-truth-real-money&quot;&gt;The moment of truth: real money&lt;/h3&gt;
&lt;p&gt;Tests passing, Credo clean, docs generated. Only one test left that really matters: &lt;strong&gt;a bank app accepting the code.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The first try failed in all three banks I tested. Itaú, Nubank and Mercado Pago: &quot;Invalid QR Code&quot;.&lt;/p&gt;
&lt;p&gt;For a minute I thought the weekend was wasted. It wasn't: I had used a made-up Pix key. When you paste a static Pix code, the app looks the key up in the Central Bank's directory. Unknown key, rejected code. The test was wrong, not the library.&lt;/p&gt;
&lt;p&gt;I generated it again with my real Itaú random key and an amount of one cent:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-elixir&quot;&gt;PixBrcode.encode(%{key: &quot;my-real-key&quot;, amount: 1,
                   merchant_name: &quot;Igor&quot;, merchant_city: &quot;Sao Paulo&quot;})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pasted it into Nubank. My name showed up, R$ 0.01. Paid. It landed in my Itaú account instantly.&lt;/p&gt;
&lt;p&gt;The best-invested cent of my life.&lt;/p&gt;
&lt;h3 id=&quot;the-bug-no-test-caught&quot;&gt;The bug no test caught&lt;/h3&gt;
&lt;p&gt;The reverse path was still missing: generate a code &lt;strong&gt;in the bank app&lt;/strong&gt; and parse it with the library. Pix &amp;gt; Receive on Nubank, copy, paste into the terminal:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-elixir&quot;&gt;iex&amp;gt; PixBrcode.decode(&quot;00020126580014BR.GOV.BCB.PIX0136…&quot;)
{:error, :invalid_gui}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;BR.GOV.BCB.PIX&lt;/code&gt;. In uppercase.&lt;/p&gt;
&lt;p&gt;The &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bcb.gov.br/estabilidadefinanceira/pix&quot;&gt;Central Bank's manual&lt;/a&gt; writes &lt;code&gt;br.gov.bcb.pix&lt;/code&gt; in lowercase, and the library compared the exact text. Nubank sends it uppercase. So does Itaú. All my tests passed because they all followed the manual to the letter, and the banks don't.&lt;/p&gt;
&lt;p&gt;The fix was one line: compare case-insensitively when parsing, and keep generating lowercase, as the manual says. Postel again: strict in what you send, liberal in what you accept.&lt;/p&gt;
&lt;p&gt;The real codes showed other differences too: Nubank includes the postal code (field &lt;code&gt;61&lt;/code&gt;) and puts part of the account holder's tax ID in the receiver name; Itaú doesn't. The library's tests now use payloads with the same layout as the real ones, but with fake data. (Your partial tax ID in a public repo is not a great idea, and I learned that before making the mistake.)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The lesson:&lt;/strong&gt; the spec is the minimum. Real systems have variations that only show up with real data.&lt;/p&gt;
&lt;h3 id=&quot;a-second-opinion-before-publishing&quot;&gt;A second opinion before publishing&lt;/h3&gt;
&lt;p&gt;Before pushing to Hex, I had an AI agent do an independent code review: a fresh session, with no context from the development, reading everything from scratch. Nothing blocked the release, but it came back with four good findings:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the amount field didn't enforce the spec's 13-character limit;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;decode(nil)&lt;/code&gt; raised an exception, while the README promised always &lt;code&gt;{:ok, _}&lt;/code&gt; or &lt;code&gt;{:error, _}&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;text with invalid bytes also crashed the library;&lt;/li&gt;
&lt;li&gt;emoji in the name got through, and since each emoji takes several bytes, the length declared in the TLV was wrong for other parsers.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All four were fixed before v0.1.0. Name, city and description must now be ASCII after removing accents (&lt;code&gt;São João&lt;/code&gt; becomes &lt;code&gt;Sao Joao&lt;/code&gt;, and ☕ is an error).&lt;/p&gt;
&lt;h3 id=&quot;what-s-next&quot;&gt;What's next&lt;/h3&gt;
&lt;p&gt;v0.1.0 generates and parses static and dynamic Pix codes, validates keys (tax IDs, phone, e-mail, random key) and runs CI on three Elixir versions. Next on the list: typespecs, more tolerant key parsing and a CHANGELOG. And there's another idea in the queue: Brazilian &lt;em&gt;boleto&lt;/em&gt; bank slips, which also have no package on Hex.&lt;/p&gt;
&lt;p&gt;If you work with Elixir and Pix, try the library and tell me what breaks. Issues and PRs are very welcome:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hex: &lt;a rel=&quot;nofollow&quot; href=&quot;https://hex.pm/packages/pix_brcode&quot;&gt;hex.pm/packages/pix_brcode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Docs: &lt;a rel=&quot;nofollow&quot; href=&quot;https://hexdocs.pm/pix_brcode&quot;&gt;hexdocs.pm/pix_brcode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/igorgbr/pix_brcode&quot;&gt;github.com/igorgbr/pix_brcode&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Fixing other people's libraries taught me to read code. Building my own taught me that the manual is only the start of the conversation.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This post was originally published in Portuguese on &lt;a rel=&quot;nofollow&quot; href=&quot;https://coisadedevacademy.com.br/biblioteca-pix-elixir-pix-brcode/&quot;&gt;Coisa de Dev&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/28983/i-built-a-pix-library-for-elixir-and-one-cent-proved-it-works</guid>
<pubDate>Tue, 29 Sep 2026 00:34:58 +0000</pubDate>
</item>
<item>
<title>Multi-Agent Metacognition and Causal Consensus via PON</title>
<link>https://coderlegion.com/26845/multi-agent-metacognition-and-causal-consensus-via-pon</link>
<description>&lt;h2 id=&quot;multi-agent-metacognition-and-causal-consensus-via-pon&quot;&gt;Multi-Agent Metacognition and Causal Consensus via PON&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Keywords:&lt;/strong&gt; RAG, AI, architecture, backend, multi-agent systems, PON, causal consensus, metacognition&lt;/p&gt;
&lt;h3 id=&quot;abstract&quot;&gt;Abstract&lt;/h3&gt;
&lt;p&gt;As AI systems evolve from isolated single agents into multi-agent ecosystems, traditional architectures face a critical bottleneck: dependence on centralized orchestrators such as rigid state graphs, sequential pipelines, or master routing nodes.&lt;/p&gt;
&lt;p&gt;In a centralized orchestrator, every agent must report to a coordinator that evaluates global state, polls subprocesses, and decides the next API call. The result is predictable:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Latency cascades:&lt;/strong&gt; final response time becomes the linear sum of all agent executions plus the orchestrator’s serialization overhead.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;State contention:&lt;/strong&gt; the central node becomes a memory and CPU bottleneck.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Operational rigidity:&lt;/strong&gt; failure of a master node interrupts the entire reasoning chain.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In nature, complex systems — from insect swarms to cortical neural networks — do not rely on a central controlling node. Consensus emerges from reactive interaction among autonomous parts that notify their immediate neighbors of state changes.&lt;/p&gt;
&lt;p&gt;To build scalable multi-agent ecosystems, we must move from procedural orchestration to &lt;strong&gt;Causal Consensus&lt;/strong&gt; based on the &lt;strong&gt;Notification-Oriented Paradigm (PON)&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;1-theory-of-mind-in-distributed-agents&quot;&gt;1. Theory of Mind in Distributed Agents&lt;/h3&gt;
&lt;p&gt;Theory of Mind is the cognitive ability to infer and represent the mental states, intentions, and knowledge of other individuals. In a distributed AI system, this means an agent should understand the context and capabilities of its peers without having to send explicit query messages such as “Are you free?” or “What do you know about X?”&lt;/p&gt;
&lt;p&gt;In the PON kernel, each agent’s state is mapped directly into &lt;strong&gt;global/replicated state attributes&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;┌────────────────────────────────────────────────────────────────────────┐
│               PON State Registry (In-Memory Attributes)               │
│                                                                        │
│  [Research_Agent]  ──► Status: Busy   │ Load: 85% │ Specialty: RAG     │
│  [Validator_Agent] ──► Status: Free   │ Load: 10% │ Specialty: Bacen   │
│  [Synthesis_Agent] ──► Status: Idle   │ Load: 0%  │ Specialty: LLM     │
└───────────────────────────────────┬────────────────────────────────────┘
                                    │
                         (Notification Propagation)
                                    │
                                    ▼
┌────────────────────────────────────────────────────────────────────────┐
│                        Direct Causal Notification                      │
│  Research_Agent updates its state ──► Notifies ONLY those that depend  │
│  on 'Status' and 'Specialty' without lookup requests (Zero Polling).   │
└────────────────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Instead of sending a prompt to query Agent B’s availability, Agent A reads the notified in-memory attribute at runtime with &lt;strong&gt;O(1)&lt;/strong&gt; complexity. Theory of Mind stops being a heavy message exchange between LLMs and becomes a matrix of reactively notified states.&lt;/p&gt;
&lt;h3 id=&quot;2-causal-consensus-and-latency-negotiation-without-locks&quot;&gt;2. Causal Consensus and Latency Negotiation Without Locks&lt;/h3&gt;
&lt;p&gt;When multiple autonomous agents work on the same problem — for example, a vector RAG agent, a graph-search agent, and a regulatory validation agent — they often diverge or compete for execution time.&lt;/p&gt;
&lt;p&gt;In the traditional model, synchronization locks or synchronous consensus algorithms such as adapted Paxos/Raft are used. These block threads until all participants respond.&lt;/p&gt;
&lt;p&gt;With PON, consensus is strictly &lt;strong&gt;causal and reactive&lt;/strong&gt;.&lt;/p&gt;
&lt;h4 id=&quot;a-consensus-rule-networks-rule-nets-&quot;&gt;A. Consensus Rule Networks (Rule-Nets)&lt;/h4&gt;
&lt;p&gt;Convergence rules live inside the kernel itself. When the &lt;code&gt;RAG_Agent&lt;/code&gt; changes the &lt;code&gt;Partial_Response_V1&lt;/code&gt; attribute, the consensus rule node is notified. If the rule requires N confirmations or a confidence threshold ≥ 0.85, the node evaluates the condition instantly:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Consensus_Rule:
IF (RAG_Score &amp;gt;= 0.85 AND Regulatory_Status == :approved)
THEN Trigger(Synthesis_Agent)
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;b-dynamic-latency-negotiation-window-shrinking-&quot;&gt;B. Dynamic Latency Negotiation (Window Shrinking)&lt;/h4&gt;
&lt;p&gt;If the Graph Search Agent realizes it will take 800 ms to complete its traversal, it updates its &lt;code&gt;Estimated_Latency&lt;/code&gt; attribute.&lt;/p&gt;
&lt;p&gt;This change instantly notifies the consensus rule node, which adaptively shrinks the waiting window and forces the system to decide with the evidence available at that moment, eliminating timeout overruns.&lt;/p&gt;
&lt;h3 id=&quot;3-reactive-conflict-resolution-without-blocking-loops&quot;&gt;3. Reactive Conflict Resolution Without Blocking Loops&lt;/h3&gt;
&lt;p&gt;In scenarios where two agents generate contradictory hypotheses — for example, Agent A suggests “Approve Credit” while Agent B suggests “Reject Credit” — resolution occurs through &lt;strong&gt;causal notification propagation&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;┌──────────────────────────────┐            ┌──────────────────────────────┐
│ Agent A: Hypothesis (Approve) │            │ Agent B: Hypothesis (Reject) │
└──────────────┬───────────────┘            └──────────────┬───────────────┘
               │                                           │
         (Updates State)                             (Updates State)
               │                                           │
               └─────────────────────┬─────────────────────┘
                                     │
                                     ▼
                      ┌──────────────────────────────┐
                      │   Conflict Node (Rule-Net)   │
                      │   - Evaluates DIVERGENCE     │
                      └──────────────┬───────────────┘
                                     │
                     (Notifies Metacognitive Subsystem)
                                     │
                                     ▼
                      ┌──────────────────────────────┐
                      │    Arbitration by Reasoning  │
                      │      System 2 (Slow Path)    │
                      └──────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The presence of contradictory values in the attributes triggers the Conflict Rule-Net.&lt;/p&gt;
&lt;p&gt;This rule does not trap agents in &lt;code&gt;while(true)&lt;/code&gt; loops; it generates an arbitration notification. The notification escalates the decision asynchronously to &lt;strong&gt;System 2 (Slow Path)&lt;/strong&gt;, while edge agents remain free to process other events from the queue.&lt;/p&gt;
&lt;h3 id=&quot;4-comparative-table-centralized-multi-agent-vs-causal-consensus-via-pon&quot;&gt;4. Comparative Table: Centralized Multi-Agent vs. Causal Consensus via PON&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Dimension &lt;/th&gt;&lt;th&gt;Centralized Orchestration (Graphs/Master) &lt;/th&gt;&lt;th&gt;Causal Consensus via PON&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Architecture &lt;/td&gt;&lt;td&gt;Hierarchical / master routing node &lt;/td&gt;&lt;td&gt;Distributed / notification-based&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Theory of Mind &lt;/td&gt;&lt;td&gt;Prompt/message exchange between nodes &lt;/td&gt;&lt;td&gt;Shared state attributes in O(1)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Conflict Resolution &lt;/td&gt;&lt;td&gt;Blocks the pipeline until resolved &lt;/td&gt;&lt;td&gt;Reactive: triggers asynchronous arbitration node&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Adding Agents &lt;/td&gt;&lt;td&gt;Requires updating orchestrator logic &lt;/td&gt;&lt;td&gt;Agent simply subscribes to notifications of interest&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;CPU/Memory Bottleneck &lt;/td&gt;&lt;td&gt;High at the coordinator node &lt;/td&gt;&lt;td&gt;Distributed via atomic O(k) complexity&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Latency &lt;/td&gt;&lt;td&gt;Sum of agent execution + serialization overhead &lt;/td&gt;&lt;td&gt;Event-driven, parallel, no central serialization&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&quot;5-conclusion-emergence-over-control&quot;&gt;5. Conclusion: Emergence over Control&lt;/h3&gt;
&lt;p&gt;Trying to control complex AI networks through rigid centralized orchestrators repeats the mistakes of 1990s distributed computing.&lt;/p&gt;
&lt;p&gt;True multi-agent metacognition requires an infrastructure where communication is as cheap as a state change itself. By integrating the &lt;strong&gt;Notification-Oriented Paradigm (PON)&lt;/strong&gt; as the communication backbone between autonomous agents, we eliminate orchestration overhead and allow emergent consensus to happen at the speed of memory.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/26845/multi-agent-metacognition-and-causal-consensus-via-pon</guid>
<pubDate>Fri, 11 Sep 2026 13:20:25 +0000</pubDate>
</item>
<item>
<title>Getting Started with Elixir: Understanding Erlang, BEAM, and Your First Mix Project</title>
<link>https://coderlegion.com/10308/getting-started-with-elixir-understanding-erlang-beam-and-your-first-mix-project</link>
<description>&lt;h3 id=&quot;introduction&quot;&gt;Introduction&lt;/h3&gt;
&lt;p&gt;In the previous article, we covered how to set up the development environment to start working with Elixir.&lt;br&gt;
Now it’s time to talk about the language itself and write our first real code.&lt;/p&gt;
&lt;p&gt;If you are coming from languages like JavaScript, Ruby, or Python, some concepts may feel unfamiliar at first — and that’s totally normal.&lt;/p&gt;
&lt;p&gt;Let’s start by understanding why we had to install both &lt;strong&gt;Elixir and Erlang&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;elixir-vs-erlang&quot;&gt;Elixir vs Erlang&lt;/h3&gt;
&lt;p&gt;Erlang is a programming language created decades ago to solve problems related to &lt;strong&gt;telecommunication systems&lt;/strong&gt;, such as reliability, concurrency, and fault tolerance.&lt;/p&gt;
&lt;p&gt;It is extremely powerful, but its syntax is considered quite complex for many developers.&lt;/p&gt;
&lt;p&gt;This is where Elixir comes in.&lt;/p&gt;
&lt;p&gt;Elixir provides a &lt;strong&gt;modern and friendly syntax&lt;/strong&gt;, while still running on top of the same runtime as Erlang.&lt;br&gt;
In practice, your Elixir code is compiled to Erlang bytecode and executed by the same virtual machine.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;what-is-beam-&quot;&gt;What is BEAM?&lt;/h3&gt;
&lt;p&gt;BEAM stands for &lt;strong&gt;Bogdan/Björn’s Erlang Abstract Machine&lt;/strong&gt;, named after its original creators.&lt;/p&gt;
&lt;p&gt;It is the virtual machine responsible for running Erlang and Elixir code, similar to how the JVM runs Java and Kotlin.&lt;/p&gt;
&lt;p&gt;BEAM is famous for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lightweight processes  &lt;/li&gt;
&lt;li&gt;Massive concurrency  &lt;/li&gt;
&lt;li&gt;Fault-tolerant design  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is one of the main reasons Elixir is used in systems that require high availability.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;creating-your-first-project-with-mix&quot;&gt;Creating Your First Project with Mix&lt;/h3&gt;
&lt;p&gt;The best way to learn a programming language is by building something.&lt;/p&gt;
&lt;p&gt;Reading documentation and watching tutorials helps, but real learning happens when you actually write code.&lt;/p&gt;
&lt;p&gt;In Elixir, we use &lt;strong&gt;Mix&lt;/strong&gt;, the built-in build tool and project manager.&lt;/p&gt;
&lt;p&gt;Mix is responsible for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Creating projects  &lt;/li&gt;
&lt;li&gt;Compiling code  &lt;/li&gt;
&lt;li&gt;Managing dependencies  &lt;/li&gt;
&lt;li&gt;Running tasks and tests  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let’s create a new project.&lt;/p&gt;
&lt;p&gt;In your terminal, run:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;mix new basics
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You should see an output similar to:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;* creating README.md
* creating .formatter.exs
* creating .gitignore
* creating mix.exs
* creating lib
* creating lib/basics.ex
* creating test
* creating test/test_helper.exs
* creating test/basics_test.exs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now enter the project directory:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cd basics
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3 id=&quot;modules-and-functions&quot;&gt;Modules and Functions&lt;/h3&gt;
&lt;p&gt;Inside the &lt;code&gt;lib&lt;/code&gt; directory, you will find the file &lt;code&gt;basics.ex&lt;/code&gt; with the following content:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-elixir&quot;&gt;defmodule Basics do
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In Elixir, almost all code lives inside &lt;strong&gt;modules&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;A module is simply a &lt;strong&gt;collection of functions&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Let’s add our first function:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-elixir&quot;&gt;defmodule Basics do
  def create_list do
    [1, 2, 3, &quot;little indians&quot;]
  end
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We use &lt;code&gt;def&lt;/code&gt; to define a function inside the &lt;code&gt;Basics&lt;/code&gt; module.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;running-the-project-with-iex&quot;&gt;Running the Project with IEx&lt;/h3&gt;
&lt;p&gt;To run and test our code, we use &lt;strong&gt;IEx (Interactive Elixir Shell)&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;It works like Python’s REPL or Ruby’s IRB, allowing you to run Elixir code interactively.&lt;/p&gt;
&lt;p&gt;From the project directory, run:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;iex -S mix
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now test the function:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-elixir&quot;&gt;Basics.create_list()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You should get:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-elixir&quot;&gt;[1, 2, 3, &quot;little indians&quot;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice that the last expression is automatically returned.&lt;br&gt;
This is called &lt;strong&gt;implicit return&lt;/strong&gt;, which is common in functional programming.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;object-oriented-vs-functional-programming&quot;&gt;Object-Oriented vs Functional Programming&lt;/h3&gt;
&lt;p&gt;In object-oriented languages, you usually create objects and call methods on them.&lt;/p&gt;
&lt;p&gt;In functional programming, functions return values directly without relying on object instances.&lt;/p&gt;
&lt;p&gt;In Elixir:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There are no classes  &lt;/li&gt;
&lt;li&gt;Modules are not objects  &lt;/li&gt;
&lt;li&gt;Functions return data  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A module is just a namespace for functions, nothing more.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;understanding-arity&quot;&gt;Understanding Arity&lt;/h3&gt;
&lt;p&gt;In Elixir, functions are identified not only by their name, but also by the &lt;strong&gt;number of arguments&lt;/strong&gt; they receive.&lt;/p&gt;
&lt;p&gt;This is called &lt;strong&gt;arity&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Let’s create a new function:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-elixir&quot;&gt;def shuffle(list) do
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now recompile inside IEx:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-elixir&quot;&gt;recompile
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And try calling:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-elixir&quot;&gt;Basics.shuffle()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You will see an error similar to:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;function Basics.shuffle/0 is undefined. Did you mean shuffle/1?
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That means the function expects &lt;strong&gt;one argument&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-elixir&quot;&gt;defmodule Basics do
  def hello(), do: &quot;Hello World&quot;            # hello/0
  def hello(name), do: &quot;Hello, #{name}&quot;    # hello/1
  def hello(a, b), do: &quot;#{a} and #{b}&quot;      # hello/2
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These are considered &lt;strong&gt;different functions&lt;/strong&gt; because of their arity.&lt;/p&gt;
&lt;p&gt;Arity is written as:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function_name/number_of_arguments
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It becomes very important later when working with pattern matching and function clauses.&lt;/p&gt;
&lt;p&gt;More about functions and arity:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://elixirschool.com/en/lessons/basics/functions/&quot;&gt;https://elixirschool.com/en/lessons/basics/functions/&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;In this article we covered:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The relationship between Elixir and Erlang  &lt;/li&gt;
&lt;li&gt;What BEAM is and why it matters  &lt;/li&gt;
&lt;li&gt;How to create projects with Mix  &lt;/li&gt;
&lt;li&gt;How modules and functions work  &lt;/li&gt;
&lt;li&gt;What function arity means  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the next article, we’ll continue improving this project and exploring more Elixir features.&lt;/p&gt;
&lt;p&gt;See you soon!&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/10308/getting-started-with-elixir-understanding-erlang-beam-and-your-first-mix-project</guid>
<pubDate>Thu, 22 Jan 2026 23:35:11 +0000</pubDate>
</item>
<item>
<title>Elixir Setup Guide: Installing Erlang, Elixir, and Livebook with ASDF</title>
<link>https://coderlegion.com/9610/elixir-setup-guide-installing-erlang-elixir-and-livebook-with-asdf</link>
<description>&lt;h3 id=&quot;introduction-1&quot;&gt;Introduction&lt;/h3&gt;
&lt;p&gt;This article is part of a beginner series where I document my personal journey learning &lt;strong&gt;Elixir&lt;/strong&gt; and taking my first real steps in its ecosystem.&lt;/p&gt;
&lt;p&gt;I recently came from &lt;strong&gt;Node.js&lt;/strong&gt;, where setting up a development environment is usually very simple: install Node, get npm, add some VS Code extensions, and you're ready to go.&lt;/p&gt;
&lt;p&gt;With Elixir, the process is not hard, but I had a tough time finding a clear step-by-step guide. I ended up skipping important steps, which later caused a lot of unnecessary problems to fix.&lt;/p&gt;
&lt;p&gt;So in this guide, I’ll walk you through &lt;strong&gt;how to set up your Elixir environment from scratch&lt;/strong&gt; using ASDF.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; I’m using &lt;strong&gt;Linux Mint&lt;/strong&gt;, but the same process applies to most Linux distributions with small adjustments.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://i.giphy.com/media/4Zgy9QqzWU8C3ugvCa/giphy-downsized.gif&quot; alt=&quot;pinguim gif&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;what-is-asdf-and-why-use-it-&quot;&gt;What Is ASDF and Why Use It?&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://i.giphy.com/media/yoJC2qZ23Pb8HQI08g/giphy.gif&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The first thing we’ll install is a small but very powerful tool called &lt;strong&gt;ASDF&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;[ASDF][1] is a &lt;strong&gt;version manager&lt;/strong&gt; that allows you to install and manage multiple versions of languages and runtimes — including &lt;strong&gt;Erlang&lt;/strong&gt; and &lt;strong&gt;Elixir&lt;/strong&gt; — on the same machine.&lt;/p&gt;
&lt;p&gt;That means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You can easily switch between versions&lt;/li&gt;
&lt;li&gt;Projects can define their own required versions&lt;/li&gt;
&lt;li&gt;Your global system stays clean&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Grab some coffee ☕ and let’s start.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;step-1-installing-asdf&quot;&gt;Step 1: Installing ASDF&lt;/h3&gt;
&lt;p&gt;First, go to the official website:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://asdf-vm.com/&quot;&gt;https://asdf-vm.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Click on &lt;strong&gt;Get Started&lt;/strong&gt; and check the installation method for your operating system.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=4969792934007661136&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;On Linux Mint (and Ubuntu-based distros), make sure you have &lt;code&gt;curl&lt;/code&gt; and &lt;code&gt;git&lt;/code&gt; installed:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt install curl git
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now clone the ASDF repository:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.9.0
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;shell-integration-very-important-&quot;&gt;Shell Integration (Very Important)&lt;/h4&gt;
&lt;p&gt;This step is critical so your terminal can recognize the &lt;code&gt;asdf&lt;/code&gt; command.&lt;/p&gt;
&lt;h5 id=&quot;if-you-use-oh-my-zsh&quot;&gt;If you use Oh My Zsh&lt;/h5&gt;
&lt;p&gt;Follow the plugin instructions from:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins/asdf&quot;&gt;https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins/asdf&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Basically, add this line to your &lt;code&gt;~/.zshrc&lt;/code&gt; file:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;plugins=(git asdf)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then close and reopen your terminal.&lt;/p&gt;
&lt;h5 id=&quot;if-you-use-bash&quot;&gt;If you use Bash&lt;/h5&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=3452091372340258109&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Add these two lines to your &lt;code&gt;~/.bashrc&lt;/code&gt; file:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;. $HOME/.asdf/asdf.sh
. $HOME/.asdf/completions/asdf.bash
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Restart the terminal.&lt;/p&gt;
&lt;h4 id=&quot;verify-installation&quot;&gt;Verify Installation&lt;/h4&gt;
&lt;p&gt;Run:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;asdf --version
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You should see something similar to:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;v0.9.0-9ee24a3
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3 id=&quot;step-2-installing-the-erlang-plugin&quot;&gt;Step 2: Installing the Erlang Plugin&lt;/h3&gt;
&lt;p&gt;With ASDF installed, we can now install plugins. Let’s start with &lt;strong&gt;Erlang&lt;/strong&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;asdf plugin-add erlang
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;installing-system-dependencies&quot;&gt;Installing System Dependencies&lt;/h4&gt;
&lt;p&gt;Before compiling Erlang, we must install some required packages.&lt;/p&gt;
&lt;p&gt;For Linux Mint / Ubuntu 20-based systems:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt-get -y install build-essential autoconf m4 libncurses5-dev libwxgtk3.0-gtk3-dev libgl1-mesa-dev libglu1-mesa-dev libpng-dev libssh-dev unixodbc-dev xsltproc fop libxml2-utils libncurses-dev openjdk-11-jdk
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=4250902851566363072&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;These dependencies are listed in the official ASDF Erlang plugin repository:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/asdf-vm/asdf-erlang&quot;&gt;https://github.com/asdf-vm/asdf-erlang&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;step-3-installing-erlang&quot;&gt;Step 3: Installing Erlang&lt;/h3&gt;
&lt;p&gt;List all available Erlang versions:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;asdf list-all erlang
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=2914432950873415211&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Install the latest stable version at the time of writing:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;asdf install erlang 24.2.1
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; This step takes time and may look frozen. That’s normal. Be patient.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=12081288385957681070&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;set-erlang-as-global-version&quot;&gt;Set Erlang as Global Version&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;asdf global erlang 24.2.1
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;test-erlang&quot;&gt;Test Erlang&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;erl
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you see the Erlang shell, everything is working.&lt;br&gt;
Exit with &lt;code&gt;Ctrl + C&lt;/code&gt; twice.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=3602725178836810932&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;step-4-installing-elixir-with-asdf&quot;&gt;Step 4: Installing Elixir with ASDF&lt;/h3&gt;
&lt;p&gt;Now let’s install the Elixir plugin:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;asdf plugin-add elixir
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;List available versions:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;asdf list-all elixir
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since we installed Erlang OTP 24, we must install an Elixir version built for OTP 24.&lt;/p&gt;
&lt;p&gt;At the time of writing:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;asdf install elixir 1.13.3-otp-24
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Set it globally:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;asdf global elixir 1.13.3-otp-24
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;test-elixir&quot;&gt;Test Elixir&lt;/h4&gt;
&lt;p&gt;Start IEx:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;iex
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You should see the Elixir interactive shell.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=12211755436164361430&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;hello-world&quot;&gt;Hello World&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=16018175787732953936&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Inside IEx:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-elixir&quot;&gt;IO.puts(&quot;Hello World&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Welcome to Elixir &lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;step-5-using-livebook-for-experiments-and-notes&quot;&gt;Step 5: Using Livebook for Experiments and Notes&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=9478895543657364402&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Livebook&lt;/strong&gt; is similar to Jupyter Notebook for Python.&lt;/p&gt;
&lt;p&gt;It allows you to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Write executable Elixir code&lt;/li&gt;
&lt;li&gt;Document your learning&lt;/li&gt;
&lt;li&gt;Save notebooks as Markdown&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;installing-livebook&quot;&gt;Installing Livebook&lt;/h3&gt;
&lt;p&gt;Go to the official repository:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/livebook-dev/livebook&quot;&gt;https://github.com/livebook-dev/livebook&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Since Elixir is already installed globally, run:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;mix escript.install hex livebook
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Confirm installation when prompted.&lt;/p&gt;
&lt;p&gt;Because we’re using ASDF, we must refresh shims:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;asdf reshim
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Start Livebook:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;livebook server
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now open your browser and go to:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;http://localhost:8080
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=14719100701539462777&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;conclusion-1&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;In this article, we covered how to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Install &lt;strong&gt;ASDF&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Install &lt;strong&gt;Erlang&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Install &lt;strong&gt;Elixir&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Set up &lt;strong&gt;Livebook&lt;/strong&gt; locally&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This setup gives you a solid and flexible environment to start learning and building with Elixir.&lt;/p&gt;
&lt;p&gt;In the next articles of this series, we’ll finally start writing real Elixir code.&lt;/p&gt;
&lt;p&gt;See you in the next post ⚡&lt;/p&gt;
</description>
<category>Tutorials</category>
<guid isPermaLink="true">https://coderlegion.com/9610/elixir-setup-guide-installing-erlang-elixir-and-livebook-with-asdf</guid>
<pubDate>Mon, 12 Jan 2026 20:42:17 +0000</pubDate>
</item>
</channel>
</rss>