Normandy

Build production-ready AI agents in Elixir β€” structured schemas, tool calling, multi-agent coordination, streaming, and distributed sessions, with first-class Anthropic Claude support.

Hex.pmDocumentationCILicense: MIT

Normandy is an Elixir framework for building reliable LLM agents on the BEAM. It gives you type-safe input/output schemas with automatic JSON Schema generation, tool/function calling, conversational memory, and OTP-native primitives for multi-agent coordination and distributed, fault-tolerant sessions. It ships with a built-in adapter for Anthropic Claude and a clean protocol for any other LLM provider.

Features

Installation

Add normandy to your dependencies in mix.exs:

def deps do
[
{:normandy, "~> 1.0"}
]
end

Then fetch dependencies:

mix deps.get

Quick Start

Define structured data, then run an agent against Anthropic Claude:

# 1. Configure an LLM client (built-in Anthropic Claude adapter)
client = %Normandy.LLM.ClaudioAdapter{
api_key: System.get_env("ANTHROPIC_API_KEY"),
options: %{enable_caching: true}
}
# 2. Initialize an agent
agent =
Normandy.Agents.BaseAgent.init(%{
client: client,
model: "claude-sonnet-4-6",
temperature: 0.7
})
# 3. Run a turn
{agent, response} =
Normandy.Agents.BaseAgent.run(agent, %{
chat_message: "Explain Elixir's actor model in one sentence."
})

Defining a typed schema is just as direct:

defmodule User do
use Normandy.Schema
io_schema "User profile" do
field(:name, :string, description: "Full name", required: true)
field(:age, :integer, description: "Age", minimum: 0, maximum: 150)
end
end
# Export as JSON Schema for LLM prompts / structured output
schema = User.get_json_schema()

Bring your own LLM by implementing the Normandy.Agents.Model protocol β€” Claude is supported out of the box, but nothing is hard-wired to it.

Documentation

Full API reference and guides are published on HexDocs:

Generate the docs locally with mix docs and open doc/index.html.

Development

mix test # run the default suite (integration tests skipped)
mix test --cover # run with coverage
mix dialyzer # static type analysis
mix format # format code

Run the live-API integration suite with an Anthropic key:

export ANTHROPIC_API_KEY="your-api-key"
mix test --include integration --include normandy_integration

Contributing

Contributions are welcome β€” please open an issue or submit a pull request.

License

Released under the MIT License.

Acknowledgments

The schema system is inspired by Ecto's approach to data definition, validation, and changesets.


Made with Elixir πŸ’œ