Skip to content

Conversation

@pokey
Copy link
Owner

@pokey pokey commented Oct 3, 2025

Adds middleware to enable code execution using Anthropic's beta code execution tool. The middleware does the following:

  • Enables Anthropic's code execution tool
  • Automatically manages container IDs for Anthropic (enables file persistence across turns)
  • Injects required beta headers for code execution and files API
  • Works around Anthropic API bugs with file references in conversation history

This PR also includes a simple standalone example usage file, though I'm not entirely sure where to put that

Depends on:

@pokey pokey force-pushed the pokey/anthropic-code-execution-middleware branch from 5358b8c to 7ed4fbf Compare October 3, 2025 14:51
Copy link
Owner Author

Choose a reason for hiding this comment

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

Not sure where this file (and its corresponding test) should go. Tbh most of the functions we probably don't want to support ourselves, but extractGeneratedFilesAnthropic should maybe go into anthropic provider? cc/ @hntrl

Copy link

Choose a reason for hiding this comment

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

I wonder if it makes sense to collapse this as gated logic inside of the anthropicCodeExecution? E.g. when we specify middleware we can attach files and those will be auto-uploaded to anthropic, and file contents + metadata will be contained within the content of the message

Would agree that it doesn't make a lot of sense to expose these as user APIs

Comment on lines +39 to +44
* import {
* uploadFileAnthropic,
* extractGeneratedFilesAnthropic,
* getFileMetadataAnthropic,
* downloadFileAnthropic,
* } from "langchain/agents/middleware";
Copy link
Owner Author

Choose a reason for hiding this comment

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

note that if we don't end up supporting these, we should update the jsdoc to just inline their impls; they're fairly simple

Comment on lines +80 to +83
* @see {@link uploadFileAnthropic} for uploading files to Anthropic
* @see {@link extractGeneratedFilesAnthropic} for extracting generated file IDs from responses
* @see {@link getFileMetadataAnthropic} for retrieving file metadata including filenames
* @see {@link downloadFileAnthropic} for downloading generated files from Anthropic
Copy link
Owner Author

Choose a reason for hiding this comment

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

as above

messages: workAroundAnthropicCodeExecutionBug(request.messages),
callOptions: {
// Pass container ID to reuse files across turns
// FIXME: What to do about container expiration?
Copy link
Owner Author

Choose a reason for hiding this comment

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

wasn't sure how to handle container expiration. Open to suggestions, including punt

* @param messages The messages to filter
* @returns The filtered messages
*/
function workAroundAnthropicCodeExecutionBug(
Copy link
Owner Author

Choose a reason for hiding this comment

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

This is unfortunate. I've sent an email to anthropic support with a link to a gist for them to reproduce it

Copy link

Choose a reason for hiding this comment

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

we can flag this with them internally also!

Comment on lines +184 to +187
/**
* Anthropic code execution content block types.
* These match the types from @anthropic-ai/sdk BetaBashCodeExecution* interfaces.
*/
Copy link
Owner Author

Choose a reason for hiding this comment

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

Not ideal to reproduce all these types here but I didn't want to depend on our anthropic provider or anthropic sdk

Copy link

Choose a reason for hiding this comment

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

good call, makes for even more reason to have integration specific middleware!

Copy link
Owner Author

Choose a reason for hiding this comment

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

Wasn't sure where to put this. Should maybe go somewhere in the docs?

Copy link

Choose a reason for hiding this comment

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

examples/ is typically where we dump stuff like this

"format:check": "prettier --config .prettierrc --check \"src\""
},
"devDependencies": {
"@anthropic-ai/sdk": "^0.56.0",
Copy link
Owner Author

Choose a reason for hiding this comment

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

we need to remove this once we figure out where the anthropic file helpers should go; left here for now so people can play with the code

Copy link
Owner Author

Choose a reason for hiding this comment

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

this goes with the dataAnalysisExperiment; we should remove once we figure out where that is going

Copy link
Owner Author

Choose a reason for hiding this comment

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

Fwiw here is an example run:

I was kinda hoping because they share thread id they'd end up in same run?

Copy link

Choose a reason for hiding this comment

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

There is a "Threads" tab in a tracing project that should let you view both (though you can't share that thread publicly)

Comment on lines +62 to +66
for (const fileId of extractGeneratedFilesAnthropic(response2)) {
const metadata = await getFileMetadataAnthropic(client, fileId);
await downloadFileAnthropic(client, fileId, metadata.filename);
console.log(`Downloaded generated file: ${metadata.filename}`);
}
Copy link
Owner Author

Choose a reason for hiding this comment

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

would be cool if these files could make it into langsmith trace

Copy link

Choose a reason for hiding this comment

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

there's prob a way, will ask

Copy link

Choose a reason for hiding this comment

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

if there is a will

Copy link
Owner Author

Choose a reason for hiding this comment

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

I wonder if we want any tracking of uploaded / generated files? The latter might be useful

Copy link

Choose a reason for hiding this comment

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

how do you imagine this looking? is this not retained in the returned message history? (is that another content type that we need to add?)

@pokey
Copy link
Owner Author

pokey commented Oct 3, 2025

One thing I've left completely unexplored and untested is how this machinery interacts if you also have local tools

* @param messages The messages to filter
* @returns The filtered messages
*/
function workAroundAnthropicCodeExecutionBug(
Copy link
Owner Author

Choose a reason for hiding this comment

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

FWIW I could also see this code migrating to anthropic message parser

@pokey
Copy link
Owner Author

pokey commented Oct 16, 2025

Closing in favour of langchain-ai#9209

@pokey pokey closed this Oct 16, 2025
@pokey pokey deleted the pokey/anthropic-code-execution-middleware branch October 16, 2025 18:22
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.

4 participants