Skip to main content

LangGraph quickstart

This quickstart creates a deterministic LangGraph agent, registers it with the local Console, and proves that ActionRail blocks a cross-customer refund before the refund tool executes.

It does not require a model API key or a checkout of the ActionRail repository.

LangGraph is ActionRail's current automatic discovery and wrapping adapter. Any Python application can instead use the direct runtime API; additional automatic framework adapters are planned.

1. Install the packages

python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install "actionrail[agents]" actionrail-console

This installs the SDK, LangGraph integration dependencies, the local Console, and the packaged quickstart command. If you are testing unpublished wheels, follow Install local beta wheels instead.

2. Start the Console

actionrail-console --no-open

Leave this terminal running. The Console listens at http://127.0.0.1:8020.

3. Run the quickstart

In a second terminal, activate the same environment and run:

source .venv/bin/activate
actionrail-quickstart

Expected output:

✓ Registered agent …
✓ Connected local source …
✓ ActionRail blocked the cross-customer refund before the tool executed
✓ The value-free decision is visible in Activity
Open http://127.0.0.1:8020/activity

Open http://127.0.0.1:8020/activity to inspect the decision.

Run the poisoned note through a live model

The deterministic replay above is the recommended first run because its result is stable and needs no third-party account. To exercise the same gate with a real agent model, set an Anthropic API key and pass a model ID available to your account:

export ANTHROPIC_API_KEY="…"
actionrail-quickstart --model claude-sonnet-4-6

This mode builds a real model-driven LangGraph loop. The authenticated customer asks for a refund, while an untrusted retrieved support note tells the model to use another customer's valid order ID. If the model proposes that poisoned value, ActionRail checks the order against the authenticated customer ID and blocks the tool call before execution.

The refund tool in this example only appends to an in-memory list; it never contacts a payment provider. A strong model may reject this particular injected note before it proposes a tool call. The command reports that safe model outcome, then submits the same poisoned proposal as a clearly labelled, deterministic runtime challenge. This independently proves that the ActionRail boundary blocks the action even when an upstream model or component does propose it.

Expected output when the model resists the note:

✓ claude-sonnet-4-6 resisted the poisoned support note
✓ Submitted the same poisoned proposal as an independent runtime challenge
✓ ActionRail blocked the cross-customer refund before the tool executed

What the example proves

The script performs the complete integration path:

  1. creates a local SQLite database with two customers’ orders;
  2. registers a new agent and receives its one-time agent key;
  3. creates a SQLite Source;
  4. saves a rule for issue_refund;
  5. wraps the compiled LangGraph agent with enforce();
  6. proposes a refund for an order owned by another customer;
  7. verifies the real refund function was never called;
  8. flushes the reporting queue;
  9. confirms Activity contains the block without private runtime values.

The grounding rule compares the order record with authenticated trusted context:

"match": [
{"column": "customer_id", "ctx": "customer_id"},
{"column": "status", "value": "delivered"},
]

The order exists and is delivered, but its customer_id does not match the caller. Because all match conditions are required, the grounding check fails and the action is blocked.

Use a different Console endpoint

actionrail-quickstart \
--endpoint http://127.0.0.1:8030

Use --database /absolute/path/to/orders.sqlite3 to choose the example database path.

Run it from a repository checkout

The package command above is the normal user path. If you are developing ActionRail itself, the repository keeps a thin wrapper so you can run the same example against editable installs:

python -m pip install -e ".[agents]" -e ./control-plane
python examples/langgraph_quickstart.py

These commands intentionally assume the repository root and are not required for an installed-package user.

Read the implementation

The packaged implementation keeps both the deterministic replay and opt-in live-model graph in one auditable module: actionrail/quickstart.py.

Next, turn the example behavior into a repeatable CI contract with Action Tests, learn the decision mental model, or integrate the SDK into your own agent.

To exercise a real MCP Streamable HTTP verification call locally, continue with the MCP Source example.