Sweep 22 Sep 2026 · 17:19Z Build v2.1.280 501 read Stable v2.1.267 Latest v2.1.280 Next v2.1.280 Feeds RSS JSON llms.txt Unofficial
One change · api

fine-grained-tool-streaming changed

agents-and-tools/tool-use/fine-grained-tool-streaming

Nearest release: v2.1.275, published an hour before this site recorded the change. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.

Recorded here
Lines+84added
Lines−68removed
From line 402 where the diff opens
First seen 14 Aug 2026 this site's first read of the page
Recorded edits5to this page, all time

The whole hunk

from line 402, old and new numbered
/
lines
from line 402
402402 $toolInputs = [];
403403 
404404 foreach ($stream as $event) {
405 if (
406 $event instanceof RawContentBlockStartEvent
407 && $event->contentBlock instanceof ToolUseBlock
408 ) {
409 $toolInputs[$event->index] = '';
410 } elseif (
411 $event instanceof RawContentBlockDeltaEvent
412 && $event->delta instanceof InputJSONDelta
413 ) {
414 echo $event->delta->partialJSON;
415 $toolInputs[$event->index] .= $event->delta->partialJSON;
405 switch (true) {
406 case $event instanceof RawContentBlockStartEvent:
407 if ($event->contentBlock instanceof ToolUseBlock) {
408 $toolInputs[$event->index] = '';
409 }
410 break;
411 case $event instanceof RawContentBlockDeltaEvent:
412 if ($event->delta instanceof InputJSONDelta) {
413 echo $event->delta->partialJSON;
414 $toolInputs[$event->index] .= $event->delta->partialJSON;
415 }
416 break;
416417 }
417418 }
418419 
from line 571
570571 });
571572 
572573 for await (const event of stream) {
573 if (event.type === "content_block_start" && event.content_block.type === "tool_use") {
574 toolInputs.set(event.index, "");
575 } else if (event.type === "content_block_delta" && event.delta.type === "input_json_delta") {
576 toolInputs.set(
577 event.index,
578 (toolInputs.get(event.index) ?? "") + event.delta.partial_json
579 );
580 } else if (event.type === "content_block_stop" && toolInputs.has(event.index)) {
581 const rawInput = toolInputs.get(event.index)!;
582 try {
583 console.log("Tool input:", JSON.parse(rawInput));
584 } catch {
585 // The accumulated string is not guaranteed to be valid JSON.
586 // See "Handling invalid JSON in tool responses" on this page.
587 console.log("Invalid tool input:", rawInput);
588 }
574 switch (event.type) {
575 case "content_block_start":
576 if (event.content_block.type === "tool_use") {
577 toolInputs.set(event.index, "");
578 }
579 break;
580 case "content_block_delta":
581 if (event.delta.type === "input_json_delta") {
582 toolInputs.set(
583 event.index,
584 (toolInputs.get(event.index) ?? "") + event.delta.partial_json
585 );
586 }
587 break;
588 case "content_block_stop":
589 if (toolInputs.has(event.index)) {
590 const rawInput = toolInputs.get(event.index)!;
591 try {
592 console.log("Tool input:", JSON.parse(rawInput));
593 } catch {
594 // The accumulated string is not guaranteed to be valid JSON.
595 // See "Handling invalid JSON in tool responses" on this page.
596 console.log("Invalid tool input:", rawInput);
597 }
598 }
599 break;
589600 }
590601 }
591602 ```
from line 753
742753 var eventIterator = streamResponse.stream().iterator();
743754 while (eventIterator.hasNext()) {
744755 RawMessageStreamEvent event = eventIterator.next();
745 if (event.isContentBlockStart()) {
746 var blockStart = event.asContentBlockStart();
747 if (blockStart.contentBlock().isToolUse()) {
748 toolInputs.put(blockStart.index(), new StringBuilder());
756 switch (event.type().value()) {
757 case CONTENT_BLOCK_START -> {
758 var blockStart = event.asContentBlockStart();
759 if (blockStart.contentBlock().isToolUse()) {
760 toolInputs.put(blockStart.index(), new StringBuilder());
761 }
749762 }
750 } else if (event.isContentBlockDelta()) {
751 var blockDelta = event.asContentBlockDelta();
752 if (blockDelta.delta().isInputJson() && toolInputs.containsKey(blockDelta.index())) {
753 toolInputs.get(blockDelta.index()).append(blockDelta.delta().asInputJson().partialJson());
763 case CONTENT_BLOCK_DELTA -> {
764 var blockDelta = event.asContentBlockDelta();
765 if (blockDelta.delta().isInputJson() && toolInputs.containsKey(blockDelta.index())) {
766 toolInputs.get(blockDelta.index()).append(blockDelta.delta().asInputJson().partialJson());
767 }
754768 }
755 } else if (event.isContentBlockStop()) {
756 var blockStop = event.asContentBlockStop();
757 if (toolInputs.containsKey(blockStop.index())) {
758 String accumulated = toolInputs.get(blockStop.index()).toString();
759 try {
760 IO.println("Tool input: " + objectMapper.readTree(accumulated));
761 } catch (JsonProcessingException e) {
762 // The accumulated string is not guaranteed to be valid JSON.
763 // See "Handling invalid JSON in tool responses" on this page.
764 IO.println("Invalid tool input: " + accumulated);
769 case CONTENT_BLOCK_STOP -> {
770 var blockStop = event.asContentBlockStop();
771 if (toolInputs.containsKey(blockStop.index())) {
772 String accumulated = toolInputs.get(blockStop.index()).toString();
773 try {
774 IO.println("Tool input: " + objectMapper.readTree(accumulated));
775 } catch (JsonProcessingException e) {
776 // The accumulated string is not guaranteed to be valid JSON.
777 // See "Handling invalid JSON in tool responses" on this page.
778 IO.println("Invalid tool input: " + accumulated);
779 }
765780 }
766781 }
767782 }
from line 818
803818 );
804819 
805820 foreach ($stream as $event) {
806 if (
807 $event instanceof RawContentBlockStartEvent
808 && $event->contentBlock instanceof ToolUseBlock
809 ) {
810 $toolInputs[$event->index] = '';
811 } elseif (
812 $event instanceof RawContentBlockDeltaEvent
813 && $event->delta instanceof InputJSONDelta
814 ) {
815 $toolInputs[$event->index] .= $event->delta->partialJSON;
816 } elseif (
817 $event instanceof RawContentBlockStopEvent
818 && isset($toolInputs[$event->index])
819 ) {
820 $accumulated = $toolInputs[$event->index];
821 try {
822 $parsed = json_decode($accumulated, associative: true, flags: JSON_THROW_ON_ERROR);
823 echo "Tool input: " . json_encode($parsed) . "\n";
824 } catch (JsonException $e) {
825 // The accumulated string is not guaranteed to be valid JSON.
826 // See "Handling invalid JSON in tool responses" on this page.
827 echo "Invalid tool input: {$accumulated}\n";
828 }
821 switch (true) {
822 case $event instanceof RawContentBlockStartEvent:
823 if ($event->contentBlock instanceof ToolUseBlock) {
824 $toolInputs[$event->index] = '';
825 }
826 break;
827 case $event instanceof RawContentBlockDeltaEvent:
828 if ($event->delta instanceof InputJSONDelta) {
829 $toolInputs[$event->index] .= $event->delta->partialJSON;
830 }
831 break;
832 case $event instanceof RawContentBlockStopEvent:
833 if (isset($toolInputs[$event->index])) {
834 $accumulated = $toolInputs[$event->index];
835 try {
836 $parsed = json_decode($accumulated, associative: true, flags: JSON_THROW_ON_ERROR);
837 echo "Tool input: " . json_encode($parsed) . "\n";
838 } catch (JsonException $e) {
839 // The accumulated string is not guaranteed to be valid JSON.
840 // See "Handling invalid JSON in tool responses" on this page.
841 echo "Invalid tool input: {$accumulated}\n";
842 }
843 }
844 break;
829845 }
830846 }
831847 ```