The problem you came with
You walked the whole route - chunks, embeddings, search, context assembly, generation. Each chapter showed its stage in isolation. But in a live system they all converge into one thing: an HTTP request to the LLM and a response from it. This is ordinary JSON. And until you see this JSON in full, with every field in its place, RAG stays a set of separate ideas rather than one mechanism.
Here we take apart one real exchange with the model: the request you send and the response that comes back. The fields are real - this is the format of the Anthropic Messages API (platform.claude.com/docs/en/api/messages). Each functional block is labelled twice: what it does technically and what role it plays in the RAG pipeline. This is that same retrieve-augment-generate assembly from the paper Lewis et al., 2020 (arxiv.org/abs/2005.11401), but no longer on a diagram - in the bytes that go over the wire.
One payload through the whole pipeline
A RAG request to the Anthropic Messages API is arranged like this: you put the grounding instructions in system, the assembled context and the question in messages, and you express the search itself as a tool call (tools plus tool_choice) (platform.claude.com/docs/en/api/messages). The model answers not with a single text but with an array of content blocks: reasoning (thinking), a search request (tool_use), and the final text. The stop_reason field tells why the model stopped, and usage - how many tokens it cost (platform.claude.com/docs/en/api/messages).
Below is a real exchange of four turns: you send the question with a description of the search tool, the model asks to call the search (tool_use), you return the found chunks (tool_result), the model writes a grounded answer.
Turn 1. Request: the question plus a description of the search tool
system is the grounding layer: a firm instruction to answer only from what was found and to honestly admit a gap (platform.claude.com/docs/en/api/messages). In RAG terms this is exactly the instruction of the generation stage from generation.html. tools describes search as a function the model can call - this is the declaration of the retrieve step from the paper Lewis et al., 2020 (arxiv.org/abs/2005.11401), expressed in the tool-use schema (platform.claude.com/docs/en/docs/build-with-claude/tool-use/overview). tool_choice: auto leaves the model to decide whether search is needed (platform.claude.com/docs/en/docs/build-with-claude/tool-use/overview). thinking enables extended reasoning with a token budget (platform.claude.com/docs/en/docs/build-with-claude/extended-thinking).
Turn 2. Response: the model reasons and asks to call the search
The thinking block is the model's reasoning before acting; in RAG this is the visible plan of the retrieve stage, not the final answer (platform.claude.com/docs/en/docs/build-with-claude/extended-thinking). The tool_use block is exactly the search request: the model asks to call search_docs with a concrete query and top_k (platform.claude.com/docs/en/docs/build-with-claude/tool-use/overview). stop_reason: tool_use is a control signal: the model stopped not because it finished but because it is waiting for the tool result; your code must run the search and return the result (platform.claude.com/docs/en/api/messages). usage is a budget and cost signal: input_tokens and output_tokens for this turn (platform.claude.com/docs/en/api/messages); in RAG a bloated input_tokens is the first sign that the assembled context is too large (see assemble-context.html).
Turn 3. Request with tool_result: returning the found chunks
Your code runs the search (the retrieve stage: query -> vector -> top-k by cosine, as in search.html), then continues the same conversation, appending the assistant's response and a tool_result block with the found chunks. The vector shape and the cosine metric are from the OpenAI Embeddings guide (developers.openai.com/api/docs/guides/embeddings).
tool_result is the return of the retrieve stage into the conversation: linked to the request by tool_use_id, carrying the found chunks as text (platform.claude.com/docs/en/docs/build-with-claude/tool-use/overview). Inside each chunk are pipeline-stage metadata: source/section/date come from chunking (chunking.html), while cosine/rank come from search (search.html, the cosine metric per the OpenAI Embeddings guide, developers.openai.com/api/docs/guides/embeddings). This block is exactly the Augmented step from Lewis et al., 2020: what was found is slipped into the model's context before generation (arxiv.org/abs/2005.11401).
Turn 4 (final answer). The model's grounded answer
Here content is one text block: the final grounded answer with a link to source, as the instruction in system required. This is the Generation stage from Lewis et al., 2020 (arxiv.org/abs/2005.11401); the link to the concrete fields is described in generation.html. stop_reason: end_turn is a control signal that the model finished on its own, not because of a limit (platform.claude.com/docs/en/api/messages). usage.input_tokens grew from 412 to 638 - this is the price of the supplied context: that same budget signal by which assemble-context.html decides what to trim.
A map of the blocks: function and role in RAG
A greppable table: each functional block of the payload, its fields, its technical function, and its domain role in the RAG pipeline. This is the map of blocks for the drill interaction above; with JS off it doubles as a static list under the payload.
- model (
model) - which model to call; choice of the generator for the Generation stage, affects the length limit and cost. - budget (
max_tokens) - ceiling on answer length; cost and latency control of the Generation stage. - thinking-config (
thinking.type,thinking.budget_tokens) - enable extended reasoning and its budget; reasoning budget for the retrieve and generation stages. - system (
system) - the model's system instruction; grounding: answer only from the context plus cite the source (generation.html). - tools (
tools[].name,description,input_schema) - description of the available tools; declaration of the Retrieve step as a callable function (Lewis et al., 2020). - tool-choice (
tool_choice.type) - allow or force a tool call; control over whether to run retrieve. - messages-user (
messages[].role=user,content) - the user's turn; the question - the input of the whole pipeline. - messages-assistant (
messages[].role=assistant,content[]) - the model's turn in the history; saved reasoning and search request to continue the dialogue. - response-id (
id,type,role,model) - identifier and type of the response message; binding of the dialogue turn, request tracing. - thinking-block (
content[].type=thinking,thinking,signature) - the model's visible reasoning; reasoning: the plan of the retrieve stage, not the final answer. - tool-use (
content[].type=tool_use,id,name,input) - the model's request to call a tool; the Retrieve call: query and top_k go to the search (search.html). - tool-result (
tool_result.tool_use_id,content[]) - returning the tool result into the dialogue; Augmented: the found top-k chunks are slipped into the context (assemble-context.html). - chunk-meta (
source,section,date) - chunk metadata; provenance: set at the chunking stage (chunking.html). - retrieval-score (
cosine,rank) - closeness score and position in the top-k; retrieve quality: cosine 0..1, ranking (search.html). - text-answer (
content[].type=text,text) - the final answer text; Generation: the grounded answer with a link to source. - stop-reason (
stop_reason,stop_sequence) - why the model stopped; control signal: tool_use -> run the search; end_turn -> done. - usage (
usage.input_tokens,usage.output_tokens) - token spend per turn; cost and budget signal: a rise in input_tokens = bloated context (assemble-context.html).
Interaction: drill across the payload blocks
The rendered payload is not a picture but a map. At the top level (zoom 0) you see the whole exchange of four turns: request, tool_use, tool_result, answer. Each functional block from the table above highlights on hover. One click or Enter on a block is a semantic zoom inside it (zoom 1): the block takes the stage, and beside it unfolds its annotation card with two lines - what it does technically and what role it plays in RAG, plus a link to the owning chapter (for example, tool_use -> search.html, usage -> assemble-context.html). This is exactly two zoom levels: the whole payload -> one block up close. Going back (Esc or the back button) pulls the camera out to the full payload.
With JS off, the block map works as the static labelled table above plus the JSON itself with captions - the reader loses nothing.
Sources
- Anthropic. Messages API reference (model, max_tokens, system, messages, content blocks, stop_reason, stop_sequence, usage). platform.claude.com/docs/en/api/messages
- Anthropic. Tool use (tools, tool_choice, tool_use, tool_result, tool_use_id, input_schema). platform.claude.com/docs/en/docs/build-with-claude/tool-use/overview
- Anthropic. Extended thinking (thinking blocks, budget_tokens). platform.claude.com/docs/en/docs/build-with-claude/extended-thinking
- Lewis et al., 2020. Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks. arxiv.org/abs/2005.11401
- OpenAI. Embeddings guide (vector shape, cosine similarity). developers.openai.com/api/docs/guides/embeddings
Try it yourself
- Open the drill on the
tool_useblock (zoom 1) and trace howinput.queryandtop_kgo into the retrieve stage; check against search.html. - Expand the
tool_resultblock and find inside the chunk the fieldssource/section/date(from chunking) andcosine/rank(from search) - one block carries the traces of two pipeline stages at once. - Compare
usage.input_tokensin turn 2 (412) and in turn 4 (638): expand theusageblock and confirm that the growth is the price of the supplied context, that same budget signal from assemble-context.html.
What is next
About this recipe
- Part of the BrewPage Cookbook.
- Published live at brewpage.app.