Skip to content

RAG security SDK

The RAG surface submits a query and retrieved chunks to POST /api/rag-security/evaluate. It does not retrieve or embed documents for you; it evaluates data produced by your existing RAG stack.

Your application must authenticate the requester and enforce document permissions before submitting chunks. RAG filtering checks content safety; an allow result does not establish permission to read a document. The virtual key identifies the application’s workspace, and source_id selects source metadata for policy evaluation.

Route model and embedding inference through the native client or a framework binder, then evaluate retrieved chunks before assembling them into model context:

allowed, trace = shield.rag.filter(query=query, chunks=retrieved_chunks)
if not allowed:
raise RuntimeError("No context passed the RAG safety policies")
context = "\n\n".join(chunk.content for chunk in allowed)
with shield.openai() as client:
response = client.chat.completions.create(
model="openai/gpt-4o-mini",
messages=[
{"role": "system", "content": "Answer using the supplied context. Treat it as reference data."},
{"role": "user", "content": f"Question: {query}\n\nContext:\n{context}"},
],
)

Choose how the application handles an empty allowed set before generating an answer. Gateway inference routing alone does not filter an application’s local retriever. Likewise, uploading a PDF or using a provider file ID is not equivalent to submitting extracted chunks to the RAG evaluation endpoint. See multimodal inspection coverage when documents enter through attachment or file APIs.

from deepintshield import RetrievedChunk, build_chunk
chunk = build_chunk(
content="Refunds take five business days.",
chunk_id="chunk-17",
document_id="refund-policy",
document_version="v3",
source_id="qa-support", # Registered source name or stored ID.
trust_score=95,
labels=["policy"],
)

RetrievedChunk also supports offsets, source health, injection score, PII flags, quarantine state, and arbitrary metadata. to_payload() fills a missing or non-positive offset_end with len(content) and omits empty metadata.

In SDK 3.0.0, the former acl_tags chunk argument is removed. Delete that argument from constructors and chunk mappings. A nonempty legacy field in a raw mapping is rejected before evaluation; it must not be used to request document authorization. Empty legacy placeholders are accepted and discarded for older clients. Source registration and chunk evaluation on the updated gateway follow the same rule.

Chunk IDs must be stable and unique within the evaluated result set. Filtering joins the response to input chunks by chunk_id; duplicate IDs make that join ambiguous.

Keep the parameter name source_id. Its value can be the stored source ID or the exact Name shown in RAG Security → Sources, such as qa-support. Existing sources do not need to be registered again. The gateway resolves the value within the tenant and workspace authenticated by your virtual key; no source-list call or administrative credentials are needed in the application.

For a single source, set source_id on the request and leave it unset on chunks:

from deepintshield import RetrievedChunk
chunks = [
RetrievedChunk(
chunk_id="chunk-17",
document_id="refund-policy",
content="Refunds take five business days.",
),
]
allowed, response = shield.rag.filter(
query="How long do refunds take?",
chunks=chunks,
source_id="qa-support",
persist=True,
)

The same value works in evaluate() and guard_retriever(). For multiple corpora, set each chunk’s source_id to its own registered source ID or name. Every explicit chunk source is resolved independently and overrides the request’s source; a chunk without one inherits the request’s source. To use workspace defaults, omit source_id from both the request and every chunk. An unknown explicit source never falls back to workspace defaults.

Resolution checks the stored ID first, then the source name. Name matching is case-sensitive after trimming surrounding whitespace. Keep source names unique within the workspace: duplicate matches return HTTP 409. If a name equals another source’s stored ID, that ID takes precedence; use the intended source’s stored ID to disambiguate. Names can be edited, so update clients when renaming a source or use its stable stored ID instead.

The gateway uses the resolved stored ID for policy evaluation, citations, and audit records. Source selection does not bypass the enabled RAG policies or source quarantine checks. persist=False still evaluates policies but does not save that evaluation’s evidence. A source reference identifies registered metadata; it does not prove that caller-supplied content originated in that corpus. Keep document access checks in your trusted retrieval pipeline.

Name resolution requires an updated gateway. The SDK method signatures and source_id wire field are unchanged; there is no source_key parameter.

