Writing it yourself today
An integration is smaller than it looks. It is three things: map your messages to records, call the endpoint, and fail open.- Hold back what must survive.
required_record_idsis the field designed to pin a record and it does not pin today. Keeping a message out ofrecords[]is the only guarantee, and it is the right shape anyway — a system prompt does not benefit from being selected. - Supply an
idon every record. Without one you get a server-generated id back that joins to nothing on your side, and two identical calls return different ids. - Two pass-through paths — an exception, and an empty selection. Both return the original list. An empty selection returned as a success is a failure mode, not a valid answer.
Keep the message order. The example filters the original list rather than
rebuilding from
selected[], so ordering is preserved for free.
selected[] is in selection order, not conversation order, and reconstructing
from it directly will scramble a conversation.What is coming
needlepath / @needlepath/sdk
Framework-free core clients for Python and TypeScript. One seam for transport
and auth, so localhost, hosted and any future deployment are the same client.
Shadow mode as a one-line switch.
LangChain and LangGraph
One
AgentMiddleware reaching both. wrap_tool_call is the best-fit hook in
the ecosystem for our sweet spot: it hands over a tool call and accepts a
rewritten tool message, which is exactly a tool_result record, structurally
typed, before it enters the message list.LangGraph-native users get a documented recipe in the same package — not a
second package.LiteLLM
A guardrail for the LiteLLM proxy. Mutation is proxy-only; the SDK
callbacks are observability-only, so this integration is deliberately scoped
to the proxy rather than pretending to work in both.
LlamaIndex
A node postprocessor, following the host’s naming convention. Worth knowing
what it is and is not: a retrieval-time seam that never sees tool outputs, so
it exercises the case Needlepath is least differentiated on.
The LangGraph recipe, in advance
For a LangGraph graph, the seam that composes with a non-destructive selection service is a pre-model hook that changes what the model sees without mutating graph state — thellm_input_messages pattern. Selection is advisory
per call, so a later node still has the full state to work from.
Deleting messages from state with RemoveMessage also works and is the right
tool if you genuinely want them gone, but it is destructive: a stand-down cannot
undo it, and a subsequent turn cannot recover a record the engine would have
selected next time.
Rules every adapter follows
These are binding on our packages and are the right rules for yours.1
Fail open on every error path
Timeout, non-2xx, empty selection — pass the original messages through
unmodified and emit a metadata-only warning. At a framework boundary this
matters more than anywhere else, because the caller has no way to inspect what
happened.
2
Pin the operating point in the constructor
Not per call, and never left to the server default. Behaviour must not shift
under an application that has not changed.
3
Guard the 6 MB body limit client-side
It is a platform cap enforced before the service is reached, so the error it
produces will not be a Needlepath error shape. Check before sending.
4
Depend only on public, documented framework symbols
And cap the framework at a major version. Reaching into a framework’s internals
buys a feature now and an outage on its next minor release.
Choosing between us and what your framework already ships
Several frameworks now include some form of context trimming in-tree and free — LangChain, for example, ships middleware that clears tool results once a token threshold is crossed. A developer evaluating Needlepath usually already has that installed, so the honest comparison is not “can something prune tool results”. It is three narrower questions:
If your problem is “the context window overflows and I need it to stop”, a
threshold-based trimmer in your framework is a genuinely reasonable answer and
it costs nothing. Reach for Needlepath when which records survive is the part
that matters.
Try it on your own traffic first
Run selection alongside your existing prompts, record what would have been
dropped, and change nothing until you have looked.