Normandy.Agents.ToolCallResponse
(normandy v2.2.0)
View Source
Response schema for agent outputs that may include tool calls.
This schema allows the LLM to either provide a final text response or request tool executions.
:thinking holds the response's thinking and redacted_thinking blocks
in their wire shape (string keys, with signature or data). They are sent
back unchanged, first, when the turn is replayed: a thinking model needs
them on the assistant message that carries the tool calls.
:prefix_key (see prefix_key/3) records the system prompt, tools and model the
response was produced under. The API accepts a thinking block only under that
same prefix and model, so Normandy.Components.AgentMemory.drop_stale_thinking/2 drops
thinking whose key no longer matches. It is never sent to the API.
:content_blocks holds the assistant turn as the API returned it: string-keyed,
API-shaped blocks in their order (thinking, text with its citations, tool_use,
server_tool_use, mcp_tool_use and their results), as
Claudio.Messages.Response.to_assistant_content/1 makes them. When it is not empty,
the turn is replayed from it unchanged, so the next request carries exactly what the
model produced; :content, :tool_calls and :thinking are what Normandy reads.
A response built without it (by hand, or stored before it existed) is rebuilt from
those three fields.
:stop_reason is why the model stopped (Normandy.LLM.Response.stop_reason/0), or
nil when the client did not say. The turn continues a :pause_turn response. It is
never sent to the API.
Summary
Functions
:content_blocks for a response's content blocks given as maps (a streamed message's
string-keyed blocks): Claudio.Messages.Response.to_assistant_content/1 of them, so a
streamed turn is replayed in the same shape as a non-streamed one.
A key for the part of a request a thinking block is bound to besides the messages: the system prompt, the tool set and the model. The API binds tools as a set sorted by name, so their order doesn't change the key.
The thinking and redacted_thinking blocks among response content blocks
(atom or string keys), in order and in wire shape, for :thinking.
Types
@type t() :: %Normandy.Agents.ToolCallResponse{ content: String.t() | nil, content_blocks: [map()], prefix_key: integer() | nil, stop_reason: Normandy.LLM.Response.stop_reason() | nil, thinking: [map()], tool_calls: [Normandy.Components.ToolCall.t()] }
Functions
:content_blocks for a response's content blocks given as maps (a streamed message's
string-keyed blocks): Claudio.Messages.Response.to_assistant_content/1 of them, so a
streamed turn is replayed in the same shape as a non-streamed one.
@spec prefix_key(term(), [map()], String.t() | nil) :: non_neg_integer()
A key for the part of a request a thinking block is bound to besides the messages: the system prompt, the tool set and the model. The API binds tools as a set sorted by name, so their order doesn't change the key.
The thinking and redacted_thinking blocks among response content blocks
(atom or string keys), in order and in wire shape, for :thinking.