cd /news/developer-tools/tracesage-see-inside-your-langgraph-… · home topics developer-tools article
[ARTICLE · art-29584] src=dev.to ↗ pub= topic=developer-tools verified=true sentiment=↑ positive

tracesage: See Inside Your LangGraph Agents

A developer built tracesage, an open-source local-first observability tool for LangChain and LangGraph agents. It hooks into LangChain's callback stream to capture events, stores them locally, and renders an interactive graph and timeline UI in the browser in real time. The tool requires only two lines of code to integrate and runs entirely on the user's laptop with no external infrastructure.

read7 min views1 publishedJun 16, 2026

Open-source LangChain/LangGraph tracing — drop in two lines, watch your agents run live in your browser.

If you've built anything non-trivial with LangChain or LangGraph — a multi-agent supervisor, a RAG pipeline, a tool-using ReAct loop — you know the feeling. It works on the happy path, then a real query comes in and… something goes wrong. But what?

Which agent actually ran? In what order?

Did the model call the tool you expected, or hallucinate a different one?

How many tokens did that one request burn?

Where did the error come from — your tool, the model, or the orchestration?

The usual answer is a wall of print()

statements and verbose=True

logs you scroll through at 2 a.m. There are great hosted tracing platforms, but they mean signing up, shipping your prompts to a third party, and wiring up an SDK.

I wanted something I could pip install

and have running in ten seconds, entirely on my laptop. So I built tracesage.

tracesage is a local-first observability tool for LangChain & LangGraph agents. It hooks into LangChain's callback stream, captures every chain / tool / LLM / retriever event, stores it locally (SQLite + gzipped blobs), and renders it as an interactive graph + timeline UI in your browser — in real time.

🚀 Two-line integration. One callback added to your existing invoke

/ainvoke

.

🧰 Zero infrastructure. No Docker, no Postgres, no external service. Just pip install

.

🔒 Never crashes your app. The callback handler is wrapped to never raise — tracing can fail, your agent keeps running.

🗺️ MCP-aware. Tools loaded from MCP servers are attributed back to their server, so you can see which tools came from where.

🧪 Testable. A pytest

fixture lets you assert "did my agent call search

?" in CI.

📦 MIT licensed, runs in a single Python process.

Links:

Examples gallery (30 before/after apps): in the repo under examples/showcase/

Before we write any code, see what we're aiming for:

pip install "tracesage[langchain]"
tracesage demo            # seeds a sample trace and opens the UI

Your browser opens to http://localhost:7842/ui

and you're looking at a live agent topology.

