Omni.Tools (Omni Tools v0.1.0)

Copy Markdown View Source

License

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

Omni Tools is a small set of reference Omni.Tool implementations that ship ready-to-use and serve as worked examples of how to build tools for LLMs. Each tool validates configuration at construction time and works with any Omni provider that supports tool use.

Installation

Add Omni Tools to your dependencies:

{:omni_tools, "~> 0.1"}

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

The tools

ModuleWhat it does
Omni.Tools.FileSystemCRUD over a scoped directory with read-only and flat modes
Omni.Tools.BashExecutes shell commands with timeout and output capture
Omni.Tools.ReplEvaluates Elixir code in a sandboxed peer node
Omni.Tools.WebFetchFetches URLs, simplifies content for LLM consumption

Each tool is created with new/1 and returns an %Omni.Tool{} struct ready to pass into an Omni context:

fs   = Omni.Tools.FileSystem.new(base_dir: "/data/workspace")
bash = Omni.Tools.Bash.new(dir: "/app")
repl = Omni.Tools.Repl.new()
web  = Omni.Tools.WebFetch.new()

FileSystem

Read, write, patch, list, and delete files within a scoped directory. Configuration controls read-only access and whether subdirectories are allowed:

# 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)

See Omni.Tools.FileSystem for all options. The underlying operations are also available standalone via Omni.Tools.FileSystem.FS.

Bash

Executes shell commands in a configured working directory with environment variables, timeout, and output truncation:

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

See Omni.Tools.Bash for all options. The command runner is also available standalone via Omni.Tools.Bash.Runner.

Repl

Evaluates Elixir code in a fresh peer node — clean slate per execution, with IO capture and configurable extensions:

alias Omni.Tools.Repl.Extension

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

See Omni.Tools.Repl for all options and Omni.Tools.Repl.Extension for the extension API.

WebFetch

Fetches one or more URLs and extracts content appropriate for LLM consumption — HTML to Markdown, JSON to pretty-printed, plain text passthrough:

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, []}])

See Omni.Tools.WebFetch for all options and Omni.Tools.WebFetch.Strategy for the strategy behaviour.

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.

Writing custom tools

These tools implement the Omni.Tool behaviour from the omni package. To build your own, see Omni.Tool — or read any of the tools in this package as worked examples.