Skip to content

🖼️ fix: Correct ToolMessage Response Format for Agent-Mode Image Tools#12310

Merged
danny-avila merged 6 commits into
devfrom
fix/response-format-image-tools
Mar 19, 2026
Merged

🖼️ fix: Correct ToolMessage Response Format for Agent-Mode Image Tools#12310
danny-avila merged 6 commits into
devfrom
fix/response-format-image-tools

Conversation

@danny-avila

@danny-avila danny-avila commented Mar 19, 2026

Copy link
Copy Markdown
Owner

Summary

Fixed a context-exhaustion bug where DALL-E 3, FluxAPI, and Stable Diffusion image tools, when invoked in agent mode, were serializing the full base64 image payload directly into ToolMessage.content instead of routing it to artifact.content.

  • Set this.responseFormat = 'content_and_artifact' in the constructors of DALLE3, FluxAPI, and StableDiffusionAPI when isAgent is true, so LangChain's Tool.invoke() correctly maps the [content, artifact] tuple returned by _call() onto the respective ToolMessage fields rather than JSON.stringify-ing the entire tuple into content.
  • Added a JSDoc comment at each responseFormat assignment explaining why LangChain requires the property for correct ToolMessage construction.
  • Fixed FluxAPI.generateFinetunedImage(), which had no isAgent branch and would unconditionally call this.processFileURL — a method that is never set in agent context — causing a silent TypeError and a failed generation with no image returned.
  • Fixed StableDiffusionAPI._call() error path, which was returning a raw string on axios failure, bypassing returnValue() and breaking the content_and_artifact tuple contract when isAgent is true.
  • Added imageTools-agent.spec.js with 13 regression tests covering responseFormat assignment, happy-path invoke() for all three tools (including the generate_finetuned FluxAPI action), and error-path invoke() for all three tools, verifying the ToolMessage structure in every case.

Change Type

  • Bug fix (non-breaking change which fixes an issue)

Testing

Verified via the new api/app/clients/tools/structured/specs/imageTools-agent.spec.js regression suite. Run from the api workspace:

cd api && npx jest imageTools-agent

Test Configuration:

  • No external services required — OpenAI SDK, axios, node-fetch, and undici are all mocked.
  • Tests cover: responseFormat set/not-set on construction, invoke() returning a ToolMessage with base64 confined to artifact.content on success, invoke() returning a well-formed ToolMessage with an error string in content on upstream API failure, and the generate_finetuned FluxAPI action path in agent mode.

Checklist

  • My code adheres to this project's style guidelines
  • I have performed a self-review of my own code
  • I have commented in any complex areas of my code
  • My changes do not introduce new warnings
  • I have written tests demonstrating that my changes are effective or that my feature works
  • Local unit tests pass with my changes

…leDiffusion classes

- Added logic to set `responseFormat` to 'content_and_artifact' when `isAgent` is true in DALLE3.js, FluxAPI.js, and StableDiffusion.js.
…ent.spec.js

- Introduced a new test suite for DALLE3, FluxAPI, and StableDiffusion classes to verify that the invoke() method returns a ToolMessage with base64 in artifact.content, ensuring it is not serialized into content.
- Validated that responseFormat is set to 'content_and_artifact' when isAgent is true, and confirmed the correct handling of base64 data in the response.
Copilot AI review requested due to automatic review settings March 19, 2026 17:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds an agent-mode regression guard for image generation tools to ensure LangChain Tool.invoke() returns a ToolMessage with image base64 placed in artifact.content (instead of being JSON-stringified into content, which bloats token counting / context).

Changes:

  • Set responseFormat = 'content_and_artifact' for DALLE3 / FluxAPI / StableDiffusion tools when isAgent is true.
  • Add Jest regression tests validating invoke() produces a ToolMessage where base64 only appears in the artifact payload.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
