Verifiable decisions for LangGraph agents.
Keep LangGraph responsible for graph state, checkpoints and execution. Use LoopGrid Core for signed decisions, exact-action policy checks and human-review evidence. The trusted host still owns reviewer identity, external side effects and observed outcomes.
loopgrid-langgraph==0.1.0 · Python 3.10+ · validated with LangGraph 1.2.14 · LoopGrid Core 0.8.1-design-partner.
Resume is not approval. An interrupted LangGraph node may restart; the guard checks signed Core policy, review and prior tool requests before allowing a consequential callback.
Install the released Python integration.
python -m pip install loopgrid-langgraph==0.1.0
The package provides native StateGraph decision, guarded-execution and verification nodes via LangGraphBridge. It requires Python 3.10+ and declares langgraph>=1.2.12,<2 and httpx>=0.27,<1. The persistent SQLite test optionally installs langgraph-checkpoint-sqlite. The package is community-built, not an officially endorsed LangGraph extension.
Bind one proposed action to Core, then guard the native node.
from typing import TypedDict
from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.types import Command
from loopgrid_langgraph import CoreClient, LangGraphBridge
import os
class State(TypedDict, total=False):
amount: int
operation_id: str
loopgrid: dict
loopgrid_tool_result: dict
loopgrid_verification: dict
core = CoreClient(
base_url="http://127.0.0.1:8000", # loopback only; use HTTPS remotely
workspace_id="YOUR_TEST_WORKSPACE",
service_key=os.environ["LOOPGRID_SERVICE_KEY"],
)
bridge = LangGraphBridge(core, agent_id="refund-agent")
arguments = lambda s: {"amount": s["amount"], "currency": "USD"}
propose = bridge.make_decision_node(
tool="refund", policy_id="refund-policy", arguments=arguments,
authority=lambda s: {"limit_usd": 1500, "scope": ["refund:create"]},
model=lambda s: {"name": "host-supplied-model-identity"},
context=lambda s: {"prompt_version": "refund-v1"},
operation_id=lambda s: s["operation_id"],
)
# Only synthetic local data. No payment or refund API is called.
execute = bridge.make_guarded_node(
tool="refund", arguments=arguments,
callback=lambda args: {"sandbox": True, "amount": args["amount"]},
)
builder = StateGraph(State)
builder.add_node("propose", propose)
builder.add_node("execute", execute)
builder.add_node("verify", bridge.make_verify_node())
builder.add_edge(START, "propose")
builder.add_edge("propose", "execute")
builder.add_edge("execute", "verify")
builder.add_edge("verify", END)
graph = builder.compile(checkpointer=InMemorySaver())
cfg = {"configurable": {"thread_id": "refund-thread-unique-01"}}
result = graph.invoke({"amount": 75, "operation_id": "refund-op-unique-01"}, cfg)
# When policy requires approval, result includes an interrupt.
# ONLY the authenticated host requests approval through Core's review API.
# Graph resume text is never a human approval credential.
# After authorized review is recorded against the SAME decision:
# result = graph.invoke(Command(resume="continue"), cfg)This is a synthetic refund example, not a payment application. Create a disposable workspace, configure a real Core policy and supply a scoped service credential. InMemorySaver is for tests; use a durable supported checkpointer and a host-provided dispatch lease in production.
Evidence follows the consequential action, not the graph's narration.
Application-owned operation and thread identifiers, agent/model context, delegated authority, target tool and exact proposed arguments are bound to the Core decision. Reusing a decision with changed metadata fails closed.
Only host-observed model output may be recorded as model_completed. A model identifier or graph callback does not prove a model invocation.
Core evaluates the actual active versioned policy, including policy digest and action-input commitment. A review-required decision remains blocked until an authenticated Core review is present.
The native guard checks signed policy, review, argument binding and previous attempts. tool_requested is recorded before the synchronous callback; failure after reservation requires reconciliation, not blind replay.
Callback receipts are distinct from an authoritative external outcome. The trusted host may append outcome_observed only after independently checking the downstream system.
Core verifies workspace-scoped signed evidence. For separate offline verification, pin a trusted signer key and validate the exported evidence format using the independent verifier.
make_decision_node(), make_guarded_node() and make_verify_node() return native graph nodes. LoopGridGraphCallback is for non-authorizing interrupt/resume observations only.
Checkpoint restoration must not repeat a consequential action.
interrupt and Command(resume=...) coordinate the graph, but never serve as proof of approval.tool_requested is a conservative no-replay barrier. Reconcile against the downstream system before any new intentional attempt.The integration does not guarantee globally exactly-once business effects. In multi-worker deployments, use a host-controlled atomic distributed lease or outbox. The included SQLite lease is a single-host reference, not a distributed lock.
Keep checkpoints, credentials and commitments under application control.
The loopgrid graph scope avoids duplicating the raw proposed tool-argument map. Other host state, model outputs, callback results and checkpoint stores may still contain sensitive data; deploy retention, encryption and access controls accordingly. Core redacted fields use typed SHA-256 commitments, which are checked rather than ignored on replay.
dispatch_lease=... and require_dispatch_lease=True with a production-grade host implementation.Tested against native LangGraph and LoopGrid Core.
StateGraph interrupt/resume and persistent SqliteSaver restart/recovery succeeded; no duplicate synthetic execution.evidence_complete, and signed workspace verification with zero failures.These tests use controlled sandbox actions and do not constitute certification for real-money workflows. Signed workspace verification is not itself a claim that an independently exported bundle was verified offline in the same run. See the validation record ↗ and integration contract ↗ for boundaries.
LangGraph orchestrates. Your host authorizes. LoopGrid records evidence.
Do not equate agent text, graph resume values, successful callbacks or signed histories with a verified transfer or refund. Keep authentication, real external action execution, downstream reconciliation, signer trust and checkpoint privacy under independent application control.
Source: GitHub ↗ · Security notes ↗ · PyPI ↗.
Keep durable graph execution. Verify consequential decisions.
Begin with a disposable Core workspace, a synthetic guarded tool and a real application policy. Add authenticated review and authoritative external receipts as the integration moves beyond testing.