Skip to content

Commit b67428a

Browse files
authored
real fix for LangSmith RuntimeError (#314)
revert override() reversion Bypassing review in order to expedite fix to LangSmith Studio
1 parent 4cf59b5 commit b67428a

3 files changed

Lines changed: 19 additions & 16 deletions

File tree

backend/pyproject.toml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,6 @@ markers = [
6666
filterwarnings = [
6767
# Third-party library using deprecated Pydantic v1 API internally.
6868
"ignore::pydantic.warnings.PydanticDeprecatedSince20:langsmith",
69-
# langchain deprecated direct attribute assignment on ModelRequest in favour of
70-
# request.override(), but override() triggers execution_info patching that crashes
71-
# in LangSmith Studio before a run context exists. Direct mutation is intentional
72-
# here; suppress until the library resolves that bug.
73-
"ignore:Direct attribute assignment to ModelRequest:DeprecationWarning",
7469
]
7570

7671
[tool.coverage.run]

backend/tenantfirstaid/graph.py

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,6 @@ class _SystemPromptFromContext(AgentMiddleware[Any, TFAContext]):
8484
location context (city/state) from the agent state, mirroring what
8585
the web app does via prepare_system_prompt().
8686
87-
Note: direct attribute assignment to ModelRequest.system_message is
88-
deprecated by langchain in favour of request.override(), but override()
89-
triggers execution_info patching that crashes in LangSmith Studio before
90-
a run context exists. Direct mutation is the correct approach here until
91-
the library resolves that bug.
9287
"""
9388

9489
def _build(self, request: ModelRequest[TFAContext]) -> SystemMessage:
@@ -108,16 +103,14 @@ def wrap_model_call(
108103
request: ModelRequest[TFAContext],
109104
handler: Callable[[ModelRequest[TFAContext]], ModelResponse],
110105
) -> ModelResponse:
111-
request.system_message = self._build(request) # type: ignore[misc]
112-
return handler(request)
106+
return handler(request.override(system_message=self._build(request)))
113107

114108
async def awrap_model_call(
115109
self,
116110
request: ModelRequest[TFAContext],
117111
handler: Callable[[ModelRequest[TFAContext]], Awaitable[ModelResponse]],
118112
) -> ModelResponse:
119-
request.system_message = self._build(request) # type: ignore[misc]
120-
return await handler(request)
113+
return await handler(request.override(system_message=self._build(request)))
121114

122115

123116
def _build_system_message(
@@ -163,12 +156,15 @@ def create_graph(
163156
)
164157

165158
# LangGraph deployment path: middleware injects the prompt from
166-
# Studio's editable configuration panel.
159+
# Studio's editable configuration panel. context_schema is NOT set here
160+
# because this graph runs as a subgraph inside graph() — the outer graph
161+
# owns the context and propagates it. Declaring it on both levels causes
162+
# LangSmith to patch execution_info during __start__ before a run context
163+
# exists.
167164
return create_agent(
168165
model,
169166
tools,
170167
middleware=[_SystemPromptFromContext()],
171-
context_schema=TFAContext,
172168
state_schema=TFAAgentStateSchema,
173169
checkpointer=checkpointer,
174170
)

backend/tests/test_graph.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,18 @@ def _make_middleware_request(
9595
request.runtime.context = TFAContext(system_prompt=prompt)
9696
request.state = {"city": city, "state": state}
9797
request.system_message = None
98+
99+
# override() must return a new mock whose system_message reflects the kwarg,
100+
# mirroring the real ModelRequest.override() behaviour.
101+
def _override(**kwargs):
102+
child = MagicMock()
103+
child.runtime = request.runtime
104+
child.state = request.state
105+
for k, v in kwargs.items():
106+
setattr(child, k, v)
107+
return child
108+
109+
request.override = _override
98110
return request
99111

100112

0 commit comments

Comments
 (0)