defmodule Nous.MixProject do use Mix.Project @version "0.16.6" @source_url "https://github.com/nyo16/nous" def project do [ app: :nous, version: @version, elixir: "~> 1.18", start_permanent: Mix.env() == :prod, deps: deps(), docs: docs(), aliases: aliases(), description: "AI agent framework for Elixir with multi-provider LLM support", source_url: @source_url, package: package(), elixirc_paths: elixirc_paths(Mix.env()), dialyzer: [ plt_file: {:no_warn, "priv/plts/dialyzer.plt"}, plt_add_apps: [:mix, :ex_unit, :inets] ] ] end def application do [ extra_applications: [:logger, :inets], mod: {Nous.Application, []}, # hackney's :default pool starts automatically when the :hackney # application starts; ensuring it's listed here is just defensive. included_applications: [] ] end defp elixirc_paths(:test), do: ["lib", "test/support"] defp elixirc_paths(_), do: ["lib"] defp deps do [ # YAML (for evaluation framework) {:yaml_elixir, "~> 2.9"}, # Validation {:ecto, "~> 3.11"}, # HTTP clients for all LLM providers. # Finch/Req is the default backend for both one-shot and streaming. # Hackney is an opt-in alternative for SSE/long-streaming bodies — its # `:async, :once` mode is truly pull-based, so the consumer paces the # producer and a slow consumer can't OOM us via mailbox accumulation. # (Finch.stream/5's callback is push-based; a fast LLM + slow consumer = # unbounded mailbox growth — see review M-12.) To use the hackney # backend, declare `{:hackney, "~> 4.0"}` in your app's deps and select # it via `NOUS_HTTP_BACKEND=hackney` (or the streaming variant). {:finch, "~> 0.19"}, # `or ~> 0.6` lets downstream apps adopt req 0.6.x without a resolver # conflict against nous (we still lock 0.5.x until verified on 0.6). {:req, "~> 0.5 or ~> 0.6"}, {:hackney, "~> 4.0", optional: true}, # Google Cloud auth for Vertex AI (optional — add to your app's deps to unlock) {:goth, "~> 1.4", optional: true}, # HTML parsing (for web content extraction in research tools) {:floki, "~> 0.36", optional: true}, # Memory system store backends (all optional — add to your app's deps to unlock) # {:muninn, "~> 0.4", optional: true}, # {:zvec, "~> 0.2", optional: true}, # {:exqlite, "~> 0.27", optional: true}, # {:duckdbex, "~> 0.3", optional: true}, # Local LLM inference via llama.cpp NIFs (optional — add to your app's deps # to unlock the LlamaCpp provider). optional: true keeps it out of # downstream apps' builds unless they opt in, while still being available # for Nous's own dev/test (e.g. the tagged llamacpp smoke test). {:llama_cpp_ex, "~> 0.8", optional: true}, # Memory system embedding providers (all optional — add to your app's deps to unlock) # {:bumblebee, "~> 0.6", optional: true}, # {:exla, "~> 0.9", optional: true}, # Process execution for command hooks and the Bash tool. A NIF-based # runner is used (over System.cmd/Port) for fine-grained process-tree # control and reliable kill-on-timeout of child processes. `~> 1.0` (not # the tighter `~> 1.0.4`) so downstream apps can pick up 1.x fixes without # waiting on a nous release. {:net_runner, "~> 1.0"}, # Telemetry {:telemetry, "~> 1.2"}, # Note: For Prometheus metrics, users can add {:prom_ex, "~> 1.11"} and {:plug, "~> 1.18"} # to their deps. The Nous.PromEx.Plugin will automatically be available. # Dev/Test {:ex_doc, "~> 0.31", only: :dev, runtime: false}, {:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false}, {:credo, "~> 1.7", only: [:dev, :test], runtime: false}, {:mox, "~> 1.1", only: :test}, # optional (not only: :test) so the `~> 2.1` constraint reaches downstream # resolvers — Nous.PubSub integrates with phoenix_pubsub at runtime (guarded # by Code.ensure_loaded?), and apps that bring their own copy should see a # compatible-version requirement rather than a hidden test-only pin. {:phoenix_pubsub, "~> 2.1", optional: true}, # Bypass = in-test HTTP server for exercising the streaming pipeline # without hitting real LLM endpoints. Available in :dev too so # `bench/http_backend.exs` can spin up an in-process server. {:bypass, "~> 2.1", only: [:dev, :test]}, # Benchee = HTTP backend benchmark (`mix run bench/http_backend.exs`). {:benchee, "~> 1.3", only: :dev} ] end defp docs do [ main: "readme", extras: [ "README.md", "CHANGELOG.md", {"AGENTS.md", title: "AI Agent Guide (AGENTS.md)"}, {"CONTRIBUTING.md", title: "Contributing"}, # Getting Started {"docs/getting-started.md", filename: "getting_started", title: "Getting Started Guide"}, # Examples Overview {"examples/README.md", filename: "examples_overview", title: "Examples Overview"}, {"docs/guides/README.md", filename: "guides_index", title: "All Guides"}, # Production Guides {"docs/guides/skills.md", filename: "skills", title: "Skills Guide"}, {"docs/guides/hooks.md", filename: "hooks", title: "Hooks Guide"}, {"docs/guides/liveview-integration.md", filename: "liveview_integration", title: "Phoenix LiveView Integration"}, {"docs/guides/best_practices.md", filename: "best_practices", title: "Production Best Practices"}, {"docs/guides/tool_development.md", filename: "tool_development", title: "Tool Development Guide"}, {"docs/guides/troubleshooting.md", filename: "troubleshooting", title: "Troubleshooting Guide"}, {"docs/guides/migration_guide.md", filename: "migration_guide", title: "Migration Guide"}, {"docs/guides/evaluation.md", filename: "evaluation", title: "Evaluation Framework Guide"}, {"docs/guides/structured_output.md", filename: "structured_output", title: "Structured Output Guide"}, {"docs/guides/workflows.md", filename: "workflows", title: "Workflow Engine Guide"}, {"docs/guides/memory.md", filename: "memory", title: "Memory System Guide"}, {"docs/guides/context.md", filename: "context", title: "Context & Dependencies Guide"}, {"docs/guides/knowledge_base.md", filename: "knowledge_base", title: "Knowledge Base Guide"}, {"docs/guides/permissions.md", filename: "permissions", title: "Permissions & Guardrails Guide"}, {"docs/guides/observability.md", filename: "observability", title: "Observability & Telemetry Guide"}, # Orchestration & Multi-Agent {"docs/guides/teams.md", filename: "teams", title: "Multi-Agent Teams Guide"}, {"docs/guides/decisions.md", filename: "decisions", title: "Decision Graph Guide"}, {"docs/guides/research.md", filename: "research", title: "Deep Research Guide"}, # Providers & Backends {"docs/guides/providers.md", filename: "providers", title: "Providers Overview"}, {"docs/guides/custom_providers.md", filename: "custom_providers", title: "Custom Providers Guide"}, {"docs/guides/http_backends.md", filename: "http_backends", title: "HTTP Backends Guide"}, {"docs/guides/vertex_ai_setup.md", filename: "vertex_ai_setup", title: "Vertex AI Setup Guide"}, {"docs/guides/fallback.md", filename: "fallback", title: "Fallback Chains Guide"}, # Design Documents {"docs/design/llm_council_design.md", filename: "council_design", title: "LLM Council Design"}, {"docs/benchmarks/http_backend.md", filename: "http_backend_benchmark", title: "HTTP Backend Benchmark"} ], source_ref: "v#{@version}", source_url: @source_url, groups_for_extras: [ "Getting Started": [ "readme.html", "getting_started.html", "examples_overview.html", "guides_index.html" ], "Production Guides": [ "skills.html", "hooks.html", "liveview_integration.html", "best_practices.html", "tool_development.html", "troubleshooting.html", "migration_guide.html", "evaluation.html", "structured_output.html", "memory.html", "context.html", "knowledge_base.html", "permissions.html", "observability.html" ], "Orchestration & Multi-Agent": [ "teams.html", "decisions.html", "research.html", "workflows.html" ], "Providers & Backends": [ "providers.html", "custom_providers.html", "http_backends.html", "vertex_ai_setup.html", "fallback.html" ], Design: [ "council_design.html", "http_backend_benchmark.html" ], Reference: [ "changelog.html", "agents.html", "contributing.html" ] ], groups_for_modules: [ "Core API": [ Nous, Nous.Agent, Nous.Agent.Context, Nous.Agent.Behaviour, Nous.Agent.Callbacks, Nous.ReActAgent, Nous.Transcript, Nous.LLM, Nous.RunContext ], "Agent Implementations": [ Nous.Agents.BasicAgent, Nous.Agents.ReActAgent ], "Agent Execution": [ Nous.AgentRunner, Nous.AgentServer ], "Model Configuration": [ Nous.Model, Nous.ModelDispatcher, Nous.Fallback ], Providers: [ Nous.Provider, Nous.Providers.HTTP, Nous.Providers.HTTP.JSONArrayParser, Nous.Providers.OpenAI, Nous.Providers.OpenAICompatible, Nous.Providers.Anthropic, Nous.Providers.Custom, Nous.Providers.Gemini, Nous.Providers.Mistral, Nous.Providers.LMStudio, Nous.Providers.VertexAI, Nous.Providers.LlamaCpp, Nous.Providers.VLLM, Nous.Providers.SGLang ], "Messages & Streaming": [ Nous.Message, Nous.Message.ContentPart, Nous.Messages, Nous.Messages.OpenAI, Nous.Messages.Anthropic, Nous.Messages.Gemini, Nous.StreamNormalizer, Nous.StreamNormalizer.OpenAI, Nous.StreamNormalizer.Anthropic, Nous.StreamNormalizer.Gemini, Nous.StreamNormalizer.LlamaCpp, Nous.StreamNormalizer.ToolCallAccumulator ], "HTTP Backends": [ Nous.HTTP.Backend, Nous.HTTP.Backend.Req, Nous.HTTP.Backend.Hackney, Nous.HTTP.StreamBackend, Nous.HTTP.StreamBackend.Req, Nous.HTTP.StreamBackend.Hackney ], "Tool System": [ Nous.Tool, Nous.Tool.Behaviour, Nous.Tool.ContextUpdate, Nous.Tool.Validator, Nous.Tool.Registry, Nous.Tool.Schema, Nous.ToolSchema, Nous.ToolExecutor ], "Structured Output": [ Nous.OutputSchema, Nous.OutputSchema.UseMacro, Nous.OutputSchema.Validator ], "Research Tools": [ Nous.Tools.WebFetch, Nous.Tools.Summarize, Nous.Tools.SearchScrape, Nous.Tools.TavilySearch, Nous.Tools.BraveSearch, Nous.Tools.ResearchNotes ], "Coding Tools": [ Nous.Tools.Bash, Nous.Tools.FileRead, Nous.Tools.FileWrite, Nous.Tools.FileEdit, Nous.Tools.FileGlob, Nous.Tools.FileGrep, Nous.Tools.TodoTools, Nous.Tools.PathGuard, Nous.Tools.UrlGuard ], "Utility Tools": [ Nous.Tools.DateTimeTools, Nous.Tools.StringTools, Nous.Tools.ReActTools ], Testing: [ Nous.Tool.Testing ], Templates: [ Nous.PromptTemplate ], "Data Types": [ Nous.Types, Nous.Usage ], Infrastructure: [ Nous.Telemetry, Nous.PromEx.Plugin, Nous.Errors, Nous.Errors.RetryInfo, Nous.Errors.ConfigurationError, Nous.Errors.ModelError, Nous.Errors.ProviderError, Nous.Errors.ToolError, Nous.Errors.ToolTimeout, Nous.Errors.ValidationError, Nous.Errors.UsageLimitExceeded, Nous.Errors.MaxIterationsExceeded, Nous.Errors.ExecutionCancelled ], Evaluation: [ Nous.Eval, Nous.Eval.Suite, Nous.Eval.TestCase, Nous.Eval.Runner, Nous.Eval.Evaluator, Nous.Eval.Evaluators.Contains, Nous.Eval.Evaluators.ExactMatch, Nous.Eval.Evaluators.FuzzyMatch, Nous.Eval.Evaluators.LLMJudge, Nous.Eval.Evaluators.Schema, Nous.Eval.Evaluators.ToolUsage, Nous.Eval.Metrics, Nous.Eval.Metrics.Summary, Nous.Eval.Result, Nous.Eval.SuiteResult, Nous.Eval.YamlLoader, Nous.Eval.Config, Nous.Eval.Reporter, Nous.Eval.Reporter.Console, Nous.Eval.Reporter.Json, Nous.Eval.Optimizer, Nous.Eval.Optimizer.Parameter, Nous.Eval.Optimizer.SearchSpace, Nous.Eval.Optimizer.Strategy, Nous.Eval.Optimizer.Strategies.Bayesian, Nous.Eval.Optimizer.Strategies.GridSearch, Nous.Eval.Optimizer.Strategies.Random ], "Hooks System": [ Nous.Hook, Nous.Hook.Registry, Nous.Hook.Runner ], "Skills System": [ Nous.Skill, Nous.Skill.Loader, Nous.Skill.Registry, Nous.Plugins.Skills, Nous.Skills.CodeReview, Nous.Skills.TestGen, Nous.Skills.Debug, Nous.Skills.Refactor, Nous.Skills.ExplainCode, Nous.Skills.CommitMessage, Nous.Skills.DocGen, Nous.Skills.SecurityScan, Nous.Skills.Architect, Nous.Skills.TaskBreakdown, Nous.Skills.PhoenixLiveView, Nous.Skills.EctoPatterns, Nous.Skills.OtpPatterns, Nous.Skills.ElixirTesting, Nous.Skills.ElixirIdioms, Nous.Skills.PythonFastAPI, Nous.Skills.PythonTesting, Nous.Skills.PythonTyping, Nous.Skills.PythonDataScience, Nous.Skills.PythonSecurity, Nous.Skills.PythonUv ], "Plugin System": [ Nous.Plugin, Nous.Plugins.HumanInTheLoop, Nous.Plugins.InputGuard, Nous.Plugins.InputGuard.Strategy, Nous.Plugins.InputGuard.Result, Nous.Plugins.InputGuard.Policy, Nous.Plugins.InputGuard.Strategies.Pattern, Nous.Plugins.InputGuard.Strategies.LLMJudge, Nous.Plugins.InputGuard.Strategies.Semantic, Nous.Plugins.Memory, Nous.Plugins.SubAgent, Nous.Plugins.Summarization, Nous.Plugins.Decisions, Nous.Plugins.TeamTools ], "Multi-Agent (Teams)": [ Nous.Teams, Nous.Teams.Supervisor, Nous.Teams.Coordinator, Nous.Teams.Role, Nous.Teams.Comms, Nous.Teams.SharedState, Nous.Teams.RateLimiter ], "Decision Graph": [ Nous.Decisions, Nous.Decisions.Node, Nous.Decisions.Edge, Nous.Decisions.ContextBuilder, Nous.Decisions.Store, Nous.Decisions.Store.ETS, Nous.Decisions.Store.DuckDB ], Memory: [ Nous.Memory, Nous.Memory.Entry, Nous.Memory.Scope, Nous.Memory.Store, Nous.Memory.Store.ETS, Nous.Memory.Store.SQLite, Nous.Memory.Store.DuckDB, Nous.Memory.Store.Muninn, Nous.Memory.Store.Zvec, Nous.Memory.Store.Hybrid, Nous.Memory.Scoring, Nous.Memory.Search, Nous.Memory.Tools, Nous.Memory.Embedding, Nous.Memory.Embedding.Bumblebee, Nous.Memory.Embedding.OpenAI, Nous.Memory.Embedding.Local ], PubSub: [ Nous.PubSub, Nous.PubSub.Approval ], Persistence: [ Nous.Persistence ], Supervision: [ Nous.AgentRegistry, Nous.AgentDynamicSupervisor ], Research: [ Nous.Research, Nous.Research.Coordinator, Nous.Research.Planner, Nous.Research.Searcher, Nous.Research.Synthesizer, Nous.Research.Reporter, Nous.Research.Finding, Nous.Research.Report ], Session: [ Nous.Session.Config, Nous.Session.Guardrails ], Permissions: [ Nous.Permissions, Nous.Permissions.Policy ], "Knowledge Base": [ Nous.KnowledgeBase, Nous.KnowledgeBase.Entry, Nous.KnowledgeBase.Document, Nous.KnowledgeBase.Link, Nous.KnowledgeBase.Store, Nous.KnowledgeBase.Store.ETS, Nous.KnowledgeBase.Tools, Nous.KnowledgeBase.Workflows, Nous.KnowledgeBase.HealthReport, Nous.KnowledgeBase.Prompts, Nous.Plugins.KnowledgeBase, Nous.Agents.KnowledgeBaseAgent ], "Workflow Engine": [ Nous.Workflow, Nous.Workflow.Graph, Nous.Workflow.Node, Nous.Workflow.Edge, Nous.Workflow.State, Nous.Workflow.Compiler, Nous.Workflow.Engine, Nous.Workflow.Engine.Executor, Nous.Workflow.Engine.ParallelExecutor, Nous.Workflow.Engine.StateMerger, Nous.Workflow.Mermaid, Nous.Workflow.Trace, Nous.Workflow.Checkpoint, Nous.Workflow.Checkpoint.Store, Nous.Workflow.Checkpoint.ETS, Nous.Workflow.Scratch, Nous.Workflow.Telemetry ], "Mix Tasks": [ Mix.Tasks.Nous.Eval, Mix.Tasks.Nous.Optimize ] ] ] end defp package do [ # Explicit files list — exclude `priv/plts/` (dialyzer artifacts) which # the default Hex package set would otherwise bundle, bloating the # tarball by 100MB+. files: ~w(lib .formatter.exs mix.exs README.md LICENSE CHANGELOG.md AGENTS.md), licenses: ["Apache-2.0"], links: %{ "GitHub" => @source_url, "Changelog" => "#{@source_url}/blob/master/CHANGELOG.md" } ] end defp aliases do [docs: ["docs", ©_images/1]] end defp copy_images(_) do File.mkdir_p!("doc/images") File.cp!("images/header.jpeg", "doc/images/header.jpeg") File.cp!("images/logo.jpeg", "doc/images/logo.jpeg") end end