T
thetonymaster/normandy
Build production-ready AI agents in Elixir — structured schemas, tool calling, multi-agent coordination,…
View on GitHub ↗Link checked 2026-11-12 · HTTP 200 · opens the vendor's own site
- Star count
- 2 ★ · thetonymaster/normandy · read from the GitHub search API · (checked 2026-11-13 20:00:50)
- Source
- read directly from its GitHub page · type: open-source project
- Harvest history
- first seen 2026-10-24 · last seen 2026-11-14 · seen 25× · listed by 1 sources
- Score
- score 103 · 2 ★ · 1 sources · repo
FAQ (answers come from our records)
Who is it for?
We filed it under these tags: 开源项目. The tags come from the entry itself, not a taxonomy we imposed.
Who maintains it?
repository
thetonymaster/normandy;first catalogued 2026-10-24;last seen 2026-11-14。There is no official certification or quality rating here — we record sources and dates only.# Normandy
以下摘录自该仓库的 README(片段) · 在 GitHub 读完整 README →
> Build production-ready AI agents in Elixir — structured schemas, tool calling, multi-agent coordination, streaming, and distributed sessions, with first-class Anthropic Claude support.
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
🧠 Agent system — conversational agents with memory, state, and turn-based history.
📋 Schema DSL — typed, validated structs with JSON Schema generation (nested schemas, anyOf/oneOf/allOf, conditional if/then/else, virtual fields, introspection).
🔧 Tool calling — LLM tool/function calling with automatic execution loops.
🤝 Multi-agent coordination — reactive patterns (race/all/some), agent pools, and supervised agent processes.
🌐 Distributed sessions — single-node to multi-node, fault-tolerant sessions across Tiers 0/1/2 (in-memory/ETS, Postgres, Mnesia, Redis) with eager resume on node loss.
🛡️ Guardrails — input/output admission control with fail-open/closed policies and semantic scope checks.
🌊 Streaming — real-time response streaming with callback-based event processing.
💰 Prompt caching — up to 90% cost reduction via automatic Anthropic prompt caching.
🔄 Resilience — built-in retry (exponential backoff + jitter) and circuit breaker patterns.
📦 Batch processing — concurrent processing of many inputs with progress tracking.
📏 Context management — token counting, automatic truncation, and LLM-based summarization.
🔌 Protocol support — interoperate via Model Context Protocol (MCP) and Agent-to-Agent (A2A).
📊 Observability — Telemetry events, structured lifecycle logging, and OpenTelemetry-compatible spans.
🎯 Type safety — comprehensive type system with Dialyzer support, backed by 900+ tests including property-based testing.
## Installation
Add normandy to your dependencies in mix.exs:
elixir
def deps do
{:normandy, "~> 2.0"}
end
Upgrading from 1.x? See MIGRATING-2.0.md.
Then fetch dependencies:
bash
mix deps.get
## Quick Start
Define structured data, then run an agent against Anthropic Claude:
elixir
# 1. Configure an LLM client (built-in Anthropic Claude adapter; prompt caching is on
# by default)
client = %Normandy.LLM.ClaudioAdapter{apikey: System.getenv("ANTHROPICAPIKEY")}
# 2. Initialize an agent
agent =
Normandy.Agents.BaseAgent.init(%{
client: client,
model: "claude-opus-5-5"
})
# 3. Run a turn: {:ok, agent, response} with the updated agent (it holds the
# conversation), or {:error, exception}, e.g. a %Normandy.LLMError{}
input = %{chatmessage: "Explain Elixir's actor model in one sentence."}
case Normandy.Agents.BaseAgent.run(agent, input) do
{:ok, agent, response} -> IO.puts(response.chatmessage)
{:error, error} -> IO.puts("Turn failed: " <> Exception.message(error))
end
Defining a typed schema is just as direct:
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
🧠 Agent system — conversational agents with memory, state, and turn-based history.
📋 Schema DSL — typed, validated structs with JSON Schema generation (nested schemas, anyOf/oneOf/allOf, conditional if/then/else, virtual fields, introspection).
🔧 Tool calling — LLM tool/function calling with automatic execution loops.
🤝 Multi-agent coordination — reactive patterns (race/all/some), agent pools, and supervised agent processes.
🌐 Distributed sessions — single-node to multi-node, fault-tolerant sessions across Tiers 0/1/2 (in-memory/ETS, Postgres, Mnesia, Redis) with eager resume on node loss.
🛡️ Guardrails — input/output admission control with fail-open/closed policies and semantic scope checks.
🌊 Streaming — real-time response streaming with callback-based event processing.
💰 Prompt caching — up to 90% cost reduction via automatic Anthropic prompt caching.
🔄 Resilience — built-in retry (exponential backoff + jitter) and circuit breaker patterns.
📦 Batch processing — concurrent processing of many inputs with progress tracking.
📏 Context management — token counting, automatic truncation, and LLM-based summarization.
🔌 Protocol support — interoperate via Model Context Protocol (MCP) and Agent-to-Agent (A2A).
📊 Observability — Telemetry events, structured lifecycle logging, and OpenTelemetry-compatible spans.
🎯 Type safety — comprehensive type system with Dialyzer support, backed by 900+ tests including property-based testing.
## Installation
Add normandy to your dependencies in mix.exs:
elixir
def deps do
{:normandy, "~> 2.0"}
end
Upgrading from 1.x? See MIGRATING-2.0.md.
Then fetch dependencies:
bash
mix deps.get
## Quick Start
Define structured data, then run an agent against Anthropic Claude:
elixir
# 1. Configure an LLM client (built-in Anthropic Claude adapter; prompt caching is on
# by default)
client = %Normandy.LLM.ClaudioAdapter{apikey: System.getenv("ANTHROPICAPIKEY")}
# 2. Initialize an agent
agent =
Normandy.Agents.BaseAgent.init(%{
client: client,
model: "claude-opus-5-5"
})
# 3. Run a turn: {:ok, agent, response} with the updated agent (it holds the
# conversation), or {:error, exception}, e.g. a %Normandy.LLMError{}
input = %{chatmessage: "Explain Elixir's actor model in one sentence."}
case Normandy.Agents.BaseAgent.run(agent, input) do
{:ok, agent, response} -> IO.puts(response.chatmessage)
{:error, error} -> IO.puts("Turn failed: " <> Exception.message(error))
end
Defining a typed schema is just as direct:
Listed badge (optional)
Copy this line into the README if you want the listing mark. Optional, and it does not affect being listed.
[](https://anclum.com/en/s/thetonymaster-normandy/)
- Source
- github · https://github.com/thetonymaster/normandy
- Browse by field
- Open source
- Traction
- 2 ★
- added
- today
More like this
Filed under
Every tag opens the full list for that filter. Counts are the live catalogue figures.