Skip to content

RubyLLM Integration

daniele frisanco edited this page Jul 5, 2026 · 1 revision

⭐ RubyLLM Integration

RubyLLM is a unified Ruby client for every major LLM provider — Anthropic, OpenAI, Gemini, Bedrock, and more — behind one API. Anything you send a model is exactly the kind of free text that leaks secrets and PII: pasted logs, stack traces, config snippets, customer messages, tool output an agent feeds back in. data_redactor scrubs all of it before it leaves your process.

There are two ways to use them together. Start with per-call — it's explicit and needs no monkeypatch. Reach for transparent mode when you want every outbound request scrubbed with no per-call ceremony.

Per-call (recommended)

RubyLLM takes plain strings, so wrap each prompt — and any with_instructions system prompt — in DataRedactor.redact before passing it to ask. No extra integration required:

require "ruby_llm"
require "data_redactor"

chat = RubyLLM.chat(model: "claude-opus-4-8")
chat.with_instructions(DataRedactor.redact("You are a support agent for ACME Corp."))

user_input = "My card is 4111 1111 1111 1111 and my email is alice@example.com"
chat.ask(DataRedactor.redact(user_input))
# the model receives: "My card is [REDACTED] and my email is [REDACTED]"

This is the recommended approach: explicit, no patched internals, and every filter option (only:, except:, placeholder:) is right there at the call site.

See examples/ruby_llm.rb for a runnable version.

Transparent mode — redact every request automatically

If you'd rather redact every outbound request — including the system prompt, tool definitions, and any file contents or shell-command output an agent feeds back as a tool result — opt into the monkeypatch:

require "ruby_llm"
require "data_redactor/integrations/ruby_llm"

DataRedactor::Integrations::RubyLLM.install!   # once, at boot

chat = RubyLLM.chat(model: "claude-opus-4-8")
chat.ask("my card is 4111111111111111")        # sent as "my card is [REDACTED]"

install! prepends a patch onto RubyLLM::Protocol#render — the one point where every provider has assembled its final request — and deep-redacts the payload before it's posted. It:

  • forwards only: / except: / placeholder: (pass them to install!),
  • is idempotent (calling it twice is a no-op), and
  • fails fast at install! if an unsupported ruby_llm version is loaded or the internal API has moved — so it never silently leaks.

See examples/ruby_llm_transparent.rb for a runnable version.

Caveats (by design)

Two things to know before choosing transparent mode:

  1. It's a monkeypatch on RubyLLM internals, pinned to a supported version range. Prefer per-call DataRedactor.redact unless you specifically need transparency. RubyLLM does not yet expose a public request hook — crmne/ruby_llm#765 tracks the connection-middleware hook that would let us drop the patch. When that lands, this integration will move onto it.
  2. Base64 attachments (PDFs, images, audio sent inline) and URL-referenced files are not redacted — the sensitive bytes are encoded or remote, so the patterns cannot see them. This is the same base64 / URL limitation that applies everywhere in the gem.

Which mode should I use?

Per-call Transparent (install!)
Setup none one line at boot
Coverage prompts you wrap every request, incl. system prompt & tool results
Patches internals no yes (pinned version range)
Per-call filter overrides trivial via install! defaults
Recommended when you control the call sites agents / many call sites, want a safety net

See also

Clone this wiki locally