striking

striking

Alloy 0.8.0 - Minimal, OTP-native agent loop for Elixir

Alloy 0.8.0 The model-agnostic agent engine for Elixir

Alloy is a minimal agent loop for building AI agents on the BEAM. Think of it as the completion-tool-call loop and nothing else, no opinions on sessions, persistence, or UI.

What’s new in 0.8.0

Cost guard pass max_budget_cents: 50 to Alloy.run/2 and the loop halts with :budget_exceeded status before your agent overspends. The check runs at the start of each turn alongside max_turns.

{:ok, result} = Alloy.run("Research this codebase",
  provider: {Alloy.Provider.Anthropic, api_key: key, model: "claude-sonnet-4-6"},
  tools: [Alloy.Tool.Core.Read, Alloy.Tool.Core.Bash],
  max_budget_cents: 50
)
# result.status => :budget_exceeded | :completed

Summary-based context compaction when conversations approach the token limit, Alloy generates a structured handoff summary of older context instead of truncating. The summary preserves progress, key decisions, constraints, and next steps. Falls back to deterministic truncation if summary generation fails.

Compaction is now configurable:

Alloy.run(input,
  provider: provider,
  compaction: [
    reserve_tokens: 12_000,       # Room for the next response
    keep_recent_tokens: 8_000,    # Recent messages kept verbatim
    fallback: :truncate           # When summary fails
  ]
)

One-shot streaming Alloy.stream/3 gives you token-by-token output without managing a GenServer:

{:ok, result} = Alloy.stream("Explain OTP", fn chunk ->
  IO.write(chunk)
end, provider: {Alloy.Provider.OpenAI, api_key: key, model: "gpt-5.4"})

Why model-agnostic matters

Alloy works with Anthropic, OpenAI (Responses API), xAI/Grok, Gemini, and any OpenAI-compatible endpoint (Ollama, OpenRouter, DeepSeek, Mistral, Groq). Swap providers by changing one line — your tools, prompts, and agent logic stay the same.

Today’s best model might not be tomorrow’s. Building on Alloy means you can switch without rewriting your agent.

The philosophy

Inspired by Pi Agent’s minimalism: 4 built-in tools (read, write, edit, bash), a good prompt, and a loop. That’s the framework. ~5,000 lines, small enough to read and understand in an afternoon.

OTP gives us the rest for free: supervision trees for fault tolerance, Task.Supervisor for parallel tool execution, PubSub for event streaming, GenServer for stateful agents.

Links

Feedback, issues, and PRs welcome. Happy to answer questions about the architecture.

Where Next?

Popular in News & Updates Top

zachdaniel
Hey folks! I’ve released the first version of our new AI policy. Accepting it is now part of our issue and pull request templates. Feel ...
New
zachdaniel
What if you had full stack types for SPAs built with tech like React, Inertia, Vue, Svelte… but all of the power Ash Framework and Elixir...
New
bartblast
Great news for Hologram: the Erlang Ecosystem Foundation has awarded a stipend to support key development milestones! I’m deeply gratefu...
New
bartblast
Hologram’s journey just took a significant leap forward: Curiosum is coming on board as the Main Sponsor, and I’m joining their team to w...
New
zachdaniel
Ash Framework 3.0: Official Release! I’m here with the fine folks at Gig City Elixir, pushing the button live on stage :sunglasses: T...
New
zachdaniel
Hey folks, made some recent performance improvements to spark, the tool underlying all of our DSLs. GitHub - ash-project/spark: Tooling f...
New
josevalim
Hi everyone, We have just released Mime v2.0.4 with a potential security fix. Before this version, Mime.extensions("foo/bar+baz") would ...
New
zachdaniel
We recently launched atomic updates, which look like this: update :update do change atomic_update(:score, expr(score + 1)) end # or w...
New
jjcarstens
NervesPack 0.4.0 is a minor bump with a fairly big change. This update drops :nerves_firmware_ssh in favor of the newer and more focused...
New
fhunleth
I wanted to let everyone know that the Erlang Ecosystem Foundation (EEF) has a working group dedicated to embedded systems and IoT. We ha...
New

Other popular topics Top

mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
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 Postgres...
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 53690 245
New
josevalim
Hi everyone, One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
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
axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 47930 226
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

We're in Beta

About us Mission Statement