Skip to main content

Apply JSON Patches in LangChain

A custom Runnable that calls the Guardian and applies the patches inline.

LangChain runs everything as Runnable chains. We'll add a small custom Runnable that takes the upstream LLM output, sends it to a Trinitite Guardian, and applies any returned RFC 6902 patches before passing the value downstream.

Install

pip install langchain langchain-openai requests jsonpatch

The Runnable

import os
import requests
import jsonpatch
from langchain_core.runnables import RunnableLambda

def trinitite_guardian(guardian: str):
api_key = os.environ["TRINITITE_API_KEY"]
base = os.environ.get("TRINITITE_BASE", "https://api.trinitite.ai")

def _run(state):
resp = requests.post(
f"{base}/v1/chat",
headers={"Authorization": f"Bearer {api_key}"},
json={"guardian": guardian,
"input": [{"role": "assistant", "content": state["text"]}]},
timeout=10,
)
resp.raise_for_status()
body = resp.json()

if body["outcome"] == "passed":
return state

if body["outcome"] == "blocked":
raise RuntimeError(
f"Trinitite blocked output (ledger {body['ledger_id']}): {body.get('reason')}"
)

# corrected — apply the JSON Patch
original = [{"role": "assistant", "content": state["text"]}]
patched = jsonpatch.apply_patch(original, body["corrections"])
state["text"] = patched[0]["content"]
state["trinitite_ledger_id"] = body["ledger_id"]
return state

return RunnableLambda(_run)

Use it in a chain

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_messages(
[("system", "Be helpful and concise."), ("user", "{question}")]
)
llm = ChatOpenAI(model="gpt-4o")

chain = (
prompt
| llm
| RunnableLambda(lambda msg: {"text": msg.content})
| trinitite_guardian("pii-redactor")
)

result = chain.invoke({"question": "Look up the customer record for Jane Doe."})
print(result["text"])
print("Ledger:", result.get("trinitite_ledger_id"))

What you get

  • Zero changes to your prompts.
  • Every output flows through a Guardian; PII spans are surgically removed.
  • A trinitite_ledger_id you can GET /v1/logs/:id to verify.

For agentic chains, drop the same Runnable between the agent's tool-output step and the agent's reasoning step — the Guardian then governs the agent's view of the world, not just the user-facing string.

What's next

Cookbook: SIEM export — stream all those ledger_ids to Splunk / Datadog.

Quickstart — the underlying API.