langchain-core 1.7.0: Tool-Call Args Now Stream as Deltas
langchain-core 1.7.0 streams tool-call args as tool-call-delta slices instead of snapshots. Here is what changed since 1.6.13, what did not, and how to upgrade.

7 min read
Came here from Instagram, LinkedIn, X or YouTube? Here is the full source list you came for. Everything below is built from these, nothing else.
The release
langchain-core 1.7.0 shipped on October 22, 2026, published by github-actions from commit f4e6cde with a verified GitHub signature. It is marked as the latest release.
The changelog against 1.6.13 has exactly two entries:
release(core): 1.7.0(#41418)feat(core): emit tool-call-delta for streamed tool-call args(#41257)
That looks small. It is not, if you read raw stream events. The way tool-call arguments arrive while a model is still streaming has changed, and code that assumed the old shape will quietly build the wrong thing.
Here is every change that matters, what it looked like before, what it looks like now, and what to do about it.
Key takeaways
- langchain-core 1.7.0 was released on October 22, 2026, with 2 changelog entries since 1.6.13.
- Streamed tool-call args now arrive as tool-call-delta slices, not block-delta snapshots of the args so far.
- Iterating ChatModelStream.tool_calls now yields each call's new args slice, not the full args so far.
- .tool_calls.get() and .output are unchanged. If you only read final results, nothing breaks.
- To keep the old snapshot behaviour, pin langchain-core<1.7.
What changed in langchain-core 1.7.0?
One feature, with three visible effects and one thing deliberately left alone. I have split it into the pieces you will actually hit in code.
1. A new event: tool-call-delta
The headline entry is PR #41257: "emit tool-call-delta for streamed tool-call args".
When a model decides to call a tool, it streams the arguments piece by piece, the same way it streams text. Before 1.7, core reported that progress through block-delta events. In 1.7, core emits a dedicated tool-call-delta event for those arguments.
Before (1.6.13):
stream event: block-delta (carries tool-call args)
After (1.7.0):
stream event: tool-call-delta (carries tool-call args)
If you filter raw stream events by type, this is the first thing to check. A filter that only looks for block-delta to catch tool arguments will now miss them.
2. Args are slices now, not snapshots
This is the change that breaks code without raising an error.
The release notes are explicit: tool-call args now stream as tool-call-delta slices instead of block-delta snapshots of the args so far.
A snapshot is cumulative. Each event repeats everything received up to that point, plus the new part. A slice is only the new part.
Picture a tool call whose final arguments are {"city": "Paris"}, arriving in three pieces. This is an illustration of the two shapes, not a captured log:
| Event | Before 1.7 (snapshot) | 1.7.0 (slice) |
|---|---|---|
| 1 | {"ci | {"ci |
| 2 | {"city": "Pa | ty": "Pa |
| 3 | {"city": "Paris"} | ris"} |
With snapshots, the latest event is always the answer so far. You overwrite. With slices, no single event is the answer. You append.
That is why this one is sneaky. Code that does "take the latest value" will not crash on 1.7. It will just end up holding ris"} and try to parse it.
3. ChatModelStream.tool_calls iteration changed too
This is not limited to raw events. The notes call out the higher-level stream object as well: "iterating ChatModelStream.tool_calls yields each call's new args slice, not a snapshot of the args so far."
So the same overwrite versus append logic applies here. In plain terms:
Before (1.6.13):
for each item in ChatModelStream.tool_calls:
args_so_far = item # each item is the full args so far
After (1.7.0):
for each item in ChatModelStream.tool_calls:
args_so_far += item # each item is only the new slice
I have written this as pseudocode on purpose. The release notes describe the behaviour, not the exact field names on each item, so check the shape in your own code before you change it.
4. What did not change: .tool_calls.get() and .output
This is the good news, and it covers most apps.
The notes say plainly that .tool_calls.get() and .output are unchanged. If your code waits for the stream to finish and then reads the completed tool calls or the final output, 1.7.0 should be a no-op for you.
| How you read tool calls | Affected by 1.7.0? |
|---|---|
| Raw stream events, reading block-delta args mid-stream | Yes. Read tool-call-delta instead |
| Iterating ChatModelStream.tool_calls | Yes. Items are now slices |
| .tool_calls.get() | No |
| .output | No |
The split is simple. If you touch tool-call args while they stream, you are affected. If you read them after, you are not.
5. The escape hatch: pin below 1.7
The release notes give one official way to keep the old behaviour: "To keep snapshots, pin langchain-core<1.7."
pip install "langchain-core<1.7"
Or in a requirements file:
langchain-core<1.7
Treat this as a stopgap, not a plan. Pinning keeps you off every future core release, not just this change.
Who needs to care about this upgrade?
Ask yourself one question: do I show or process tool-call arguments before the model has finished?
The usual reasons people do that:
- A UI that shows "calling search with query: ..." as the arguments type out.
- Logging or tracing that records each streamed event.
- Early validation that tries to parse partial JSON to start work sooner.
- Custom stream handlers that forward events to a frontend.
If any of those are in your codebase, you are in the affected group. If your agent just runs, collects the finished tool calls and executes them, you are almost certainly not.
How do you upgrade to langchain-core 1.7.0 safely?
Here is the order I would do it in.
Step 1. Find the call sites. Search your code for block-delta, for loops over tool_calls, and for any handler that reads tool-call args during streaming. Ignore places that only call .tool_calls.get() or read .output.
Step 2. Upgrade in a branch.
pip install -U "langchain-core==1.7.0"
Step 3. Switch event types. Anywhere you read tool-call args from block-delta mid-stream, read tool-call-delta instead. That is the exact instruction in the release notes.
Step 4. Flip overwrite to append. Wherever you kept "the latest args", keep a buffer per tool call and add each slice to it. If you stream several tool calls at once, keep one buffer per call, because each slice belongs to one specific call.
Step 5. Stop parsing partial pieces. With snapshots, you could try to parse each event as JSON and hope. With slices, a single event is almost never valid JSON on its own. Parse the buffer, not the slice.
Step 6. Compare final results. Run the same prompt on 1.6.13 and 1.7.0. Your accumulated args at the end should match what .tool_calls.get() returns. If they do, your streaming code is correct.
Step 7. If you cannot fix it now, pin. langchain-core<1.7 keeps snapshots while you schedule the work.
What does this mean for your projects?
Three things.
First, slices match how text already streams. Text arrives as new pieces, not as "everything so far". With 1.7.0, tool-call args follow the same pattern, so one append-and-buffer approach can handle both. That is less special-case code in your stream handler.
Second, minor versions can still change behaviour you depend on. This went from 1.6.13 to 1.7.0, and the notes flag a change in what a stream yields. If you run LangChain in production, pin to a version range you have tested, and read the notes before every bump, not after something breaks.
Third, the safest way to consume tool calls is still the finished result. The APIs that read completed calls, .tool_calls.get() and .output, did not move. If you do not need live arguments in your UI, reading at the end keeps you clear of changes like this one.
My honest take: if you are building a chat UI that shows tools being called live, spend an hour on this now. If you are not, upgrade, run your tests, and move on.
FAQ
What is new in langchain-core 1.7.0?
langchain-core 1.7.0, released on October 22, 2026, makes streamed tool-call arguments arrive as tool-call-delta events. Each event carries only the new slice of the args, instead of a block-delta snapshot of everything so far. The changelog since 1.6.13 has two entries: the release itself (#41418) and this feature (#41257).
Will langchain-core 1.7.0 break my code?
Only if you read tool-call arguments while they are still streaming. That means reading block-delta args from raw stream events, or iterating ChatModelStream.tool_calls. If you only use .tool_calls.get() or .output, the release notes say those are unchanged.
How do I keep the old snapshot behaviour?
Pin langchain-core below 1.7, for example with pip install "langchain-core<1.7". This is the method the release notes give. It is fine as a short-term fix, but it also holds you back from later core releases.
What is the difference between a snapshot and a slice?
A snapshot repeats all the arguments received so far in every event, so the latest event is the current value. A slice carries only the new piece, so you have to append slices together to rebuild the full arguments. In 1.7.0, tool-call args stream as slices.
Open your stream handler today and search for block-delta before you bump the version. While you are in there, the free tools on Art of Code can help with the small jobs, and if you build with LangChain for a living, see who is hiring on Art of Code jobs.
Written by Adithya Guttha, Founder of Art of Code.
Sign in to like and save posts.
Keep reading



Discussion
Comments (0)
Want to join the conversation?
Sign in to commentNo comments yet. Be the first to comment!