The :agentcore_harness wire profile: the Bedrock Converse envelope.
inline_function/3maps a Jido action (name + description + NimbleOptions schema) to a HarnessinlineFunction(client-side / return-of-control) tool.parse/1folds a Converse event sequence into%{stop_reason, tool_uses, text}, accumulating streamedtoolUse.inputfragments and assistant text deltas.resume_messages/2assembles the STRICT resume contract: the nextInvokeHarnessMUST carry both the assistanttoolUsemessage AND the usertoolResultmessage, because Harness does not persist the partial inline-tool turn. Callers never hand-assemble this.
Reuses ReqManagedAgents.ToolSchema's JSON-Schema builder for the input schema.
Summary
Functions
Fold a Converse response's event sequence into %{stop_reason, tool_uses, text}.
Assemble the two messages for the next InvokeHarness resume turn: the assistant
toolUse blocks AND the user toolResults.
Types
Functions
@spec parse([map()]) :: %{ stop_reason: String.t() | nil, tool_uses: [map()], text: String.t(), usage: map() | nil }
Fold a Converse response's event sequence into %{stop_reason, tool_uses, text}.
Tool blocks are accumulated keyed by toolUseId — the source of truth, since
Claude mints a fresh id per real tool call — and emitted in first-seen order.
Input toolUse deltas route to whichever block is active at their
contentBlockIndex (tracked per index).
Keying by id rather than contentBlockIndex makes parsing robust to a stream that
reuses an index across two distinct ids (observed live: a stream emitted
[{0, A}, {0, B}, {1, C}] — index 0 reused). An index-keyed fold dropped one tool
and duplicated the other, producing a duplicate-toolUseId resume that Bedrock
rejected; keying by id recovers both. A genuinely-reused id collapses to one block.
@spec resume_messages([map()], [tool_result()]) :: [map()]
Assemble the two messages for the next InvokeHarness resume turn: the assistant
toolUse blocks AND the user toolResults.
The harness does NOT persist the model's streamed assistant response into the
session — sending only the toolResult makes Bedrock reject the turn with
"the number of toolResult blocks ... exceeds the number of toolUse blocks of
previous turn" (live-verified). So we echo the assistant toolUse back.
results must contain one entry per tool_uses entry (same length, each
supplying the tool_use_id returned by that call). Bedrock rejects a turn whose
assistant message carries duplicate toolUseIds ("duplicate Ids at
messages.N.content"); parse/1 guarantees unique ids by keying tool blocks on
toolUseId, so a well-formed tool_uses never trips this.