convertMessages
convertMessages(
messages,allowedToolNames?):BaseMessage<MessageStructure<MessageToolSet>,MessageType>[]
Defined in: _worktrees/docs-release/gaunt-sloth/packages/agent/src/modules/apiAgUiModule.ts:245
Convert a whole AG-UI history array to LangChain messages, applying TWO symmetric replay guards so a poisoned history can never abort every subsequent turn on the thread.
EXT-43 (forward, dangling-CALL): EXT-35’s per-message promotion is unconditional, which is correct
for a call that WILL be executed this turn. But when replaying HISTORY, promoting a STALLED text
call (one the client recorded but that never ran) yields an AIMessage with tool_calls and NO
following tool_result — a shape a strict provider (Anthropic) 400s on, where the pre-EXT-35
plain text was valid. So promotion is allowed ONLY when the assistant message is immediately
followed by a tool result message; a dangling call stays plain text (allowTextCallPromotion: false).
RC-18 (backward, orphan-RESULT): the mirror image. A replayed role:'tool' message whose matching
tool_call id is absent from EVERY PRECEDING assistant message is an ORPHAN — converting it to a
ToolMessage yields a tool result with no preceding AIMessage.tool_calls, which the same strict
provider 400s on (Invalid parameter: messages with role 'tool' must be a response to a preceding message with 'tool_calls', INVALID_TOOL_RESULTS). Such orphans arise when a terminal
(returnDirect) tool call’s result is reconstructed by the client without its parenting assistant
tool_call. We DROP the orphan (match on tool_call_id, NOT adjacency; keep genuine pairs; do NOT
fabricate a synthetic call — mirroring EXT-43’s demote-don’t-invent spirit). Ids are accumulated
in iteration order, so a result whose matching call appears only LATER is still an orphan.
RC-32 (tool NAME restoration): the AG-UI wire message for a tool result carries toolCallId
but no tool name, so a naively-converted ToolMessage has none — and every middleware that
inspects results by name is blind to it. frontend-image-injection keys on
msg.name === 'capture_image', so a captured photo reached the model on the resume turn (where
the graph builds the ToolMessage itself, with a name) and then vanished from every later turn,
leaving the model to answer questions about a picture it could no longer see. The name is
recoverable from the parenting assistant tool_call, which this function already walks for the
RC-18 guard, so it is resolved there and stamped back on.
The live middleware path (GthLangChainAgent, fixing the CURRENT turn) is unaffected — the two
guards and the name restoration are history-replay only.
Parameters
Section titled “Parameters”messages
Section titled “messages”AgUiWireMessage[]
allowedToolNames?
Section titled “allowedToolNames?”Set<string>
Returns
Section titled “Returns”BaseMessage<MessageStructure<MessageToolSet>, MessageType>[]