[PR #1799] [CLOSED] feat(sdk): add type-safe tool call streaming with agent type inference #1736

Closed
opened 2026-02-15 20:16:40 -05:00 by yindo · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/langchain-ai/langgraphjs/pull/1799
Author: @christian-bromann
Created: 11/30/2025
Status: Closed

Base: dqbd/sdk-ui-other-fwHead: cb/type-safe-streaming


📝 Commits (6)

  • 5012302 feat(sdk): add vue, svelte, angular implementation of useStream hook
  • cd7202a Update vitest
  • 43aa2c8 Add missing eslint
  • 6f04dc7 Remove tsc build for svelte and vue
  • 29b7d3c feat(sdk): add type-safe tool call streaming with agent type inference**
  • 2b003eb Change versioning to minor for ui-react and langgraph-sdk

📊 Changes

91 files changed (+8760 additions, -782 deletions)

View changed files

.changeset/serious-parrots-refuse.md (+6 -0)
examples/ui-angular/.gitignore (+46 -0)
examples/ui-angular/angular.json (+97 -0)
examples/ui-angular/langgraph.json (+7 -0)
examples/ui-angular/package.json (+51 -0)
examples/ui-angular/src/agent.mts (+18 -0)
examples/ui-angular/src/app.ts (+47 -0)
examples/ui-angular/src/index.html (+13 -0)
examples/ui-angular/src/main.ts (+10 -0)
examples/ui-angular/src/styles.css (+1 -0)
examples/ui-angular/tsconfig.app.json (+15 -0)
examples/ui-angular/tsconfig.json (+34 -0)
examples/ui-angular/tsconfig.spec.json (+14 -0)
📝 examples/ui-angular/turbo.json (+0 -0)
📝 examples/ui-react/.gitignore (+1 -0)
📝 examples/ui-react/index.html (+83 -2)
📝 examples/ui-react/langgraph.json (+1 -1)
📝 examples/ui-react/package.json (+4 -2)
📝 examples/ui-react/src/agent.mts (+78 -13)
📝 examples/ui-react/src/client.tsx (+203 -35)

...and 71 more files

📄 Description

This PR introduces type-safe tool call handling in the useStream React hook, enabling automatic type inference from LangGraph agents created with createAgent (needs https://github.com/langchain-ai/langchainjs/pull/9521 to be merged and released). When you pass typeof agent to useStream, tool calls are automatically typed as a discriminated union, allowing TypeScript to narrow types based on call.name.

Motivation

Previously, tool calls in streamed messages were typed as generic objects with name: string and args: Record<string, any>. This made it difficult to:

  • Get type-safe access to tool arguments
  • Use discriminated unions to narrow types based on tool name
  • Leverage IDE autocomplete when working with tool results

With this change, developers can now write type-safe tool call handling:

// Tool calls are automatically typed from the agent's tools
const stream = useStream<typeof agent>({
  assistantId: "agent",
  apiUrl: "http://localhost:2024",
});

// TypeScript knows all possible tool names and their args
for (const { call, result } of stream.toolCalls) {
  if (call.name === "get_weather") {
    // call.args is typed as { location: string }
    console.log(`Weather for ${call.args.location}:`, result?.content);
  }
}

Changes

SDK (libs/sdk/)

New Types:

  • AIMessage<ToolCall> - Generic AI message type parameterized by tool call type
  • ToolCallFromTool<T> - Extract tool call type from a single tool
  • ToolCallsFromTools<T> - Extract union of tool calls from an array of tools
  • ToolCallWithResult<T> - Pairs a tool call with its corresponding ToolMessage result
  • InferAgentToolCalls<T> - Extract tool calls union from an agent type
  • AgentToBag<T> - Convert agent type to useStream's Bag type parameter

New Function:

  • getToolCallsWithResults(messages) - Extracts tool calls and pairs them with their results

useStream Hook Updates:

  • Accepts typeof agent as type parameter to auto-infer tool types
  • New toolCalls property returns ToolCallWithResult[] for easy rendering
  • messages property now typed with tool call generic

React Example (examples/ui-react/)

Complete UI redesign demonstrating the new type-safe streaming:

streaming

  • Modern dark theme with Geist typography and smooth animations
  • New component architecture:
    • ToolCallCard.tsx - Type-safe tool call rendering with discriminated union
    • MessageBubble.tsx - Human/AI message display
    • Loading.tsx / States.tsx - Loading and empty states
  • Real weather tool using Open-Meteo API (no API key required)
  • Demonstrates type narrowing: if (call.name === "get_weather") narrows args type

Breaking Changes

None. All changes are additive with backwards-compatible defaults:

  • AIMessage defaults to DefaultToolCall (the previous untyped behavior)
  • useStream without type parameters works exactly as before

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/langchain-ai/langgraphjs/pull/1799 **Author:** [@christian-bromann](https://github.com/christian-bromann) **Created:** 11/30/2025 **Status:** ❌ Closed **Base:** `dqbd/sdk-ui-other-fw` ← **Head:** `cb/type-safe-streaming` --- ### 📝 Commits (6) - [`5012302`](https://github.com/langchain-ai/langgraphjs/commit/5012302ed215d5260682860e2ffb896c395e6eb4) feat(sdk): add vue, svelte, angular implementation of useStream hook - [`cd7202a`](https://github.com/langchain-ai/langgraphjs/commit/cd7202a9733a144ea712fb5cb49b5732f3009454) Update vitest - [`43aa2c8`](https://github.com/langchain-ai/langgraphjs/commit/43aa2c802ae0eaa37f014416794c3a1de22a0b5a) Add missing eslint - [`6f04dc7`](https://github.com/langchain-ai/langgraphjs/commit/6f04dc7d88fb39b82db23f1d6827d29e2ec6bf85) Remove tsc build for svelte and vue - [`29b7d3c`](https://github.com/langchain-ai/langgraphjs/commit/29b7d3cf5ffd4509f6c47949f4ff57fd0efb6b48) feat(sdk): add type-safe tool call streaming with agent type inference** - [`2b003eb`](https://github.com/langchain-ai/langgraphjs/commit/2b003ebbd54010faed02d275efee1548e792f511) Change versioning to minor for ui-react and langgraph-sdk ### 📊 Changes **91 files changed** (+8760 additions, -782 deletions) <details> <summary>View changed files</summary> ➕ `.changeset/serious-parrots-refuse.md` (+6 -0) ➕ `examples/ui-angular/.gitignore` (+46 -0) ➕ `examples/ui-angular/angular.json` (+97 -0) ➕ `examples/ui-angular/langgraph.json` (+7 -0) ➕ `examples/ui-angular/package.json` (+51 -0) ➕ `examples/ui-angular/src/agent.mts` (+18 -0) ➕ `examples/ui-angular/src/app.ts` (+47 -0) ➕ `examples/ui-angular/src/index.html` (+13 -0) ➕ `examples/ui-angular/src/main.ts` (+10 -0) ➕ `examples/ui-angular/src/styles.css` (+1 -0) ➕ `examples/ui-angular/tsconfig.app.json` (+15 -0) ➕ `examples/ui-angular/tsconfig.json` (+34 -0) ➕ `examples/ui-angular/tsconfig.spec.json` (+14 -0) 📝 `examples/ui-angular/turbo.json` (+0 -0) 📝 `examples/ui-react/.gitignore` (+1 -0) 📝 `examples/ui-react/index.html` (+83 -2) 📝 `examples/ui-react/langgraph.json` (+1 -1) 📝 `examples/ui-react/package.json` (+4 -2) 📝 `examples/ui-react/src/agent.mts` (+78 -13) 📝 `examples/ui-react/src/client.tsx` (+203 -35) _...and 71 more files_ </details> ### 📄 Description This PR introduces type-safe tool call handling in the `useStream` React hook, enabling automatic type inference from LangGraph agents created with `createAgent` (needs https://github.com/langchain-ai/langchainjs/pull/9521 to be merged and released). When you pass `typeof agent` to `useStream`, tool calls are automatically typed as a discriminated union, allowing TypeScript to narrow types based on `call.name`. ### Motivation Previously, tool calls in streamed messages were typed as generic objects with `name: string` and `args: Record<string, any>`. This made it difficult to: - Get type-safe access to tool arguments - Use discriminated unions to narrow types based on tool name - Leverage IDE autocomplete when working with tool results With this change, developers can now write type-safe tool call handling: ```tsx // Tool calls are automatically typed from the agent's tools const stream = useStream<typeof agent>({ assistantId: "agent", apiUrl: "http://localhost:2024", }); // TypeScript knows all possible tool names and their args for (const { call, result } of stream.toolCalls) { if (call.name === "get_weather") { // call.args is typed as { location: string } console.log(`Weather for ${call.args.location}:`, result?.content); } } ``` ### Changes #### SDK (`libs/sdk/`) **New Types:** - `AIMessage<ToolCall>` - Generic AI message type parameterized by tool call type - `ToolCallFromTool<T>` - Extract tool call type from a single tool - `ToolCallsFromTools<T>` - Extract union of tool calls from an array of tools - `ToolCallWithResult<T>` - Pairs a tool call with its corresponding ToolMessage result - `InferAgentToolCalls<T>` - Extract tool calls union from an agent type - `AgentToBag<T>` - Convert agent type to useStream's Bag type parameter **New Function:** - `getToolCallsWithResults(messages)` - Extracts tool calls and pairs them with their results **useStream Hook Updates:** - Accepts `typeof agent` as type parameter to auto-infer tool types - New `toolCalls` property returns `ToolCallWithResult[]` for easy rendering - `messages` property now typed with tool call generic #### React Example (`examples/ui-react/`) Complete UI redesign demonstrating the new type-safe streaming: ![streaming](https://github.com/user-attachments/assets/29978e7c-136c-43f9-af08-56d626245770) - Modern dark theme with Geist typography and smooth animations - New component architecture: - `ToolCallCard.tsx` - Type-safe tool call rendering with discriminated union - `MessageBubble.tsx` - Human/AI message display - `Loading.tsx` / `States.tsx` - Loading and empty states - Real weather tool using Open-Meteo API (no API key required) - Demonstrates type narrowing: `if (call.name === "get_weather")` narrows args type ### Breaking Changes None. All changes are additive with backwards-compatible defaults: - `AIMessage` defaults to `DefaultToolCall` (the previous untyped behavior) - `useStream` without type parameters works exactly as before --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
yindo added the pull-request label 2026-02-15 20:16:40 -05:00
yindo closed this issue 2026-02-15 20:16:40 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langchain-ai/langgraphjs#1736