Skip to content

Support tool calling in MLXLanguageModel.streamResponse() - #181

Open
noorbhatia wants to merge 1 commit into
huggingface:mainfrom
noorbhatia:mlx-stream-toolcall
Open

Support tool calling in MLXLanguageModel.streamResponse()#181
noorbhatia wants to merge 1 commit into
huggingface:mainfrom
noorbhatia:mlx-stream-toolcall

Conversation

@noorbhatia

Copy link
Copy Markdown
Contributor

streamResponse() hardcoded tools: nil and discarded .toolCall stream items, so MLX callers had to choose between streamed tokens and tool calling. respond() already ran the full tool cycle; this ports that while-loop into the streaming path, reusing mlxToolSpecs, resolveToolCalls, makeTranscriptToolCalls, and the maxToolIterations / repeated-signature guards. Text and tool entries accumulate across rounds so snapshots stay monotonic.

Also surface streamed tool activity: ResponseStream.Snapshot gains a defaulted transcriptEntries field (ArraySlice<Transcript.Entry>), wrapStream appends it to the session transcript before the response entry, and collect() returns it instead of []. The field defaults to empty, so the other providers keep their current behavior; the shared plumbing is ready for them to populate later.

Closes #164

streamResponse() hardcoded tools: nil and discarded .toolCall stream
items, so MLX callers had to choose between streamed tokens and tool
calling. respond() already ran the full tool cycle; this ports that
while-loop into the streaming path, reusing mlxToolSpecs, resolveToolCalls,
makeTranscriptToolCalls, and the maxToolIterations / repeated-signature
guards. Text and tool entries accumulate across rounds so snapshots stay
monotonic.

Also surface streamed tool activity: ResponseStream.Snapshot gains a
defaulted transcriptEntries field (ArraySlice<Transcript.Entry>), wrapStream
appends it to the session transcript before the response entry, and
collect() returns it instead of []. The field defaults to empty, so the
other providers keep their current behavior; the shared plumbing is ready
for them to populate later.

Closes huggingface#164

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@noorbhatia

Copy link
Copy Markdown
Contributor Author

@pcuenca @mattt Pls take a look.

@mattt

mattt commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Hi @noorbhatia. Thanks for this, and sorry for not reviewing it sooner.

This and #176 each add a way to observe transcript entries during streaming, for MLX and Anthropic respectively, which is what I asked for in #103. Rather than land two shapes, I'd like to settle on one in #103 and then have both PRs adopt it. I've posted a proposal there that's essentially this PR's shape; would you take a look?

@noorbhatia

Copy link
Copy Markdown
Contributor Author

No worries @mattt and welcome back!
#103 's proposal sounds good to me.

@ActuallyTaylor

Copy link
Copy Markdown
Contributor

I like the implementation! It seems to match with the rest of the streaming tool calls

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MLX: support tool calling during streamResponse (currently respond()-only)

3 participants