Skip to content

Conversation

@pokey
Copy link
Contributor

@pokey pokey commented Oct 24, 2025

Why?

Today, the way we determine whether a tool is a server or client tool is based on its shape: it it has {type: ..., name: ...} then it is server, otherwise client. This heuristic breaks for Anthropic memory and text editor tools, which have that shape, but are client tools

What?

This PR introduces the providerToolDefinition field on client tools, allowing you to define a client tool but override the way it presents itself to the provider, rather than automatically generating based on schema

@changeset-bot
Copy link

changeset-bot bot commented Oct 24, 2025

⚠️ No Changeset found

Latest commit: fd44c11

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link
Member

@christian-bromann christian-bromann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure if we want to apply this to the general tool primitive when we currently only see support for this (ever) in 1 provider. Looking at the attached PR adding a middleware to the createAgent I am concerned about mixing provider related code with our general langchain package.

Some thoughts:

  • instead of introducing providerToolDefinition, should we just use the metadata field for this?
  • let's move everything in libs/langchain/src/agents/middleware/anthropicTools from your PR into the anthropic provider package and use schema primitives from the provider packages directly
  • export these tools (currently defined from the middleware) from the provider package, attach metadata to it and make a small change in the chat model to adjust for it

So the final interface may look something like:

import { tools } from "@langchain/anthropic"

const agent = createAgent({
  model: "anthropic:...",
  tools: [
    tools.textEditor({
      type: "fs" // or "memory" or custom implementation
    }),
    tools.memory()
  ]
})

What do you think?

@pokey
Copy link
Contributor Author

pokey commented Nov 8, 2025

@christian-bromann yeah that all makes sense to me. I guess one question is how we'd handle the version of Anthropic tools that stores the file contents on the graph state. That seems to rely on langgraph / middleware types. Did we end up finding a way to do that without the circular deps issue?

@christian-bromann
Copy link
Member

@pokey would there still be a need for middleware if we abstract this as tool functions?

@pokey
Copy link
Contributor Author

pokey commented Nov 10, 2025

Good question. There are 4 different middlewares in my PR, for combinations of (file system vs graph state X memory vs file tool). The one that leverages the most middleware functionality is memory tool with graph state. That uses the following middleware functionality:

  • updating system prompt, though fwiw it is static, not dynamic
  • adding a beta header to Anthropic request
  • updating / reading graph state as that's where files are stored

If we can accomplish all of these things with just tools and no middleware, then I'm all for it!

See https://github.com/pokey/langchainjs/blob/pokey/featlangchainagents-add-anthropic-tools-middleware/libs/langchain/src/agents/middleware/anthropicTools/index.ts for the relevant code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants