> ## Documentation Index
> Fetch the complete documentation index at: https://docs.visiqlabs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Ruby SDK Reference

> Local-decision reference for the published Ruby gem binding to the VisIQ governance core — gate_action / gate_retrieval over the same compiled Rust core the Python and TypeScript SDKs use, via Fiddle FFI.

The Ruby gem calls the **same compiled Rust core** the Python and TypeScript SDKs
use, in-process via Ruby's stdlib `Fiddle` FFI — zero runtime gem dependencies.
One core, many languages; every decision is local.

<Note>
  **Scope: local-decision layer only** — bundle auto-refresh, HITL and audit
  streaming are the Governor harness (Python/TypeScript only). This gem makes one
  thing fast and local: the policy DECISION. You fetch the rule bundle and stream
  audit yourself.
</Note>

## Install

The gem bundles the platform-matching compiled core, so there is no separate
native install.

```bash theme={null}
gem install visiq
```

## Acquire a bundle

Every decision is made against a rule bundle you fetch from the control plane and
parse. Fetch it over the [rules API](/rules/action/api-reference):

```bash theme={null}
curl -H "Authorization: Bearer $VISIQ_API_KEY" \
  "$VISIQ_ENDPOINT/rules/bundle?agent_id=support-bot"
```

`VISIQ_ENDPOINT` defaults to `https://api.visiqlabs.com`; set it only for onprem.
Parse the returned JSON into a Hash (`bundle`) and pass it in.

## Govern a tool call

`Visiq.gate_action(bundle, tool_name:, args:, agent_id:)` decides one tool/action
call. Inspect `decision["allowed"]`; on a `mask` verdict apply
`decision["action"]["argRedactionRules"]` to the args before running the tool.

```ruby theme={null}
# guide:begin
decision = Visiq.gate_action(bundle, tool_name: "wire_transfer", args: { "amount" => 999 }, agent_id: "sdk-agent")
puts "allowed=#{decision['allowed']}"
# guide:end
```

This exact snippet is executed as a proof (`guide_example.rb`) against a bundle
copied verbatim from the oracle-stamped conformance corpus: the deny fixture
blocks (`allowed=false`), the permit fixture passes (`allowed=true`).

## Govern a retrieval

`Visiq.gate_retrieval(bundle, resource_metadata:, agent_id:)` decides one
retrieval. Inspect `decision["retrieval"]["action"]` — drop on `deny`/`escalate`,
redact via `decision["retrieval"]["redactionRules"]` — before content reaches the
model.

```ruby theme={null}
decision = Visiq.gate_retrieval(bundle, resource_metadata: { "classification" => "restricted" }, agent_id: "sdk-agent")
puts "action=#{decision['retrieval']['action']}"
```

## Fail mode

A HARNESS-internal failure — the compiled core can't load, or an FFI error — is
routed by `VISIQ_FAIL_MODE` (owner G001 rescope): `open` (**default**) returns a
permit-equivalent decision plus a loud stderr report so a VisIQ packaging bug
never disrupts the agent; `closed` raises a fail-closed error. A real rule
**deny** always blocks regardless of fail mode.

```bash theme={null}
VISIQ_FAIL_MODE=closed   # strict: a core-load/FFI failure denies instead of proceeding
```

## Override the core library

The gem loads its bundled core. Point it at a specific library with
`VISIQ_CORE_LIB` (an absolute path), matching the Go and Java bindings.

```bash theme={null}
VISIQ_CORE_LIB=/opt/visiq/libvisiq_core.dylib
```

## Next steps

<CardGroup cols={2}>
  <Card title="Java Reference" icon="book" href="/reference-java">
    The Java binding — `gateAction` over the same core.
  </Card>

  <Card title="Python Reference" icon="book" href="/reference-python">
    The full Python harness — Governor, gates, and audit streaming.
  </Card>
</CardGroup>
