Build an Agent That Thinks Out Loud with LangChain and TypeScript
Most LLM demos stop at a single prompt-response pair. A tool-calling agent with streaming, memory, and visible reasoning closes the gap between a chatbot and a system that can actually do work—and the content-type edge cases in the message stream are exactly the kind of detail that breaks real integrations.
Starting from an empty folder, this walkthrough constructs a functional AI agent using LangChain, LangGraph, and TypeScript. Two tools—a calculator and a time fetcher—are defined with Zod schemas that tell the LLM exactly how to call them. The agent is wired together with `createDeepAgent`, which loops the LLM through tool execution until it can answer without further calls.
Streaming output is handled by iterating over message tuples, with careful attention to the dual nature of `content`: a plain string when no tool is invoked, and an array of blocks when tool calls are in play. Multi-turn memory is achieved through `thread_id` and a `MemorySaver` checkpointer, letting the agent recall prior calculations when a user challenges a result.
Extended Thinking surfaces the model's internal monologue as gray ANSI text before the final answer, making the reasoning chain visible. The entire stack runs directly via `tsx` with no compilation step, and the Anthropic-compatible API endpoint allows swapping in models like Qwen without changing the client code.
The jump from a single LLM call to an agent loop is conceptually small but operationally large—streaming, tool result re-injection, and multi-turn state all compound quickly.
Zod's dual role as TypeScript validator and LLM instruction manual is an underappreciated design pattern; the schema is simultaneously code contract and prompt engineering.
Handling both string and array `content` types is a rite of passage for LangChain streaming; the framework's type flexibility here creates a silent bug surface.
Extended Thinking turns the model from a black box into a debuggable system—seeing the reasoning chain makes failures diagnosable rather than mysterious.
Using an Anthropic-compatible proxy to run non-Anthropic models is a practical bridge that avoids vendor lock-in while keeping the developer experience consistent.