AI & Agent Dev Bug Sandbox logo
AI & Agent Dev Bug Sandbox
Back to Radar

Core: `DictPromptTemplate.Aformat` Is Never Called — The Async Prompt Path Uses Sync `Format`

In `_MultiModalMessagePromptTemplate.aformat`, the `DictPromptTemplate` branch incorrectly calls the synchronous `format()` instead of awaiting `aformat()`. This means any subclass overriding `aformat` is silently bypassed on the async path, breaking consistency with the sibling `StringPromptTemplate` and `ImagePromptTemplate` branches which correctly await their async variants.

mediumConfidence 98%Langchain-CoreAffected V1.6.0

Origin Analysis

The async method `_MultiModalMessagePromptTemplate.aformat` was likely copied from the synchronous `format` method, but only two of three type branches were converted to await the async variant. The `DictPromptTemplate` branch was left calling `prompt.format(**inputs)` instead of `await prompt.aformat(**inputs)`.
Run the provided Python snippet with `langchain-core` 1.6.0. It monkeypatches `DictPromptTemplate.format` and `DictPromptTemplate.aformat` to trace calls, then invokes `tmpl.format_messages(q="hi")` and `tmpl.aformat_messages(q="hi")`. The async call will print `'format (sync)'` instead of `'aformat (async)'`, demonstrating that `aformat` is never reached.

Fixing Code Block

--- a/libs/core/langchain_core/prompts/chat.py +++ b/libs/core/langchain_core/prompts/chat.py @@ -641,7 +641,7 @@ class _MultiModalMessagePromptTemplate(BaseMessagePromptTemplate): elif isinstance(prompt, DictPromptTemplate): - formatted_dict = prompt.format(**inputs) + formatted_dict = await prompt.aformat(**inputs) content.append(formatted_dict)
The fix aligns the `DictPromptTemplate` branch with the other branches by awaiting `aformat` instead of calling the synchronous `format`. This ensures the asynchronous contract is honored and subclasses that override `aformat` are no longer bypassed.

Edge Case Audit

This change is non-breaking for the standard `DictPromptTemplate` implementation because its `aformat` currently delegates to `format`. However, any third-party subclass that overrides `aformat` and expects it to be called only in certain contexts may now observe different behavior on the async path. If the override contains blocking I/O or heavy computation, it could block the event loop, but that is the intended semantic of `aformat`. To roll back, revert the single line to `prompt.format(**inputs)`. Regression tests should be added to prevent future divergence.

Ecosystem Topology