Omni Tools

Hex.pmLicenseBuild Status

Ready-to-use tools for Omni-powered agents — filesystem, shell, REPL, and web fetch. Built on Omni.

Features

Installation

Add Omni Tools to your dependencies:

def deps do
  [
    {:omni_tools, "~> 0.1"}
  ]
end

Omni Tools depends on omni, which provides the LLM API layer. Configure your provider API keys as described in the Omni README.

The tools

Module What it does
Omni.Tools.FileSystem CRUD over a scoped directory with read-only and flat modes
Omni.Tools.Bash Executes shell commands with timeout and output capture
Omni.Tools.Repl Evaluates Elixir code in a sandboxed peer node
Omni.Tools.WebFetch Fetches URLs, simplifies content for LLM consumption

Each tool is created with new/1 and returns an %Omni.Tool{} struct:

FileSystem

Read, write, patch, list, and delete files within a scoped directory:

# Full access with nested paths
Omni.Tools.FileSystem.new(base_dir: "/data/workspace")

# Read-only, flat (no subdirectories)
Omni.Tools.FileSystem.new(base_dir: "/data/docs", read_only: true, nested: false)

Bash

Execute shell commands in a configured working directory:

Omni.Tools.Bash.new(dir: "/app", timeout: 60_000, env: [{"NODE_ENV", "test"}])

Repl

Evaluate Elixir code in a fresh peer node with optional extensions:

alias Omni.Tools.Repl.Extension

Omni.Tools.Repl.new(
  extensions: [
    {MyApp.ReplExtension, api_key: "sk-..."},
    Extension.new(description: "Req and Jason are available.")
  ]
)

WebFetch

Fetch URLs and extract content appropriate for LLM consumption:

Omni.Tools.WebFetch.new(max_output: 30_000, timeout: 10_000)

Three strategies are always active — GitHub (blob URLs to raw content), Reddit (JSON API to formatted Markdown), and a default catch-all. Custom strategies are prepended and matched first, so they can override or extend the built-ins:

Omni.Tools.WebFetch.new(strategies: [{MyApp.WikiStrategy, []}])

Using tools in a conversation

Pass tools to Omni.generate_text/3 or Omni.stream_text/3 — the tool loop executes uses automatically and feeds results back to the model:

fs   = Omni.Tools.FileSystem.new(base_dir: "/data/workspace")
bash = Omni.Tools.Bash.new(dir: "/data/workspace")

context = Omni.context(
  system: "You are a coding assistant with access to a project workspace.",
  messages: [Omni.message("List all Elixir files and count the lines in each.")],
  tools: [fs, bash]
)

{:ok, response} = Omni.generate_text({:anthropic, "claude-sonnet-4-6"}, context)

Tools work the same way with Omni.Agent — pass them as start options or set them in your agent's init/1 callback:

{:ok, agent} = Omni.Agent.start_link(
  model: {:anthropic, "claude-sonnet-4-6"},
  tools: [fs, bash],
  subscribe: true
)

Configuration

Every tool supports a three-layer configuration merge:

module defaults → application config → explicit opts

Explicit opts to new/1 always win. Application config provides per-environment defaults. Module defaults are sensible out of the box.

# config/runtime.exs
config :omni_tools, Omni.Tools.Bash,
  timeout: 60_000,
  max_output: 100_000

# At call site — :dir is required, :timeout overrides the app config
Omni.Tools.Bash.new(dir: "/app", timeout: 10_000)

No application config is required — every tool works with zero config and sensible defaults.

Documentation

Full API reference is available on HexDocs.

License

This package is open source and released under the Apache-2 License.

© Copyright 2026 Push Code Ltd.