-
Notifications
You must be signed in to change notification settings - Fork 1
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.
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.
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 toinstall!), - is idempotent (calling it twice is a no-op), and
-
fails fast at
install!if an unsupportedruby_llmversion is loaded or the internal API has moved — so it never silently leaks.
See examples/ruby_llm_transparent.rb for a runnable version.
Two things to know before choosing transparent mode:
-
It's a monkeypatch on RubyLLM internals, pinned to a supported version
range. Prefer per-call
DataRedactor.redactunless 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. - 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.
| 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 |
- Integration Guides — Logger, Rails, Rack, Claude/OpenAI.
- Custom Patterns & Name Patterns — teach it your org's internal ID formats and employee names before shipping to a model.
- FAQ — thread-safety and the base64/URL limitation in full.
Guides
Reference
Elsewhere