TestComposition Class — langchain Architecture
Architecture documentation for the TestComposition class in test_wrap_model_call_state_update.py from the langchain codebase.
Entity Profile
Dependency Diagram
graph TD 269d8393_43ba_e665_6d86_95d75ce0c396["TestComposition"] 949c7cf4_56fe_f3b4_cd89_9631a7e9cb1e["AgentMiddleware"] 269d8393_43ba_e665_6d86_95d75ce0c396 -->|extends| 949c7cf4_56fe_f3b4_cd89_9631a7e9cb1e 707a7c14_db9d_706f_20af_75c8ede73799["ModelResponse"] 269d8393_43ba_e665_6d86_95d75ce0c396 -->|extends| 707a7c14_db9d_706f_20af_75c8ede73799 e4070722_d3c6_f73d_d727_5779ab576a2a["AgentState"] 269d8393_43ba_e665_6d86_95d75ce0c396 -->|extends| e4070722_d3c6_f73d_d727_5779ab576a2a 08361e76_a995_1e57_f200_e292474e2f00["test_wrap_model_call_state_update.py"] 269d8393_43ba_e665_6d86_95d75ce0c396 -->|defined in| 08361e76_a995_1e57_f200_e292474e2f00 a9938455_2c48_8cba_a118_749c3cb86a5f["test_outer_command_messages_added_alongside_model()"] 269d8393_43ba_e665_6d86_95d75ce0c396 -->|method| a9938455_2c48_8cba_a118_749c3cb86a5f c243db8c_72a9_edbd_93c9_c31516998280["test_inner_command_propagated_through_composition()"] 269d8393_43ba_e665_6d86_95d75ce0c396 -->|method| c243db8c_72a9_edbd_93c9_c31516998280 4b3a2bdd_eba2_dc85_cdd0_6e1c60df119f["test_non_reducer_key_conflict_raises()"] 269d8393_43ba_e665_6d86_95d75ce0c396 -->|method| 4b3a2bdd_eba2_dc85_cdd0_6e1c60df119f 1fb03fce_737e_5cfa_0692_0994faac9b9f["test_inner_state_preserved_when_outer_has_no_conflict()"] 269d8393_43ba_e665_6d86_95d75ce0c396 -->|method| 1fb03fce_737e_5cfa_0692_0994faac9b9f 058450ac_e67f_66fe_11a3_984dcb479882["test_inner_command_retry_safe()"] 269d8393_43ba_e665_6d86_95d75ce0c396 -->|method| 058450ac_e67f_66fe_11a3_984dcb479882 b7bc4ef2_62f9_b69f_d927_a3b579a6bb33["test_decorator_returns_wrap_result()"] 269d8393_43ba_e665_6d86_95d75ce0c396 -->|method| b7bc4ef2_62f9_b69f_d927_a3b579a6bb33 2f3bb608_7ff4_8a29_55b9_22dd6fee84f9["test_structured_response_preserved()"] 269d8393_43ba_e665_6d86_95d75ce0c396 -->|method| 2f3bb608_7ff4_8a29_55b9_22dd6fee84f9
Relationship Graph
Source Code
libs/langchain_v1/tests/unit_tests/agents/middleware/core/test_wrap_model_call_state_update.py lines 312–636
class TestComposition:
"""Test ExtendedModelResponse with composed middleware.
Key semantics: Commands are collected inner-first, then outer.
For non-reducer fields, later Commands overwrite (outer wins).
For reducer fields (messages), all Commands are additive.
"""
def test_outer_command_messages_added_alongside_model(self) -> None:
"""Outer middleware's command messages are added alongside model messages."""
execution_order: list[str] = []
class OuterMiddleware(AgentMiddleware):
def wrap_model_call(
self,
request: ModelRequest,
handler: Callable[[ModelRequest], ModelResponse],
) -> ExtendedModelResponse:
execution_order.append("outer-before")
response = handler(request)
execution_order.append("outer-after")
return ExtendedModelResponse(
model_response=response,
command=Command(
update={"messages": [HumanMessage(content="Outer msg", id="outer-msg")]}
),
)
class InnerMiddleware(AgentMiddleware):
def wrap_model_call(
self,
request: ModelRequest,
handler: Callable[[ModelRequest], ModelResponse],
) -> ModelResponse:
execution_order.append("inner-before")
response = handler(request)
execution_order.append("inner-after")
return response
model = GenericFakeChatModel(messages=iter([AIMessage(content="Composed")]))
agent = create_agent(
model=model,
middleware=[OuterMiddleware(), InnerMiddleware()],
)
result = agent.invoke({"messages": [HumanMessage("Hi")]})
# Execution order: outer wraps inner
assert execution_order == [
"outer-before",
"inner-before",
"inner-after",
"outer-after",
]
# Model messages + outer command messages (additive)
messages = result["messages"]
assert len(messages) == 3
assert messages[0].content == "Hi"
assert messages[1].content == "Composed"
assert messages[2].content == "Outer msg"
def test_inner_command_propagated_through_composition(self) -> None:
"""Inner middleware's ExtendedModelResponse command is propagated.
When inner middleware returns ExtendedModelResponse, its command is
captured before normalizing to ModelResponse at the composition boundary
and collected into the final result.
"""
class OuterMiddleware(AgentMiddleware):
def wrap_model_call(
self,
request: ModelRequest,
handler: Callable[[ModelRequest], ModelResponse],
) -> ModelResponse:
# Outer sees a ModelResponse from handler (inner's ExtendedModelResponse
# was normalized at the composition boundary)
response = handler(request)
assert isinstance(response, ModelResponse)
return response
Defined In
Source
Frequently Asked Questions
What is the TestComposition class?
TestComposition is a class in the langchain codebase, defined in libs/langchain_v1/tests/unit_tests/agents/middleware/core/test_wrap_model_call_state_update.py.
Where is TestComposition defined?
TestComposition is defined in libs/langchain_v1/tests/unit_tests/agents/middleware/core/test_wrap_model_call_state_update.py at line 312.
What does TestComposition extend?
TestComposition extends AgentMiddleware, ModelResponse, AgentState.
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free