Skip to main content

langchain-turn-window

A small, model-agnostic LangChain agent middleware that keeps only the last N conversational turns before each model call — without ever splitting an AIMessage tool call from its ToolMessage response.

Why

Every provider (OpenAI, Anthropic, Gemini, ...) rejects a request where a tool_calls entry has no matching tool result message. Naive history trimming — slicing by raw message count or token count — can easily cut the window in the middle of a tool-call/tool-result pair and break the request.

TurnWindowMiddleware anchors the window on HumanMessage boundaries instead: it always starts the kept slice at the Nth-most-recent HumanMessage, which guarantees every AIMessage tool call inside the window still has its ToolMessage response attached.

This is a lightweight alternative to LangChain's built-in SummarizationMiddleware (which needs an extra LLM call) or context_editing (which selectively clears old tool outputs) for the common case of "just bound the context to the last few turns."

Install

pip install langchain-turn-window

Usage

from langchain.agents import create_agent

from langchain_turn_window import TurnWindowMiddleware

agent = create_agent(
    model="openai:gpt-4o",
    tools=[...],
    middleware=[
        TurnWindowMiddleware(keep_last_turns=3),
    ],
)

keep_last_turns is the number of most-recent HumanMessage turns to retain. If the conversation has fewer turns than that, the full history passes through unchanged.

How it works

TurnWindowMiddleware implements wrap_model_call / awrap_model_call. On every model call it:

  1. Finds the indexes of all HumanMessages in request.messages.
  2. If there are fewer than keep_last_turns human turns, passes the messages through unchanged.
  3. Otherwise, slices the message list starting at the keep_last_turns-th-most-recent HumanMessage and forwards only that suffix to the model.

The underlying pure function is also exported directly if you want to use it outside of middleware (e.g. in a custom node):

from langchain_turn_window import window_by_human_turns

windowed = window_by_human_turns(messages, n=3)

window_by_human_turns never mutates its input and returns the original list object unchanged when no trimming is needed (positive-n guard, empty list, or fewer human turns than n).

Configuration

Constructor arg Default Description
keep_last_turns 3 Number of most-recent human turns to keep. Must be >= 1.

Limitations

  • Assumes a single-user conversational shape (one HumanMessage per turn). For multi-agent handoff patterns where turns aren't anchored on HumanMessage, this middleware is not the right fit as-is.
  • This is a hard trim, not a summary — content outside the window is dropped, not condensed. Combine with SummarizationMiddleware if you need older context preserved in compressed form.

Development

pip install -e ".[dev]"
pytest

License

MIT

Metadata

Release files for langchain-turn-window 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for langchain-turn-window 0.1.0
File Size Uploaded Provenance
langchain_turn_window-0.1.0.tar.gz 5.7 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for langchain-turn-window 0.1.0
File Interpreter ABI Platform
langchain_turn_window-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 11.2 kB

Release files / langchain_turn_window-0.1.0.tar.gz

Download URL langchain_turn_window-0.1.0.tar.gz
Size 5.7 kB
Tags Source
SHA-256 checksum
How to use checksums
36173aef0da9b49e0fc2d0f2b7a77fef891841a77a2e78c95d3261f89b1a87d1
BLAKE2b-256 checksum
How to use checksums
4ede5511ab155d24629a48e10cf629e6d568209cb17a133b8b24e659d052139a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Release files / langchain_turn_window-0.1.0-py3-none-any.whl

Download URL langchain_turn_window-0.1.0-py3-none-any.whl
Size 5.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1ee10be8cd87679ec83f5ba5de42933f1b5397069db99bbff8ad4fe730f20126
BLAKE2b-256 checksum
How to use checksums
29495c34e22c1965c050ae356f57729dcf9419617c6a31937bae81870e4fd3dc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Security for langchain-turn-window 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page