Skip to main content
This guide adds ReasonBlocks to a LangChain 1.0 agent. By the end, your agent has step scoring, server-side monitor evaluation, and E-trace injection on every run, and each run streams to the ReasonBlocks dashboard.
ReasonBlocks supports three agent frameworks: LangChain, the OpenAI Agents SDK, and the Claude Agent SDK / Claude Messages API. The full steering pipeline (FSM + monitors + E-traces + model routing) ships as a LangChain middleware, so this quickstart is LangChain-shaped. For the other two, see the OpenAI Agents guide and the Claude Agent SDK guide — both ship telemetry hooks (where applicable) and the codebase memory tool factories.
1

Install the SDK

Install ReasonBlocks from PyPI. Python 3.10 or later is required.
pip install reasonblocks
langchain>=1.0 and httpx>=0.27 are installed automatically.
2

Get your API key

Log in to the ReasonBlocks dashboard and copy your API key from the Quickstart page. Keys start with rb_live_.The SDK does not read environment variables for the key — your code passes it to the constructor explicitly. Storing it in an environment variable is still the recommended pattern; just read it yourself:
export REASONBLOCKS_API_KEY=rb_live_...
The dashboard’s Quickstart page also shows your org_id and project_id next to a copy-pasteable snippet.
3

Initialize the client

Import ReasonBlocks and pass the API key. The client is reusable across runs — create it once at startup, then call rb.middleware() once per agent invocation.
import os
from reasonblocks import ReasonBlocks

rb = ReasonBlocks(api_key=os.environ["REASONBLOCKS_API_KEY"])
4

Add the middleware to your agent

Pass rb.middleware() in the middleware list when you create your agent.
from langchain.agents import create_agent

agent = create_agent(
    model="anthropic:claude-haiku-4-5-20251001",
    tools=[...],
    system_prompt="You are a senior software engineer.",
    middleware=[rb.middleware()],
)
The middleware hooks four points in the LangChain agent loop:
  • before_agent — emits the run_start telemetry event.
  • before_model — scores the last step, advances the FSM, evaluates monitors server-side, and queues E-trace injections.
  • wrap_model_call — overrides the model if routing applies, renders queued injections into the system message, and records token usage.
  • after_agent — emits the run_finish telemetry event.
5

Tag the run for the dashboard

rb.middleware() accepts identifying metadata. All fields are optional.
agent = create_agent(
    model="anthropic:claude-haiku-4-5-20251001",
    tools=[...],
    system_prompt="You are a senior software engineer.",
    middleware=[rb.middleware(
        run_id="my-run-1",                # auto-generated if omitted
        agent_name="bugfixer",            # free-form filter key
        task="fix the TypeError",
        framework="langchain",
        model="claude-haiku-4-5-20251001",
        codebase_id="myrepo@sha:abc123",
        org_id="default",                 # uuid; "default" if omitted
        project_id="default",             # uuid; "default" if omitted
        metadata={"experiment": "A"},     # free-form extra tags
    )],
)
These values land on the monitor_runs row in rb-api and surface in the dashboard’s Runs table.
When your API key is a per-customer rb_live_* key bound to an org, rb-api overrides org_id and project_id with the key’s authoritative scope. Most callers can leave them at "default".
6

Run your agent

Invoke the agent normally.
result = agent.invoke({
    "messages": [("user", "There's a TypeError in the request handler. Find and fix it.")]
})
After the run completes, open the dashboard to see the scored steps, FSM transitions, and any monitor signals or E-trace injections that fired.

Complete example

A minimal end-to-end script using a LangChain agent with mock tools:
import os
from langchain.agents import create_agent
from langchain_anthropic import ChatAnthropic
from langchain_core.tools import tool
from reasonblocks import ReasonBlocks

rb = ReasonBlocks(api_key=os.environ["REASONBLOCKS_API_KEY"])

@tool
def search_codebase(query: str) -> str:
    """Search the codebase for files matching a query."""
    return f"No results for {query!r}"

model = ChatAnthropic(model="claude-haiku-4-5-20251001", max_tokens=1024)

# Use the middleware as a context manager so the run is finished and the
# streaming connection is released on exit.
with rb.middleware(agent_name="bugfixer", task="investigate the TypeError") as mw:
    agent = create_agent(
        model=model,
        tools=[search_codebase],
        system_prompt="You are a senior software engineer.",
        middleware=[mw],
    )

    result = agent.invoke({
        "messages": [("user", "There's a TypeError in the request handler. Find it.")]
    })

Next steps

Installation options

Constructor parameters and self-hosted base URLs.

How it works

The middleware lifecycle in detail.

Model routing

Map FSM states to model identifiers.

LangChain guide

Full integration walkthrough.