smithery.ai

langchain-agents

Create and use LangChain agents with createAgent - includes agent loops, ReAct pattern, tool execution, and state management

First seen May 1, 2026

Installation

$ npx skills add https://smithery.ai

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery.ai · top by installs.

npx skills add https://smithery.ai

Browse all from smithery.ai

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 12,030 B
  • docs SUMMARY.md 194 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 1 installs

SKILL.md

langchain-agents (JavaScript/TypeScript)

Overview

Agents combine language models with tools to create systems that can reason about tasks, decide which tools to use, and iteratively work towards solutions. The createAgent() function provides a production-ready agent implementation built on LangGraph.

Key Concepts:

  • Agent Loop: The model decides → calls tools → observes results → repeats until done
  • ReAct Pattern: Reasoning and Acting - the agent reasons about what to do, then acts by calling tools
  • Graph-based Runtime: Agents run on a LangGraph graph with nodes (model, tools, middleware) and edges

When to Use Agents

Scenario Use Agent? Why
Need to call external APIs/databases ✅ Yes Agents can dynamically choose which tools to call
Multi-step task with decision points ✅ Yes Agent loop handles iterative reasoning
Simple prompt-response ❌ No Use a chat model directly
Predetermined workflow ❌ No Use LangGraph workflow instead
Need tool calling without iteration ⚠️ Maybe Consider using model.bindTools() directly

Decision Tables

Choosing Agent Configuration

Need Configuration Example
Basic agent with tools createAgent({ model, tools }) Search, calculator, weather
Custom system instructions Add systemPrompt Domain-specific behavior
Human approval for sensitive operations Add humanInTheLoopMiddleware Database writes, emails
Persistence across sessions Add checkpointer Multi-turn conversations
Structured output format Add responseFormat Extract contact info, parse forms

Tool Strategy

Tool Type When to Use Example
Static tools Tools don't change during execution Search, weather, calculator
Dynamic tools Tools depend on runtime state User-specific APIs
Built-in tools Need common functionality File system, code execution
Custom tools Domain-specific operations Your business logic

Code Examples

Basic Agent with Tools

import { createAgent } from "langchain";
import { tool } from "langchain";

// Define tools
const searchTool = tool(
  async ({ query }: { query: string }) => {
    // Your search implementation
    return `Results for: ${query}`;
  },
  {
    name: "search",
    description: "Search for information on the web",
    schema: z.object({
      query: z.string().describe("The search query"),
    }),
  }
);

const weatherTool = tool(
  async ({ location }: { location: string }) => {
    return `Weather in ${location}: Sunny, 72°F`;
  },
  {
    name: "get_weather",
    description: "Get current weather for a location",
    schema: z.object({
      location: z.string().describe("City name"),
    }),
  }
);

// Create agent
const agent = createAgent({
  model: "gpt-4.1",
  tools: [searchTool, weatherTool],
});

// Invoke agent
const result = await agent.invoke({
  messages: [
    { role: "user", content: "What's the weather in San Francisco?" }
  ],
});

console.log(result.messages[result.messages.length - 1].content);

Agent with System Prompt

import { createAgent } from "langchain";

const agent = createAgent({
  model: "gpt-4.1",
  tools: [searchTool, calculatorTool],
  systemPrompt: `You are a helpful research assistant.
Always cite your sources when using the search tool.
Show your work when performing calculations.`,
});

Agent Loop Execution Flow

// The agent runs in a loop:
// 1. Model receives user message
// 2. Model decides to call a tool (or finish)
// 3. Tool executes and returns result
// 4. Result goes back to model
// 5. Repeat until model decides to finish

const agent = createAgent({
  model: "gpt-4.1",
  tools: [searchTool, weatherTool],
});

// This single invoke() call handles the entire loop
const result = await agent.invoke({
  messages: [
    { 
      role: "user", 
      content: "Search for the capital of France, then get its weather" 
    }
  ],
});

// Agent automatically:
// - Calls search tool for capital
// - Receives "Paris"
// - Calls weather tool for Paris
// - Receives weather data
// - Responds with final answer

Streaming Agent Progress

import { createAgent } from "langchain";

const agent = createAgent({
  model: "gpt-4.1",
  tools: [searchTool],
});

// Stream with updates mode to see each step
for await (const chunk of await agent.stream(
  { messages: [{ role: "user", content: "Search for LangChain" }] },
  { streamMode: "updates" }
)) {
  console.log("Step:", chunk);
}

// Stream with messages mode for LLM tokens
for await (const chunk of await agent.stream(
  { messages: [{ role: "user", content: "Search for LangChain" }] },
  { streamMode: "messages" }
)) {
  const [token, metadata] = chunk;
  if (token.content) {
    process.stdout.write(token.content);
  }
}

Agent with Persistence

import { createAgent } from "langchain";
import { MemorySaver } from "@langchain/langgraph";

const checkpointer = new MemorySaver();

const agent = createAgent({
  model: "gpt-4.1",
  tools: [searchTool],
  checkpointer,
});

// First conversation
const config = { configurable: { thread_id: "user-123" } };
await agent.invoke({
  messages: [{ role: "user", content: "My name is Alice" }]
}, config);

// Later conversation - agent remembers
await agent.invoke({
  messages: [{ role: "user", content: "What's my name?" }]
}, config);
// Response: "Your name is Alice"

Multiple Tool Calls in Parallel

// Models can call multiple tools simultaneously
const agent = createAgent({
  model: "gpt-4.1",
  tools: [weatherTool, newsToolTool],
});

const result = await agent.invoke({
  messages: [{
    role: "user",
    content: "Get weather for NYC and latest news for SF"
  }],
});

// Agent may call both tools in parallel in a single step

Dynamic Tools (Runtime-Dependent)

import { createAgent } from "langchain";

const agent = createAgent({
  model: "gpt-4.1",
  tools: (state) => {
    // Tools can depend on current state
    const userId = state.config?.configurable?.user_id;
    return [
      getUserSpecificTool(userId),
      commonTool,
    ];
  },
});

Error Handling in Agents

import { createAgent, wrapToolCall } from "langchain";

// Custom error handling middleware
const errorHandler = wrapToolCall({
  name: "ErrorHandler",
  wrapToolCall: async (toolCall, handler) => {
    try {
      return await handler(toolCall);
    } catch (error) {
      return {
        ...toolCall,
        content: `Tool error: ${error.message}`,
      };
    }
  },
});

const agent = createAgent({
  model: "gpt-4.1",
  tools: [riskyTool],
  middleware: [errorHandler],
});

Boundaries

What Agents CAN Configure

Model: Any chat model (OpenAI, Anthropic, Google, etc.) ✅ Tools: Custom tools, built-in tools, dynamic tools ✅ System Prompt: Instructions for agent behavior ✅ Middleware: Human-in-the-loop, error handling, logging ✅ Checkpointer: Memory/persistence across conversations ✅ Response Format: Structured output schemas ✅ Max Iterations: Prevent infinite loops

What Agents CANNOT Configure

Direct Graph Structure: Use LangGraph directly for custom flows ❌ Tool Execution Order: Model decides which tools to call ❌ Interrupt Model Decision: Can only interrupt before tool execution ❌ Multiple Models: One agent = one model (use subagents for multiple)

Gotchas

1. Agent Doesn't Stop (Infinite Loop)

// ❌ Problem: No clear stopping condition
const agent = createAgent({
  model: "gpt-4.1",
  tools: [searchTool],
});

await agent.invoke({
  messages: [{ role: "user", content: "Keep searching until perfect" }]
});

// ✅ Solution: Set max iterations
const agent = createAgent({
  model: "gpt-4.1",
  tools: [searchTool],
  maxIterations: 10, // Stop after 10 tool calls
});

2. Tool Not Being Called

// ❌ Problem: Vague tool description
const badTool = tool(
  async ({ input }: { input: string }) => "result",
  {
    name: "tool",
    description: "Does stuff", // Too vague!
    schema: z.object({ input: z.string() }),
  }
);

// ✅ Solution: Clear, specific descriptions
const goodTool = tool(
  async ({ query }: { query: string }) => "result",
  {
    name: "web_search",
    description: "Search the web for current information about a topic. Use this when you need recent data that wasn't in your training.",
    schema: z.object({
      query: z.string().describe("The search query (2-10 words)"),
    }),
  }
);

3. State Not Persisting

// ❌ Problem: No checkpointer
const agent = createAgent({
  model: "gpt-4.1",
  tools: [searchTool],
});

// Each invoke is isolated - no memory
await agent.invoke({ messages: [{ role: "user", content: "Hi, I'm Bob" }] });
await agent.invoke({ messages: [{ role: "user", content: "What's my name?" }] });
// Agent doesn't remember "Bob"

// ✅ Solution: Add checkpointer and thread_id
import { MemorySaver } from "@langchain/langgraph";

const agent = createAgent({
  model: "gpt-4.1",
  tools: [searchTool],
  checkpointer: new MemorySaver(),
});

const config = { configurable: { thread_id: "session-1" } };
await agent.invoke({ messages: [{ role: "user", content: "Hi, I'm Bob" }] }, config);
await agent.invoke({ messages: [{ role: "user", content: "What's my name?" }] }, config);
// Agent remembers: "Your name is Bob"

4. Messages vs State Confusion

// Agent state includes more than just messages
const result = await agent.invoke({
  messages: [{ role: "user", content: "Hello" }]
});

// ✅ Access full conversation history
console.log(result.messages); // Array of all messages

// ✅ Access structured output (if configured)
console.log(result.structuredResponse);

// ❌ Don't try to access result.content directly
// console.log(result.content); // undefined!

5. Tool Results Must Be Serializable

// ❌ Problem: Returning non-serializable objects
const badTool = tool(
  async () => {
    return new Date(); // Date objects aren't JSON-serializable by default
  },
  { name: "get_time", description: "Get current time" }
);

// ✅ Solution: Return serializable data
const goodTool = tool(
  async () => {
    return new Date().toISOString(); // String is serializable
  },
  { name: "get_time", description: "Get current time" }
);

6. Streaming Modes Matter

// Different stream modes show different information

// "values" - Full state after each step
for await (const chunk of await agent.stream(input, { streamMode: "values" })) {
  console.log(chunk.messages); // All messages so far
}

// "updates" - Only what changed in each step
for await (const chunk of await agent.stream(input, { streamMode: "updates" })) {
  console.log(chunk); // Just the delta
}

// "messages" - LLM token stream
for await (const chunk of await agent.stream(input, { streamMode: "messages" })) {
  const [token, metadata] = chunk;
  console.log(token.content); // Each token
}

Links to Documentation