guess

guess

ClaudeCode - Agentic AI for Elixir Applications

Hi! I’ve been building ClaudeCode, an SDK that lets you embed Claude as an agent in your Elixir apps - not just a chatbot, but an AI that can take actions.

The Problem

Most AI integrations are text-in/text-out. Building anything useful means parsing responses, manually wiring tool calls, handling conversation state, and mocking everything by hand for tests.

The Solution: Hermes + ClaudeCode

ClaudeCode wraps the claude cli, giving Claude full agentic capabilities. Combined with hermes_mcp v0.14.1 — Documentation , Claude can call your Elixir functions directly:

  # Define a tool
  defmodule MyApp.Tools.RefundOrder do
    use Hermes.Server.Component, type: :tool

    schema do
      field :order_id, :string, required: true
    end

    def execute(%{order_id: id}, frame) do
      {:ok, refund} = MyApp.Orders.refund(id)
      {:reply, Response.json(Response.tool(), refund), frame}
    end
  end

  # Create an MCP server
  defmodule MyApp.SupportTools do
    use Hermes.Server, name: "myapp", version: "1.0.0", capabilities: [:tools]

    component MyApp.Tools.RefundOrder
    component MyApp.Tools.OrderLookup
  end

  # Start a session
  {:ok, session} = ClaudeCode.start_link(mcp_servers: %{"myapp" => MyApp.SupportTools})

  # Ask it to do something
  session
  |> ClaudeCode.stream("Customer jane@example.com wants a refund for her last order")
  |> ClaudeCode.Stream.tap(&IO.inspect/1)
  |> ClaudeCode.Stream.final_text()

Claude will call OrderLookup, find Jane’s order, call RefundOrder, and explain what happened. No decision trees. No hardcoded workflows.

Testing Without API Calls

  test "support agent processes refunds" do
    ClaudeCode.Test.stub(ClaudeCode, fn _query, _opts ->
      [
        ClaudeCode.Test.tool_use("OrderLookup", %{email: "jane@example.com"}),
        ClaudeCode.Test.tool_result(%{id: "ORD-123", total: 99.99}]),
        ClaudeCode.Test.text("Processing refund for order ORD-123..."),
        ClaudeCode.Test.tool_use("RefundOrder", %{order_id: "ORD-123", reason: "request"}),
        ClaudeCode.Test.tool_result(%{status: "processed"}),
        ClaudeCode.Test.text("Done! Refunded $99.99.")
      ]
    end)

    {:ok, session} = ClaudeCode.start_link()
    result = session |> ClaudeCode.stream("Refund Jane") |> ClaudeCode.Stream.final_text()

    assert result =~ "Refunded $99.99"
  end

Millisecond tests. No API calls. Full async: true support.

Also Included

  • OTP Supervision - Sessions restart on failure
  • Native Streaming - Elixir Streams, LiveView-ready
  • Multi-turn Memory - Context retained across queries
  • Concurrent Agents - Run multiple sessions with the actor model

Links

Early days - I’d love to hear what agents you’d build, or what’s missing that would make this useful for your projects.

Where Next?

Popular in Announcing Top

OvermindDL1
I created a new library (rather I pulled out a couple files from my big project), it manages an operating system PID file for the BEAM. ...
New
martinthenth
Hello everybody :wave: Recently, some of my colleagues talked about database ids and uuids and their problems, and I remembered the pain...
New
josevalim
Yes, yet another parser combinator library! Most of the parser combinators in the ecosystem are either compile-time, often using AST tra...
159 19103 141
New
jakub-zawislak
Hi everyone, I’m coming from the Symfony (PHP) framework. I like Phoenix, but it has a one thing that was build much better in the Symfo...
New
mtrudel
Bandit is an HTTP server for Plug and WebSock apps. Bandit is written entirely in Elixir and is built atop Thousand Island. It can serve...
New
Crowdhailer
Experimenting with this code. OK.try do user <- fetch_user(1) cart <- fetch_cart(1) order = checkout(cart, user) save_or...
New
woylie
I released Doggo, a collection of unstyled Phoenix components. Features Unstyled Phoenix components. Storybook that can be added to...
New
OvermindDL1
Been making an MLElixir thing (not released yet…) for fun in spare time in the past day. I’m just trying to see how much I can get an ML...
132 13940 106
New
anshuman23
Hello all, I have been working on my proposed project called Tensorflex as part of Google Summer of Code 2018.. Tensorflex can be used f...
New
trisolaran
Hi! :waving_hand: I would like to present LiveSelect, a little library that I wrote to easily add a dynamic selection input to your LV f...
198 10836 107
New

Other popular topics Top

lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
johnnyicon
Hi all, I've just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I'm trying to use Postg...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set? Thanks.
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
boundedvariable
I am going through the kafka architecture. All the features what the kafka is providing are already in Erlang. I would like hear your opi...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
klo
Got a question about when to concat vs. prepending items to list then reversing to achieve appending. So i know lists boil down to [1 | ...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New

We're in Beta

About us Mission Statement