From aa6c7f2ea486d956a07ec6a7c153ceca79099b7b Mon Sep 17 00:00:00 2001 From: bradAGI <46579244+bradAGI@users.noreply.github.com> Date: Mon, 24 Aug 2026 14:24:53 -0400 Subject: [PATCH] feat(langchain): add LC-020, tool prints to stdout for diagnostics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ports OAI-010 to LangChain. The loss is larger here than in the OpenAI pack, and the rule text says so: LangChain already threads every tool start, end, and error through its callback system into LangSmith or whichever tracer is configured, so a bare print is the one diagnostic landing outside that — detached from the run and the step that produced it, and simply absent the moment anyone debugs from a trace rather than a terminal. --- langchain/observability.yaml | 38 ++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 langchain/observability.yaml diff --git a/langchain/observability.yaml b/langchain/observability.yaml new file mode 100644 index 0000000..62a4382 --- /dev/null +++ b/langchain/observability.yaml @@ -0,0 +1,38 @@ +policy: + id: langchain_observability + name: LangChain tool observability hygiene + category: langchain + description: > + Rules covering how a LangChain tool emits diagnostics. A tool body that + prints to stdout writes outside the callback system the rest of the run is + recorded through, so the record reaches neither the model nor the trace. + +rules: + - id: LC-020 + title: LangChain tool prints to stdout for diagnostics + severity: low + confidence: 0.65 + language: python + applies_to: + - langchain_tool + scope: tool + match: + has_print_call: true + explanation: > + The tool body calls print(), which writes to the process's stdout. The + model never sees it — only the return value flows back into the executor + loop — so the output silently disappears in any deployment that captures + structured records rather than raw stdout. It is a bigger loss in this SDK + than in most, because LangChain already threads every tool start, end, and + error through its callback system into LangSmith or whatever tracer is + configured. A bare print is the one diagnostic that lands outside that, + detached from the run and the step that produced it, so the moment anyone + debugs from a trace rather than a terminal it is simply not there. If the + same tool is ever served over an MCP stdio transport, the loose print + frames interleave with JSON-RPC messages and corrupt the stream. + fix: > + Remove the print(). For operator diagnostics, emit through a module logger + (logging.getLogger(__name__).info(...)) so it lands in the application's + log sink, or attach the detail to the run through the callback system so + it is correlated with the step that produced it. If the information needs + to reach the model, return it as part of the tool's result instead.