Let's build a tiny but real LangGraph agent and wire tracesage into it. You'll need Python 3.11+ and an LLM provider key (we'll use OpenAI; Anthropic or any LangChain model works identically — tracesage is provider-agnostic).

pip install "tracesage[langchain]" langgraph langchain-openai
export OPENAI_API_KEY=sk-...

before.py

— a standard LangGraph ReAct agent with two tools:

import asyncio
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent

@tool
def get_weather(city: str) -> str:
    """Return the current weather for a city."""
    return f"It's 22°C and sunny in {city}."

@tool
def to_fahrenheit(celsius: float) -> float:
    """Convert a temperature in Celsius to Fahrenheit."""
    return celsius * 9 / 5 + 32

agent = create_react_agent(
    ChatOpenAI(model="gpt-4o-mini", temperature=0),
    tools=[get_weather, to_fahrenheit],
)

async def main() -> None:
    result = await agent.ainvoke(
        {"messages": [{"role": "user",
                       "content": "What's the weather in Paris, in Fahrenheit?"}]}
    )
    print(result["messages"][-1].content)

asyncio.run(main())

Run it and you get an answer. But you have no idea how it got there — did it call get_weather

then to_fahrenheit

? Did it loop? How many model calls?

after.py

— the only difference is creating a tracer and passing its handler:

import asyncio
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent

from tracesage import TraceSage          # 1️⃣ import

@tool
def get_weather(city: str) -> str:
    """Return the current weather for a city."""
    return f"It's 22°C and sunny in {city}."

@tool
def to_fahrenheit(celsius: float) -> float:
    """Convert a temperature in Celsius to Fahrenheit."""
    return celsius * 9 / 5 + 32

agent = create_react_agent(
    ChatOpenAI(model="gpt-4o-mini", temperature=0),
    tools=[get_weather, to_fahrenheit],
)

async def main() -> None:
    tracer = await TraceSage.create()    # 2️⃣ start tracesage (UI on :7842)

    result = await agent.ainvoke(
        {"messages": [{"role": "user",
                       "content": "What's the weather in Paris, in Fahrenheit?"}]},
        config={"callbacks": [tracer.handler]},   # 3️⃣ the one line you add
    )
    print(result["messages"][-1].content)

    input("Trace ready at http://localhost:7842/ui — press Enter to exit.")
    await tracer.stop()

asyncio.run(main())

That's it. Run python after.py

, open ** http://localhost:7842/ui**, and your run is there.

with

block For scripts and notebooks, there's a context manager that starts the UI and installs a global handler — so you don't even pass callbacks=

:

import tracesage

with tracesage.trace() as tl:                 # starts UI + global capture
    result = agent.invoke({"messages": [...]})    # 🔍 tracesage: http://127.0.0.1:7842/ui/#run=...
    input("Trace ready — open the printed link, then Enter to exit.")

Every new run prints a clickable deep link to that exact trace.

Here's where tracesage earns its keep. Open a run and you get a topology graph of everything that happened.

Every node is one of six kinds, colour-coded in the legend (bottom-left):

Kind What it is
agent
a function you registered as a node, that calls other things
tool
a @tool side-effect function (DB, API, calculation)
llm
a language-model call (what you count, cost, and cache)
retriever
a BaseRetriever — the "R" in RAG
chain
plumbing: LCEL pipes, the LangGraph state machine, routing functions
mcp
a synthesized node grouping the tools loaded from one MCP server

Click any node to open its inspector — call counts, durations, errors, and the tools it provides or uses:

The timeline on the right replays the run step-by-step; click a step to expand the full payload (prompts, tool inputs/outputs, token usage, and — on errors — the exception type and traceback).

If your agent loads tools from MCP servers (via langchain-mcp-adapters

), you usually lose track of where each tool came from — they all look like generic LangChain tools at runtime. tracesage fixes that.

Install the extra and register your MCP client:

pip install "tracesage[mcp]"
python
from langchain_mcp_adapters.client import MultiServerMCPClient
from tracesage import TraceSage
from tracesage.adapters.mcp import register_mcp_client

tracer = await TraceSage.create()

client = MultiServerMCPClient({
    "weather": {"command": "python", "args": ["weather_server.py"], "transport": "stdio"},
    "math":    {"command": "python", "args": ["math_server.py"],    "transport": "stdio"},
})

tools = await register_mcp_client(tracer, client)

Now the UI shows a "Tools by source" panel and dedicated mcp:

nodes — every tool is grouped by where it came from:

Click an MCP server node and you see exactly what it provides, how often it was called, and which agents used it:

A complete, runnable MCP example (two local stdio servers + hardcoded tools, no API key needed) lives in the repo at examples/mcp/

:

pip install "tracesage[mcp]"
python examples/mcp/main.py     # then open http://localhost:7842/ui

Tracing isn't just for eyeballing. tracesage ships a pytest

fixture (tracesage_capture

, auto-registered) so you can assert behaviour:

def test_agent_uses_search(tracesage_capture):
    agent.invoke("find me a hotel in Paris")
    tracesage_capture.assert_tool_called("get_weather")
    tracesage_capture.assert_no_errors()
    assert tracesage_capture.total_tokens()[0] < 5000   # input-token budget

No setup, no server — the fixture captures the run in-process and gives you assertions like assert_tool_called

, assert_no_errors

, and total_tokens

.

tracesage is built so you can wire it in once and control it per-environment:

Kill switch: set TRACESAGE_ENABLED=false

(or enabled=False

) and TraceSage

returns an inert tracer — no server, no DB, a no-op handler, near-zero overhead. Same code ships to prod; tracing just turns off.

Capture without the UI: TRACESAGE_START_SERVER=false

records traces to disk in prod without binding the in-process UI; view them later with tracesage serve

.

Safety rails: bearer-token auth, root-level sampling (sample_rate

), a per-run event cap, and a hard fail-stop if you bind a non-loopback address without an auth token.

pip install "tracesage[langchain]"
tracesage demo

Docs & full quickstart: https://kjgpta.github.io/tracesage/

Concepts (what each node kind means): https://kjgpta.github.io/tracesage/concepts/

MCP attribution guide: https://kjgpta.github.io/tracesage/mcp/

30 before/after example apps: examples/showcase/

in the repo

If you build agents with LangChain or LangGraph and you're tired of print

-debugging your way through a run, give it a spin. Two lines, one browser tab, and your agent stops being a black box.

tracesage is MIT-licensed and open source.

── more in #developer-tools 4 stories · sorted by recency
── more on @langchain 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/tracesage-see-inside…] indexed:0 read:7min 2026-06-16 ·