Skip to main content

Getting started

Install Nexo, configure the harness with safe provider-neutral defaults, and build your first agent in five lines.

Install Nexo, configure the harness in one place, and build your first agent. Defaults are safe and provider-neutral — there is intentionally no hardcoded model.


Installation

Add to your Gemfile:

gem "nexo_ai"

Or install directly:

gem install nexo_ai

In a Rails app, run the install generator to create the conventional layout and an initializer:

rails g nexo:install
      create  app/agents/.keep
      create  app/workflows/.keep
      create  app/skills/.keep
      create  config/initializers/nexo.rb

require "nexo" works in plain Ruby with no Rails loaded.


Configuration

Configure the harness in one place with Nexo.configure:

Nexo.configure do |config|
  config.default_model       = ENV["NEXO_MODEL"] # provider-neutral: no default
  config.default_sandbox     = :virtual          # :virtual | :local | :docker | :apple | a Hash | a Sandbox
  config.default_permissions = :read_only        # :read_only | :auto | :ask | :approve
  config.skills_path         = "app/skills"
  config.concurrency         = :threaded         # :threaded | :async (opt-in fiber offload)
  config.max_in_flight       = 8                 # Nexo.concurrent fan-out bound
  config.buffer_workflow_events = false          # buffer + flush-once workflow events
end

Nexo.config.default_sandbox      # => :virtual
Nexo.config.default_permissions  # => :read_only
Nexo.config.default_model        # => nil unless set

There is deliberately no hardcoded model — you set NEXO_MODEL (or default_model) to any ruby_llm-supported model id.


Build an agent in five lines

Subclass Nexo::Agent, declare the pieces with class macros, and call #prompt. No sandbox, permission, or tool object is wired by hand, and nothing is vendor-specific — the agent runs on any ruby_llm-supported model (set NEXO_MODEL, e.g. a local gemma3:12b via Ollama, or a hosted model):

require "nexo"

class CodeReviewer < Nexo::Agent
  model       ENV.fetch("NEXO_MODEL")   # any ruby_llm model — never a hardcoded vendor default
  sandbox     :local
  permissions :read_only

  instructions "You are a careful code reviewer. Read files and report issues. Do not write files."
end

CodeReviewer.new(cwd: "/path/to/repo").prompt("Review the auth module")

Defaults are safe: an agent with no sandbox/permissions declared gets the in-memory :virtual sandbox and :read_only permissions, so an untrusted model has zero host access until you explicitly opt in.

Safe by default: agents start :virtual + :read_only — an untrusted model has zero host access until you explicitly opt in.


Unregistered models — local tags, self-hosted, brand-new releases

ruby_llm normally validates a model id against its bundled models.json registry and infers the provider from it. A local Ollama tag (gemma3:12b), a self-hosted build, or a model newer than the installed registry isn’t listed there — so declare the provider explicitly and set assume_model_exists to skip the registry lookup:

class LocalReviewer < Nexo::Agent
  model               "gemma3:12b"
  provider            :ollama         # required once the registry lookup is skipped
  assume_model_exists true            # opt out of models.json validation

  instructions "You are a careful code reviewer."
end

Both are class macros with the same reader/writer convention as model. provider is passed straight through to RubyLLM.chat; assume_model_exists defaults to false (registry validation on). Setting assume_model_exists without a provider raises Nexo::ConfigurationErrorruby_llm can’t infer a provider once the lookup is skipped.


Where to next

  • Sandboxes — the four execution environments and hardened defaults.
  • Permissions — the capability gate and the four modes.
  • Examples — runnable scripts including a local-Ollama code reviewer.

Next steps