Skip to content

[Bug]: aws-strands TypeScript adapter never carries ToolMessage.error onto the Bedrock toolResult status #2362

Description

@TheSeydiCharyyev

Describe the Bug

Follow-up to #2306. That issue listed four conversion sites — langchain/typescript, aws-strands/python, vercel-ai-sdk and mastra — and #2317 fixed all four. The TypeScript aws-strands adapter was not on that list, and it still drops the flag on every path.

integrations/aws-strands/typescript/src/agent.ts never reads error off an AG-UI tool message. Every error in that file is an exception message or a hook_error event. Three sites are affected, two of them direct twins of code #2317 already fixed on the Python side.

1. _buildStrandsHistory (declared at agent.ts:324, tool branch at agent.ts:402-415) hardcodes the status. This is the twin of agent.py:248, fixed in #2317:

} else if (role === "tool") {
  const toolCallId = (msg as { toolCallId?: string }).toolCallId || "";
  out.push({
    role: "user",
    content: [
      {
        toolResult: {
          toolUseId: toolCallId,
          content: [_buildToolResultContent(msg.content)],
          status: "success" as const,
        },
      },
    ],
  });
}

2. buildSnapshotMessages (declared at agent.ts:259, tool branch at agent.ts:298-306) rebuilds the client's own AG-UI tool message and drops both error and encryptedValue. This is the twin of _build_snapshot_messages at agent.py:205-212, also fixed in #2317. It is on the package's public surface: buildSnapshotMessages is exported from index.ts:5 and asserted in exports.test.ts:12.

const toolCallId = (msg as { toolCallId?: string }).toolCallId ?? "";
out.push({
  id: msgId,
  role: "tool",
  content: _coerceText(msg.content),
  toolCallId,
} as AguiToolMessage);

3. convertMessagesForStrandsSeed (declared at agent.ts:2642, tool branch at agent.ts:2710-2735) has the same hardcoded status: "success" as const. There is no Python twin for this one — the seed path is TypeScript only.

The type is already in place: ToolMessageSchema.error is z.string().optional() in sdks/typescript/packages/core/src/types.ts:143. No type change is needed, the same as in #2263.

I also checked whether the current behaviour is deliberate. No test under integrations/aws-strands/typescript/src/__tests__ reads error on a tool message, and the three buildSnapshotMessages tests (messages-snapshot.test.ts:223-262) cover only argument normalisation, id fabrication and role filtering. The status: "success" occurrences in the tests are mock inputs, not assertions about error.

Steps to Reproduce

  1. Use the TypeScript aws-strands adapter with a frontend tool.
  2. Have the frontend return an AG-UI ToolMessage with error set.
  3. On the next run, inspect the toolResult block the adapter hands to Strands: status is "success", so the model is told the call succeeded.
  4. Separately, inspect the MESSAGES_SNAPSHOT payload built by buildSnapshotMessages: the echoed tool message has neither error nor encryptedValue.

The Python adapter, on the same input, reports status: "error" and keeps both fields after #2317.

Expected Behavior

The TypeScript adapter follows the rule agreed on #2306: derive the framework flag from the presence of error. Concretely status: message.error ? "error" : "success" at the two Bedrock conversion sites, and a straight copy of error and encryptedValue in the snapshot echo — so the two aws-strands adapters behave the same on the same input.

Environment

integrations/aws-strands/typescript, as of origin/main
Related: #2306, #2317, #2263, #2361

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions