[GH-ISSUE #327] Tool name collision between user-supplied tools and built-ins silently breaks schema validation at runtime #249

Closed
opened 2026-06-05 17:21:16 -04:00 by yindo · 0 comments
Owner

Originally created by @wicked-tc130 on GitHub (Mar 19, 2026).
Original GitHub issue: https://github.com/langchain-ai/deepagentsjs/issues/327

Originally assigned to: @maahir30 on GitHub.

Bug Report

Summary

When a user passes a tool to createDeepAgent whose name collides with one of the built-in FilesystemMiddleware tools (ls, read_file, write_file, edit_file, glob, grep, execute), the custom tool silently shadows the built-in. The model then invokes the tool with arguments that satisfy the custom tool's schema but fail the built-in's strict zod schema, producing a cryptic runtime error deep inside LangGraph's ToolNode.

Error seen

Error invoking tool 'write_file' with kwargs {} with error:
Error: Received tool input did not match expected schema
✖ Invalid input: expected string, received undefined
  → at file_path
at DynamicStructuredTool.call …
Please fix the error and try again.

Root cause

createDeepAgent accepts a tools array and forwards it directly to createAgent. FilesystemMiddleware then adds its own tools (same names, strict schemas). Both end up in the tool list the model sees. The model picks one schema, generates a call, and LangGraph routes it to the other handler whose schema rejects the input.

A particularly common trigger is integrating MCP servers: MCP wrappers often expose tools with generic names (write_file, execute, etc.) and permissive z.record(z.string(), z.any()) schemas.

Reproduction

import { tool } from "langchain";
import { createDeepAgent } from "deepagents";
import { z } from "zod";

// MCP-style wrapper with a permissive schema and the same name as a built-in
const myWriteFile = tool(
  async (input) => callSomeExternalService(input),
  {
    name: "write_file",          // ← collides with built-in
    description: "Write a file via my MCP server",
    schema: z.record(z.string(), z.any()),  // permissive
  }
);

const agent = createDeepAgent({ tools: [myWriteFile] });
// Agent runs → model calls write_file with {} → schema failure

Expected behaviour

createDeepAgent should detect the conflict at construction time and emit a clear warning (or optionally throw), so the developer is alerted immediately instead of chasing a runtime schema error.

Suggested fix

Add a collision check inside createDeepAgent after the tools parameter is destructured:

const BUILTIN_TOOL_NAMES = new Set([
  "ls", "read_file", "write_file", "edit_file", "glob", "grep", "execute",
]);

const collidingTools = tools
  .map((t) => t.name)
  .filter((name) => name && BUILTIN_TOOL_NAMES.has(name));

if (collidingTools.length > 0) {
  console.warn(
    `[deepagents] Warning: tool name(s) [${collidingTools.join(", ")}] ` +
    `conflict with built-in filesystem/shell tools and will shadow them. ` +
    `This may cause runtime schema-validation errors. Rename your tools to fix this.`
  );
}

I have a PR ready with this change if the approach looks good to you.

Originally created by @wicked-tc130 on GitHub (Mar 19, 2026). Original GitHub issue: https://github.com/langchain-ai/deepagentsjs/issues/327 Originally assigned to: @maahir30 on GitHub. ## Bug Report ### Summary When a user passes a tool to `createDeepAgent` whose name collides with one of the built-in `FilesystemMiddleware` tools (`ls`, `read_file`, `write_file`, `edit_file`, `glob`, `grep`, `execute`), the custom tool **silently shadows** the built-in. The model then invokes the tool with arguments that satisfy the custom tool's schema but fail the built-in's strict zod schema, producing a cryptic runtime error deep inside LangGraph's `ToolNode`. ### Error seen ``` Error invoking tool 'write_file' with kwargs {} with error: Error: Received tool input did not match expected schema ✖ Invalid input: expected string, received undefined → at file_path at DynamicStructuredTool.call … Please fix the error and try again. ``` ### Root cause `createDeepAgent` accepts a `tools` array and forwards it directly to `createAgent`. `FilesystemMiddleware` then adds its own tools (same names, strict schemas). Both end up in the tool list the model sees. The model picks one schema, generates a call, and LangGraph routes it to the *other* handler whose schema rejects the input. A particularly common trigger is integrating MCP servers: MCP wrappers often expose tools with generic names (`write_file`, `execute`, etc.) and permissive `z.record(z.string(), z.any())` schemas. ### Reproduction ```ts import { tool } from "langchain"; import { createDeepAgent } from "deepagents"; import { z } from "zod"; // MCP-style wrapper with a permissive schema and the same name as a built-in const myWriteFile = tool( async (input) => callSomeExternalService(input), { name: "write_file", // ← collides with built-in description: "Write a file via my MCP server", schema: z.record(z.string(), z.any()), // permissive } ); const agent = createDeepAgent({ tools: [myWriteFile] }); // Agent runs → model calls write_file with {} → schema failure ``` ### Expected behaviour `createDeepAgent` should detect the conflict **at construction time** and emit a clear warning (or optionally throw), so the developer is alerted immediately instead of chasing a runtime schema error. ### Suggested fix Add a collision check inside `createDeepAgent` after the `tools` parameter is destructured: ```ts const BUILTIN_TOOL_NAMES = new Set([ "ls", "read_file", "write_file", "edit_file", "glob", "grep", "execute", ]); const collidingTools = tools .map((t) => t.name) .filter((name) => name && BUILTIN_TOOL_NAMES.has(name)); if (collidingTools.length > 0) { console.warn( `[deepagents] Warning: tool name(s) [${collidingTools.join(", ")}] ` + `conflict with built-in filesystem/shell tools and will shadow them. ` + `This may cause runtime schema-validation errors. Rename your tools to fix this.` ); } ``` I have a PR ready with this change if the approach looks good to you.
yindo closed this issue 2026-06-05 17:21:16 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langchain-ai/deepagentsjs#249