feat(langchain): expose toggle to trace inputs on AgentMiddleware#38910
feat(langchain): expose toggle to trace inputs on AgentMiddleware#38910ccurme (ccurme) wants to merge 11 commits into
AgentMiddleware#38910Conversation
Merging this PR will not alter performance
Comparing Footnotes
|
| langchain-openai = { path = "../partners/openai", editable = true } | ||
| langchain-anthropic = { path = "../partners/anthropic", editable = true } | ||
| # TEMPORARY: pull langgraph from the cc/profiling-test-1 branch (adds add_node trace_inputs). | ||
| langgraph = { git = "https://github.com/langchain-ai/langgraph", subdirectory = "libs/langgraph", branch = "cc/profiling-test-1" } |
There was a problem hiding this comment.
🟠 Published package can install incompatible langgraph
This source override only affects uv installs from the repo; it does not change the wheel metadata, which still advertises langgraph>=1.2.5,<1.3.0. The code in this PR now calls StateGraph.add_node(..., trace_inputs=...), but the PR notes that kwarg comes from the temporary langgraph branch. A user installing langchain with an already-locked/allowed langgraph==1.2.5 can therefore construct an agent with a before/after middleware hook and get TypeError: add_node() got an unexpected keyword argument 'trace_inputs'. Please depend on a released langgraph version that contains add_node(trace_inputs=...) and bump the lower bound accordingly, rather than relying on the local source override.
(Refers to line 105)
Your feedback helps Open SWE learn. React with 👍 or 👎 to tell us if this review comment was useful.
| tools: Sequence[BaseTool] | ||
| """Additional tools registered by the middleware.""" | ||
|
|
||
| trace_inputs: bool = False |
There was a problem hiding this comment.
🟡 Middleware traces drop inputs by default
Changing the exported AgentMiddleware.trace_inputs default to False changes behavior for every existing middleware subclass and decorator-created middleware that does not explicitly set this attribute: after upgrading, their hook spans will stop recording the request/state inputs in LangSmith traces. Since this PR is adding an opt-out toggle, the public default should preserve the existing trace payloads (True) and let latency-sensitive callers opt into scrubbing by setting trace_inputs=False.
(Refers to line 401)
Your feedback helps Open SWE learn. React with 👍 or 👎 to tell us if this review comment was useful.
| trace_inputs: bool = False | |
| trace_inputs: bool = True |
The cc/profiling-test-1 langgraph branch no longer exists; repoint to the revert branch so downstream locks (deepagents) can resolve. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Requires langchain-ai/langgraph#8362
AgentMiddleware traces state messages in its input (once in langgraph
stateforbefore/after_*node-type hooks, and in bothrequest.messagesand langgraphstateforwrap-type hooks). For longish message histories this adds considerable latency: we've observed 500 - 1,000ms per middleware in deepagents' eval suite. For the default middleware stack this can dwarf the latency from the actual LLM call.Here we add a tracing config to
AgentMiddlewareto allow inputs from middleware traces to be completely scrubbed:~70% of the latency is from wrap-type hooks. We already choose the inputs to those hooks via
traceable, scrubbingruntimeandhandler. Here we let you trace no inputs from those hooks.20% of the latency is from node-type hooks. For this we expose the
trace_inputscallable of the underlying node'sRunnableSeqthrough toadd_node(done in langchain-ai/langgraph#8362), and access it here inlangchain.We could alternatively selectively scrub keys from state (like
messages). But the solution here is cleaner and simpler, and also will work for files in StateBackend or other large data.We don't expose a toggle for tracing outputs because those are in practice small (typically a single message in a
ModelResponseor state update).Importantly, we flip tracing inputs on AgentMiddleware to False, which would loses any meaningful inputs from trace data. If we're concerned about this, we can flip the default and update built-in middleware in
deepagents. At any rate, users can opt-in by passingtracing={"inputs": True}to middleware.Before:

After:
