sonic182

sonic182

Llm_composer - Elixir library for building LLM-based applications

Hi everyone, at Doofinder we have been building llm_composer for some new apps, and we thought it could be useful to share it with the community.

llm_composer is an Elixir library that simplifies working with large language models (LLMs) like OpenAI’s GPT, OpenRouter, Ollama, AWS Bedrock, and Google (Gemini).

It provides a streamlined way to build and execute LLM-based applications or chatbots, with features such as:

  • Multi-provider support (OpenAI, OpenRouter, Ollama, Bedrock, Google Gemini/Vertex AI).
  • System prompts and message history management.
  • Streaming responses.
  • Function calls with auto-execution.
  • Structured outputs with JSON schema validation.
  • Built-in cost tracking (currently for OpenRouter).
  • Easy extensibility for custom use cases.

A key feature is the provider router that handles failover automatically.
It will use one provider until it fails, then fall back to the next provider in the list, applying an exponential backoff strategy. This makes it resilient in production environments where provider APIs can become temporarily unavailable.

Under the hood, llm_composer uses Tesla as the HTTP client.
For production setups, especially when using streaming, it is recommended to run it with Finch for optimal performance.


More info and docs:

HexDocs: LlmComposer — llm_composer v0.20.0
GitHub:

https://github.com/doofinder/llm_composer

Most Liked

sonic182

sonic182

llm_composer v0.16.0 released (Feb 23, 2026)

Quick update since the last post (v0.12.2 / MIT switch) — quite a bit has landed since then.


What’s new in 0.16.0

  • New provider: LlmComposer.Providers.OpenAIResponses — calls OpenAI’s /responses API with support for structured outputs and reasoning (provider/model-specific params passed via request_params), normalized into the usual LlmResponse shape. Since it targets the /responses API spec, it also works with compatible providers like x.ai (xAI/Grok), OpenRouter’s responses endpoint, and others.
  • Typed streaming chunks: new LlmComposer.StreamChunk struct + provider-specific parsing turns raw stream events into typed values (:text_delta, :tool_call_delta, :done, …).
  • LlmComposer.FunctionCallExtractors: centralizes function call extraction logic per provider.
  • Provider-aware parse_stream_response: now comes in /2 and /3 arities and returns %StreamChunk{} values instead of raw decoded maps.
  • Internals refactored to protocol-based adapters (LlmComposer.ProviderResponse + LlmComposer.ProviderStreamChunk) for cleaner normalization across providers.

Notable releases since 0.12.2

  • 0.13.0 (Dec 2025): function-call workflow is now manual/explicit via FunctionExecutor + FunctionCallHelpers — breaking change, see changelog.
  • 0.13.1 (Jan 2026): custom HTTP headers support for OpenRouter.
  • 0.14.0 (Feb 4): configurable retry/backoff for provider requests.
  • 0.14.1 (Feb 9): deep merge fix for nested request_params (e.g. Google’s generationConfig).
  • 0.14.2 (Feb 10): LlmResponse.new/3 now returns {:error, …} instead of raising on unknown provider formats.
  • 0.15.0 (Feb 17): configurable :json_engine (defaults to JSON, falls back to Jason); Google provider now preserves additionalProperties in response schemas.

Upgrade

{:llm_composer, "~> 0.16.0"}

Full changelog: llm_composer/CHANGELOG.md at master · doofinder/llm_composer · GitHub

Jskalc

Jskalc

Thanks for your efforts! :raising_hands:

Could you highlight the differences from ReqLLM, discussed in this topic? I believe both libraries aim to solve the same problem.

sonic182

sonic182

We started this lib about a year ago (we’d been using it internally even before that) and only now decided to share it here.

Both libraries aim at the same thing: wrapping LLM APIs behind a unified HTTP client.

The main differences are:

  • HTTP layer: we use Tesla, ReqLLM builds on Req.

  • Routing: llm_composer includes a router with fallback + retries.

  • API style: each library exposes a slightly different way to configure and work with “bots” or requests, so it depends which style you prefer.

Where Next?

Popular in Announcing Top

danschultzer
In short Plug n’ play OAuth 2.0 provider library. Just set up a resource owner schema with Ecto (your user schema), install the dependen...
New
mspanc
I am pleased to announce an initial release of the Membrane Framework - an Elixir-based framework with special focus on processing multim...
New
pkrawat1
Presenting Aviacommerce, open source e-commerce platform in Elixir Aviacommerce is an open source e-commerce platform in Elixir. We at...
New
bryanjos
Hi, I wanted share a small library we at Revelry Labs made for rendering react components from the server side. There are instructions fo...
New
type1fool
WebAuthnLiveComponent WebAuthnComponents See this post about renaming the package. Passwordless authentication for Phoenix LiveView app...
New
versilov
Could not wait for the missing Elixir ML libraries to appear, so, I wrote one myself, taking https://github.com/sdwolfz/exlearn as a foun...
New
archan937
It is a well-know topic within the Elixir community: “To mock or not to mock? :)” Every alchemist probably has his / her own opinion con...
New
benlime
LiveMotion enables high performance animations declared on the server and run on the client. As a follow up to my previous thread A libr...
New
mattludwigs
Grizzly is a library for working with Z-Wave devices. Z-Wave is a low-frequency radio protocol for controlling smart home devices on a me...
New
New

Other popular topics Top

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 48342 226
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
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
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement