LangGraph builds stateful, multi-actor agent graphs where state accumulates across nodes and edges. Cognisafe monitors every LLM call within your graph — detecting prompt injection at any node, tracing how compromised state propagates downstream, and flagging PII that surfaces in tool outputs.
Why this matters
In a stateless agent, an injection affects one turn. In LangGraph, injected content is written to graph state and flows through every downstream node until the graph terminates. One malicious input at a retrieval node can corrupt an entire agentic workflow.
Injection via retrieval nodes
A retrieval node fetches external documents containing embedded instructions. These enter the graph state and influence every subsequent node — planner, executor, and responder alike.
PII surfacing from tool calls
A tool node queries a database and returns records containing personal data. A downstream summariser includes PII verbatim in its LLM call — which is logged and may be returned to the user.
System prompt leakage via graph introspection
A node in your graph is tricked into revealing its system message or the graph's routing logic — exposing your application architecture and decision rules.
Conditional branch hijacking
Injected content manipulates the LLM's routing decision, causing the graph to take a privileged branch (e.g. 'execute' instead of 'plan') that the attacker shouldn't have access to.
Quickstart
Cognisafe wraps the underlying LLM provider calls LangGraph makes — no changes to your graph topology, state schema, or node functions.
pip install cognisafe
import cognisafe
from langgraph.graph import StateGraph
cognisafe.configure(
api_key="csk_...", # from cognisafe.uk/dashboard/settings
project_id="my-langgraph",
)
cognisafe.patch_openai() # wraps LangChain's OpenAI calls
# or: cognisafe.patch_anthropic()
# Define and compile your graph as normal:
graph = StateGraph(AgentState)
graph.add_node("retrieve", retrieve_node)
graph.add_node("plan", plan_node)
graph.add_node("execute", execute_node)
app = graph.compile()Set agent_name inside each node function to see exactly which node triggered a safety event:
from langchain_openai import ChatOpenAI
import cognisafe
def plan_node(state: AgentState):
# Tag this node so the dashboard shows "plan" vs "execute"
cognisafe.configure(
api_key="csk_...",
project_id="my-langgraph",
agent_name="plan",
)
llm = ChatOpenAI(model="gpt-4o")
response = llm.invoke(state["messages"])
return {"messages": [response]}Advanced setup
Use a different agent tag per node so your dashboard shows the exact entry point for every threat — whether it arrived via retrieval, planning, or execution.
import cognisafe
from langchain_openai import ChatOpenAI
def get_llm(node_name: str) -> ChatOpenAI:
"""Return a monitored LLM tagged for this graph node."""
cognisafe.configure(
api_key="csk_...",
project_id="research-graph",
agent_name=node_name, # "retrieve", "plan", "execute", "respond"
)
cognisafe.patch_openai()
return ChatOpenAI(model="gpt-4o")
def retrieve_node(state):
llm = get_llm("retrieve")
...
def execute_node(state):
llm = get_llm("execute")
...Every flagged event shows which graph node triggered it — retriever, planner, or executor — with full prompt and scorer rationale.
Timestamps on every node call let you trace how injected content moves through your graph from entry to exit.
LLM calls made within tool functions are captured too — not just the top-level graph calls.
All four OWASP-mapped scorers: jailbreak (LLM01), PII (LLM02), content safety (LLM05), system prompt leakage (LLM07).
Free tier included. No credit card. Start monitoring in 5 minutes.