Packages
nous
0.5.0
0.17.0
0.16.6
0.16.5
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.8
0.15.7
0.15.6
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.3
0.14.2
0.14.1
0.14.0
0.13.3
0.13.2
0.13.1
0.13.0
0.12.17
0.12.16
0.12.15
0.12.14
0.12.13
0.12.12
0.12.11
0.12.9
0.12.7
0.12.6
0.12.5
0.12.3
0.12.2
0.12.0
0.11.3
0.11.0
0.10.1
0.10.0
0.9.0
0.8.1
0.8.0
0.7.2
0.7.1
0.7.0
0.5.0
AI agent framework for Elixir with multi-provider LLM support
Current section
Files
Jump to
Current section
Files
README.md

# Nous AI
> *"Nous (νοῦς) — the ancient Greek concept of mind, reason, and intellect; the faculty of understanding that grasps truth directly."*
AI agent framework for Elixir with multi-provider LLM support.
[](https://elixir-lang.org)
[](https://github.com/nyo16/nous/blob/master/LICENSE)
[](#features)
Nous AI is an AI agent framework for Elixir with support for any OpenAI-compatible API. Features include tool calling, multi-provider support, local LLM execution, and built-in utilities for dates, strings, web search, and task tracking.
## Installation
Add to your `mix.exs`:
```elixir
def deps do
[
{:nous, "~> 0.5.0"},
{:openai_ex, "~> 0.9.17"}
]
end
```
Then run:
```bash
mix deps.get
```
## Quick Start
```elixir
# Create an agent
agent = Nous.new("lmstudio:qwen/qwen3-30b",
instructions: "Be helpful and concise"
)
# Run it
{:ok, result} = Nous.run(agent, "What is 2+2?")
IO.puts(result.output) # "4"
IO.puts("Tokens: #{result.usage.total_tokens}")
```
## Supported Providers
| Provider | Model String | Status |
|----------|-------------|--------|
| LM Studio | `lmstudio:qwen/qwen3-30b` | Tested & Working |
| OpenAI | `openai:gpt-4` | Supported |
| Anthropic | `anthropic:claude-sonnet-4-5-20250929` | Tested & Working |
| Google Gemini | `gemini:gemini-2.0-flash-exp` | Native API |
| Mistral AI | `mistral:ministral-3-14b-instruct-2512` | Native API + Req |
| Groq | `groq:llama-3.1-70b-versatile` | Supported |
| Ollama | `ollama:llama2` | Supported |
| vLLM | `vllm:model` + `:base_url` | Supported |
| OpenRouter | `openrouter:anthropic/claude-3.5-sonnet` | Supported |
| Together AI | `together:meta-llama/Llama-3-70b-chat-hf` | Supported |
| Custom | `custom:model` + `:base_url` | Supported |
**Local (Zero Cost):** LM Studio, Ollama, vLLM
**Cloud:** OpenAI, Anthropic, Mistral AI, Groq, OpenRouter, Together AI
```elixir
# Switch providers with one line change
agent = Nous.new("lmstudio:qwen/qwen3-30b") # Local
agent = Nous.new("openai:gpt-4") # Cloud
agent = Nous.new("anthropic:claude-sonnet-4-5-20250929") # Claude
agent = Nous.new("mistral:ministral-3-14b-instruct-2512") # Mistral
```
## Agent Types
| Feature | `ReActAgent` | Standard `Agent` |
|---------|--------------|------------------|
| **Planning** | Built-in structured planning | No planning (you control flow) |
| **Todo tracking** | Automatic task breakdown | Manual (via custom tools) |
| **Completion** | Explicit `final_answer` required | Stops naturally |
| **Best for** | Complex multi-step problems | Simple tasks, custom workflows |
| **Token usage** | Higher (planning + tracking) | Lower (direct execution) |
### ReActAgent (Enhanced Planning)
Use for complex, multi-step problems with structured planning. Agent creates plans, tracks todos, and documents findings.
```elixir
agent = Nous.ReActAgent.new("lmstudio:qwen/qwen3-30b",
tools: [&search/2, &calculate/2]
)
{:ok, result} = Nous.ReActAgent.run(agent,
"Who is the oldest F1 driver and when did they win their first championship?"
)
```
See [examples/react_agent_enhanced_demo.exs](examples/react_agent_enhanced_demo.exs) or [by_feature/patterns/](examples/by_feature/README.md#-patterns-agent-reasoning--architecture)
### Standard Agent (Flexible & Simple)
Use for simple Q&A, single-step tasks, or custom workflows where you control behavior.
```elixir
agent = Nous.new("openai:gpt-4",
tools: [&calculate/2]
)
{:ok, result} = Nous.run(agent, "Calculate 15 * 23")
```
## Built-in Tools
### DateTime Tools
Date/time operations with timezone support, date arithmetic, and formatting.
```elixir
alias Nous.Tools.DateTimeTools
tools: [&DateTimeTools.current_date/2, &DateTimeTools.date_difference/2, &DateTimeTools.add_days/2]
```
See [examples/datetime_tools_demo.exs](examples/datetime_tools_demo.exs) or [by_feature/tools/](examples/by_feature/README.md#-tools-function-calling--actions)
### String Tools
Text manipulation: uppercase, replace, split, palindrome detection, number extraction.
```elixir
alias Nous.Tools.StringTools
tools: [&StringTools.to_uppercase/2, &StringTools.replace_text/2, &StringTools.extract_numbers/2]
```
See [examples/string_tools_demo.exs](examples/string_tools_demo.exs) or [by_feature/tools/](examples/by_feature/README.md#-tools-function-calling--actions)
### Todo Tools
Automatic task breakdown and progress tracking for multi-step workflows.
```elixir
alias Nous.Tools.TodoTools
agent = Nous.new("lmstudio:qwen/qwen3-30b",
enable_todos: true,
tools: [&TodoTools.add_todo/2, &TodoTools.complete_todo/2]
)
```
See [examples/todo_tools_demo.exs](examples/todo_tools_demo.exs) or [by_feature/tools/](examples/by_feature/README.md#-tools-function-calling--actions)
### Brave Search (Web Search)
Search the web for current information. Requires `BRAVE_API_KEY` ([get free key](https://brave.com/search/api/)).
```elixir
alias Nous.Tools.BraveSearch
tools: [&BraveSearch.web_search/2, &BraveSearch.news_search/2]
```
See [examples/brave_search_demo.exs](examples/brave_search_demo.exs) or [by_feature/tools/](examples/by_feature/README.md#-tools-function-calling--actions)
## Features
### Tool Calling
Define Elixir functions as tools. AI calls them automatically when needed.
```elixir
def search_database(_ctx, %{"query" => q}), do: DB.search(q)
agent = Nous.new("openai:gpt-4",
tools: [&search_database/2]
)
```
### Tools with Context
Pass dependencies (user, database, API keys) via context:
```elixir
def get_balance(ctx, _args), do: DB.get_balance(ctx.deps.database, ctx.deps.user.id)
{:ok, result} = Nous.run(agent, "What's my balance?",
deps: %{user: %{id: 123}, database: MyApp.DB}
)
```
See [examples/tools_with_context.exs](examples/tools_with_context.exs) or [custom_tools_guide.exs](examples/custom_tools_guide.exs)
### Conversations
```elixir
{:ok, r1} = Nous.run(agent, "Tell me a joke")
{:ok, r2} = Nous.run(agent, "Explain it", message_history: r1.new_messages)
```
### Streaming
```elixir
{:ok, stream} = Nous.run_stream(agent, "Write a poem")
stream |> Stream.each(fn {:text_delta, t} -> IO.write(t) end) |> Stream.run()
```
### Anthropic Extended Features
```elixir
# 1M token context window
agent = Nous.new("anthropic:claude-sonnet-4-5-20250929",
model_settings: %{enable_long_context: true}
)
# Extended thinking mode
agent = Nous.new("anthropic:claude-sonnet-4-5-20250929",
model_settings: %{thinking: %{type: "enabled", budget_tokens: 5000}}
)
```
### LiveView Integration
```elixir
# Spawn linked streaming process from LiveView
spawn_link(fn ->
agent = Nous.new("anthropic:claude-sonnet-4-5-20250929")
{:ok, stream} = Nous.run_stream(agent, message)
stream
|> Stream.each(fn
{:text_delta, text} -> send(parent, {:stream_chunk, text})
{:finish, result} -> send(parent, {:stream_complete, result})
_ -> :ok
end)
|> Stream.run()
end)
```
See [liveview_streaming_example.ex](examples/liveview_streaming_example.ex) for real-time streaming or [LIVEVIEW_INTEGRATION.md](examples/LIVEVIEW_INTEGRATION.md) for patterns
## Logging & Telemetry
Configure log level in `config/config.exs`:
```elixir
config :logger, level: :info # or :debug, :warning, :error
```
Attach telemetry handlers:
```elixir
Nous.Telemetry.attach_default_handler()
```
Events: `[:nous, :agent, :run, :*]`, `[:nous, :model, :request, :*]`, `[:nous, :tool, :execute, :*]`
## Examples
**🚀 [Get Started in 5 Minutes](examples/GETTING_STARTED.md)** - Quick setup guide with local or cloud options.
**📚 [Full Examples Collection](examples/README.md)** - Comprehensive learning path from beginner to production.
### Learning Path Overview
**🟢 Beginner** (5-15 minutes each)
- [basic_hello_world.exs](examples/basic_hello_world.exs) - 30-second minimal example
- [test_lm_studio.exs](examples/test_lm_studio.exs) - Local LM Studio setup
- [tools_simple.exs](examples/tools_simple.exs) - Basic tool calling
- [calculator_demo.exs](examples/calculator_demo.exs) - Multi-tool chaining
**🟡 Intermediate** (15-45 minutes each)
- [streaming_example.exs](examples/streaming_example.exs) - Real-time responses
- [conversation_history_example.exs](examples/conversation_history_example.exs) - Multi-turn chat
- [error_handling_example.exs](examples/error_handling_example.exs) - Graceful failure handling
- [cost_tracking_example.exs](examples/cost_tracking_example.exs) - Monitor token usage
**🔴 Advanced** (45+ minutes each)
- [Trading Desk](examples/trading_desk/README.md) - Production multi-agent system
- [Council](examples/council/README.md) - Multi-LLM deliberation
- [Coderex](examples/coderex/README.md) - AI code editor with SEARCH/REPLACE
**Browse by:**
- [Skill Level](examples/by_level/README.md) - Beginner → Intermediate → Advanced
- [Provider](examples/by_provider/README.md) - Anthropic, OpenAI, Local, etc.
- [Feature](examples/by_feature/README.md) - Tools, Streaming, Patterns, etc.
**Quick Templates:**
- [templates/](examples/templates/README.md) - Copy-paste starter files
## Architecture
```
User Code
↓
Nous.Agent (config)
↓
Nous.AgentRunner (execution loop)
↓
├─→ OpenAICompatible (model adapter)
│ ↓
│ OpenaiEx (HTTP client)
│ ↓
│ LM Studio / OpenAI / Groq / etc.
│
├─→ ToolExecutor (run functions)
├─→ Messages (format conversion)
└─→ Usage (track tokens)
```
## Stats
- **Lines:** ~2,100 | **Modules:** 16 | **Tests:** 18 passing | **Providers:** 7+
## Contributing
Contributions welcome! Areas for improvement:
- More comprehensive tests
- Structured output validation (Ecto integration)
- Performance benchmarks
- More examples
## License
Apache 2.0 License - see [LICENSE](https://github.com/nyo16/nous/blob/master/LICENSE)
## Credits
- Inspired by [Pydantic AI](https://ai.pydantic.dev/)
- Built with [openai_ex](https://github.com/cyberchitta/openai_ex)
- Validation with [ecto](https://github.com/elixir-ecto/ecto)