Skip to content

Native LangChain Integration

Bring your LangChain / LangGraph agent. Get a full terminal UI. No server required.

pip install 'gentui[langchain]'
from langchain.agents import create_agent
from gentui import GentUI

agent = create_agent("anthropic:claude-sonnet-4-5", tools=[])
GentUI.from_langchain(agent).run()

The agent runs in your Python process; there is no server, no endpoint and no second process. It works with any compiled LangGraph graph (what create_agent and langgraph.prebuilt.create_react_agent return). You get streaming chat, tool cards, reasoning, Approve / Reject, tables, charts and the event inspector. It is the same experience as native Strands agents.

Tool calling

Tools are ordinary LangChain tools. Each call is drawn as a card with its name and arguments, a running state, and then the tool's real output, or a red failed line if the tool errored.

from langchain.agents import create_agent
from langchain_core.tools import tool
from gentui import GentUI

@tool
def multiply(a: float, b: float) -> float:
    """Multiply two numbers."""
    return a * b

GentUI.from_langchain(create_agent(model, tools=[multiply])).run()

Human approval

approval_middleware makes chosen tools wait for the user. The graph pauses before the tool body runs.

from gentui.adapters.langchain import approval_middleware

agent = create_agent(model, tools=[list_files, delete_file],
                     middleware=[approval_middleware("delete_file")])   # no names = every tool
GentUI.from_langchain(agent).run()

Approve runs the tool. Reject (or cancelling) never runs it: the model receives "The user rejected running delete_file." as the tool's result (flagged as an error) and carries on. Anything other than an explicit {"approved": true} counts as a rejection. approval_middleware(..., message="Really delete?") changes the question; the message can also be a function of the tool name and input.

Under the hood this is LangGraph's interrupt(): your own code can call it too. Gentui shows it as Approve / Reject and resumes the graph with Command(resume={"approved": bool}). While an approval is open, a new chat message is refused; answer it, or use /new.

How it works

LangChainAGUIAdapter is a Gentui client, the same shape as the HTTP one. It calls agent.astream_events(..., version="v2") and translates the events into AG-UI events.

LangChain AG-UI event
invocation starts RUN_STARTED
chat model text chunk TEXT_MESSAGE_START (once), TEXT_MESSAGE_CONTENT
thinking blocks / reasoning_content REASONING_START, REASONING_MESSAGE_*, REASONING_END
tool call chunks TOOL_CALL_START / TOOL_CALL_ARGS / TOOL_CALL_END
ToolMessage TOOL_CALL_RESULT (success / error status in raw_event)
graph paused by interrupt() RUN_FINISHED with an interrupt outcome; the answer arrives as resume
invocation ends / raises RUN_FINISHED / RUN_ERROR

Models that do not stream still work: the finished message is used to fill in text and tool calls. The dev pane (d or /dev) shows both sides: lines starting with langchain are the LangChain events, the JSON lines are the AG-UI events.

Multi-turn. Memory is the graph's checkpointer, keyed by Gentui's thread id. If the graph has none, Gentui gives it an in-memory one. /new starts a fresh thread.

In the browser

gentui --serve serves the same UI in a web page (pip install 'gentui[web]'). For a native agent, serve your script with textual-serve: Server("python my_agent.py").serve(). See the command-line reference.

Limitations

  • No reasoning is shown unless the model returns it.
  • Interrupts are answered as yes / no; free-form input is not supported yet.
  • A tool's result is shown as text; images and files appear as [image] / [file].
  • Shared state (STATE_SNAPSHOT, the plan widget) is not produced.
  • Text from sub-agents run inside tools is shown as part of the chat.

Examples

examples/langchain_native/ has tool_call.py, tool_call_approval.py and chart.py. They need pip install 'gentui[langchain,langchain-ollama]' and a running, signed-in Ollama for their model. The tests need none of that: they drive a real LangChain agent with a scripted model.