api/app/clients/tools/structured/specs/imageTools-agent.spec.js Adds regression tests ensuring agent-mode invoke() keeps base64 out of ToolMessage.content and in artifact.content.
api/app/clients/tools/structured/StableDiffusion.js Sets responseFormat for agent-mode Stable Diffusion tool invocations.
api/app/clients/tools/structured/FluxAPI.js Sets responseFormat for agent-mode Flux tool invocations.
api/app/clients/tools/structured/DALLE3.js Sets responseFormat for agent-mode DALL·E 3 tool invocations.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +52 to +58
describe('image tools - agent mode ToolMessage format', () => {
beforeEach(() => {
jest.clearAllMocks();
process.env.DALLE_API_KEY = 'test-key';
process.env.FLUX_API_KEY = 'test-key';
process.env.SD_WEBUI_URL = 'http://localhost:7860';
});
- StableDiffusion._call() was returning a raw string on API error, bypassing
  returnValue() and breaking the content_and_artifact contract when isAgent is true
- FluxAPI.generateFinetunedImage() had no isAgent branch; it would call
  processFileURL (unset in agent context) instead of fetching and returning
  the base64 image as an artifact tuple
- Add JSDoc to all three responseFormat assignments clarifying why LangChain
  requires this property for correct ToolMessage construction
- Add env var save/restore in beforeEach/afterEach to prevent test pollution
- Add error path tests for all three tools verifying ToolMessage content and
  artifact are correctly populated when the upstream API fails
- Add generate_finetuned action test for FluxAPI covering the new agent branch
  in generateFinetunedImage
@danny-avila danny-avila changed the title fix/response format image tools 🖼️ fix: Correct ToolMessage Response Format for Agent-Mode Image Tools Mar 19, 2026
@danny-avila
danny-avila merged commit a88bfae into dev Mar 19, 2026
9 checks passed
@danny-avila
danny-avila deleted the fix/response-format-image-tools branch March 19, 2026 19:33
jcbartle pushed a commit to jcbartle/LibreChat that referenced this pull request May 11, 2026
danny-avila#12310)

* fix: Set response format for agent tools in DALLE3, FluxAPI, and StableDiffusion classes

- Added logic to set `responseFormat` to 'content_and_artifact' when `isAgent` is true in DALLE3.js, FluxAPI.js, and StableDiffusion.js.

* test: Add regression tests for image tool agent mode in imageTools-agent.spec.js

- Introduced a new test suite for DALLE3, FluxAPI, and StableDiffusion classes to verify that the invoke() method returns a ToolMessage with base64 in artifact.content, ensuring it is not serialized into content.
- Validated that responseFormat is set to 'content_and_artifact' when isAgent is true, and confirmed the correct handling of base64 data in the response.

* fix: handle agent error paths and generateFinetunedImage in image tools

- StableDiffusion._call() was returning a raw string on API error, bypassing
  returnValue() and breaking the content_and_artifact contract when isAgent is true
- FluxAPI.generateFinetunedImage() had no isAgent branch; it would call
  processFileURL (unset in agent context) instead of fetching and returning
  the base64 image as an artifact tuple
- Add JSDoc to all three responseFormat assignments clarifying why LangChain
  requires this property for correct ToolMessage construction

* test: expand image tool agent mode regression suite

- Add env var save/restore in beforeEach/afterEach to prevent test pollution
- Add error path tests for all three tools verifying ToolMessage content and
  artifact are correctly populated when the upstream API fails
- Add generate_finetuned action test for FluxAPI covering the new agent branch
  in generateFinetunedImage

* chore: fix lint errors in FluxAPI and imageTools-agent spec

* chore: fix import ordering in imageTools-agent spec
ThomasVuNguyen pushed a commit to ThomasVuNguyen/LibreChat that referenced this pull request Jul 15, 2026
danny-avila#12310)

* fix: Set response format for agent tools in DALLE3, FluxAPI, and StableDiffusion classes

- Added logic to set `responseFormat` to 'content_and_artifact' when `isAgent` is true in DALLE3.js, FluxAPI.js, and StableDiffusion.js.

* test: Add regression tests for image tool agent mode in imageTools-agent.spec.js

- Introduced a new test suite for DALLE3, FluxAPI, and StableDiffusion classes to verify that the invoke() method returns a ToolMessage with base64 in artifact.content, ensuring it is not serialized into content.
- Validated that responseFormat is set to 'content_and_artifact' when isAgent is true, and confirmed the correct handling of base64 data in the response.

* fix: handle agent error paths and generateFinetunedImage in image tools

- StableDiffusion._call() was returning a raw string on API error, bypassing
  returnValue() and breaking the content_and_artifact contract when isAgent is true
- FluxAPI.generateFinetunedImage() had no isAgent branch; it would call
  processFileURL (unset in agent context) instead of fetching and returning
  the base64 image as an artifact tuple
- Add JSDoc to all three responseFormat assignments clarifying why LangChain
  requires this property for correct ToolMessage construction

* test: expand image tool agent mode regression suite

- Add env var save/restore in beforeEach/afterEach to prevent test pollution
- Add error path tests for all three tools verifying ToolMessage content and
  artifact are correctly populated when the upstream API fails
- Add generate_finetuned action test for FluxAPI covering the new agent branch
  in generateFinetunedImage

* chore: fix lint errors in FluxAPI and imageTools-agent spec

* chore: fix import ordering in imageTools-agent spec
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