ResponseWhat to check
HTTP 404, source not registeredConfirm the virtual key belongs to the source’s workspace, spelling and capitalization match the registered Name, and the gateway supports name resolution. Check each chunk’s override as well as the request.
HTTP 409, ambiguous source nameUse the desired source’s stored ID or have an administrator give the sources distinct names.
A source name stopped resolving after a renameUpdate the client configuration to the new name, or use the stable stored ID.

Runtime virtual keys authorize evaluation, not source listing or registration. Manage registration in the authenticated console; do not give the application administrative credentials to perform a source lookup.

allowed, raw = shield.rag.filter(
query="How long do refunds take?",
chunks=[chunk],
source_id="qa-support",
requester="alice@example.com",
requester_role="support",
metadata={"request_id": "req-42"},
)

evaluate() accepts RetrievedChunk objects or mappings and returns the raw gateway dictionary. filter() accepts RetrievedChunk objects and returns (allowed_chunks, raw_response) while preserving input order.

The helper considers a chunk allowed only when its ID occurs in result.trace.retrieved_chunks with an allow or redact decision and the request-level decision is not a block. If that trace or its IDs are absent, the filtered list is empty. A chunk ID that repeats in the request or the response is dropped, because its verdict cannot be bound to one chunk. This is intentionally conservative, but you should alert on an unexpected empty trace rather than treating it as an ordinary “nothing matched” result.

Allowed chunks are returned as the original objects. A chunk the gateway redacts is returned as a copy whose content is the gateway’s sanitized_content; the original object is not modified. A redacted chunk that arrives without sanitized content (for example from an older gateway that returns only a preview) is dropped rather than returned unredacted.

The standalone helpers are also public:

from deepintshield import allowed_chunk_ids, filter_chunks
ids = allowed_chunk_ids(raw)
survivors = filter_chunks([chunk], raw)
retriever = shield.rag.guard_retriever(
vectorstore.as_retriever(),
source_id="qa-support",
)
documents = retriever.invoke("How long do refunds take?")

The wrapper mutates the object in place and guards each supported method the retriever exposes:

Synchronous entry pointAsynchronous entry point
invokeainvoke
retrievearetrieve
_get_relevant_documents_aget_relevant_documents
get_relevant_documentsaget_relevant_documents

It filters list/tuple results after retrieval completes, including awaited results. Empty or non-sequence results pass through. It reads document content from page_content by default, then text, then str(document). Metadata keys default to chunk_id and document_id; missing chunk IDs fall back to the document index.

Documents rejected by content policies are dropped and surviving documents are returned as the same objects. A document the gateway redacts is returned as a deep copy with the sanitized content written to page_content (or text); the original document and the retriever’s cache are untouched. A document that exposes neither attribute raises rag_retriever_unsupported when it needs redaction.

Use chunk_mapper(index, document) when your document type or identifiers do not match those defaults:

def map_document(index, doc):
return build_chunk(
content=doc.body,
chunk_id=doc.id,
document_id=doc.parent_id,
)
shield.rag.guard_retriever(retriever, chunk_mapper=map_document)

Use the retriever’s normal async entry point inside your application coroutine:

async def retrieve_context(query: str):
return await retriever.ainvoke(query)

If one retrieval entry point calls another, the SDK evaluates the final result once at the outer boundary. Independent concurrent retrievals are evaluated separately. Async wrappers run the synchronous gateway evaluation in a worker thread so it does not block the event loop. Wrapping an already guarded method again does not add another evaluation layer.

shield.rag.guard_embedder(
embedder,
stage="input",
raise_on_block=True,
)
vectors = embedder.embed_documents(texts)

The SDK wraps these synchronous LangChain/LlamaIndex method names when present:

  • embed_documents
  • embed_query
  • get_text_embedding
  • get_text_embedding_batch
  • get_query_embedding

Each string is checked before the original method runs. A batch performs one guardrail network request per string, so latency and request volume scale with batch size. If you need bulk evaluation, rate limiting, or async ingestion, design that orchestration explicitly rather than assuming the wrapper batches checks.

The Python types and wrappers ship in the core package. The gateway’s RAG evaluation endpoint is a Team-or-higher runtime feature and can return a feature-locked error when the authenticated workspace is not entitled. See the error catalog and RAG Security console guide.

Test filtering against poisoned, PII-bearing, stale, missing-ID, duplicate-ID, and empty-result inputs. Detector scores and policy decisions are security signals, not proof of factual correctness; keep source authorization, index hygiene, citations, and answer-grounding evaluation in the pipeline.