# createToolResultFork `createToolResultFork` builds the input and the send options a client needs to answer a suspended tool call. With the Vercel codec a client tool result opens a new reply run rather than re-entering the suspended run, so two clients answering the same call land on segregated sibling branches instead of colliding on one shared run. You need it on the generic hooks path, where you drive [`view.send`](https://ably.com/docs/ai-transport/api/javascript/core/client-session.md) yourself. The [`ChatTransport`](https://ably.com/docs/ai-transport/api/javascript/vercel/chat-transport.md) performs the same construction internally, so an application using `useChat` never calls this. #### Javascript ``` // Client code. import { createToolResultFork } from '@ably/ai-transport/vercel'; const { input, sendOptions } = createToolResultFork({ runMessages, parentCodecMessageId, toolCallId, result: { output }, supersedesRunId, }); const forked = await view.send([input], sendOptions); ``` ## Build a tool-result fork `createToolResultFork(params: ToolResultForkParams): { input: VercelInput, sendOptions: SendOptions }` The fork's parameters all come from the tree, because message order alone does not identify the suspended run. `view.runOf(codecMessageId)` gives the run that owns the assistant message holding the tool call, and [`tree.getRunNode(runId)`](https://ably.com/docs/ai-transport/api/react/core/use-tree.md#get-run-node) gives the node whose `parentCodecMessageId` and `projection` the fork needs. The returned input addresses a fresh assistant codec-message-id and carries a copy of the suspended run's whole message list, each entry re-minted under a new id. Seeding the whole run rather than only the current assistant message keeps context across sequential client tool calls, so a run that already resolved two tool calls carries both into the fork. ### Parameters | Parameter | Required | Description | Type | | --- | --- | --- | --- | | runMessages | required | The suspended run's full message list, read as `codec.getMessages(node.projection)`. The entry carrying `toolCallId` becomes the result's target. | `CodecMessage[]` | | parentCodecMessageId | required | The fork's structural parent, which is the suspended run's own input node from `node.parentCodecMessageId`. It roots the fork as a same-parent sibling of the suspended run instead of a detached root. | String | | toolCallId | required | The tool call being resolved. | String | | result | required | The resolution. |
| | supersedesRunId | required | The `runId` of the suspended run this fork resolves, from `node.runId`. The tree then hides that run from branch selection. | String |
| Property | Description | Type | | --- | --- | --- | | output | The value the tool produced. Set this for a success, and omit `errorMessage`. | Unknown | | errorMessage | Why the tool failed. Set this for a failure, and omit `output`. | String |
Exactly one of `output` and `errorMessage` is set. ### Returns `{ input: VercelInput, sendOptions: SendOptions }`. Pass both to `view.send([input], sendOptions)`. The send options carry `parent`, `role: 'assistant'`, and `supersedes`, and deliberately carry no `runId`. The agent mints the fork's run id when it publishes `ai-run-start`, and the tree reconciles the client's optimistic reply run onto it by the tool result's codec-message-id. The `assistant` role marks the run-less input as a reconstructed assistant turn, so the tree reads it as a reply run rather than a user prompt. Throws an [`ErrorInfo`](https://ably.com/docs/ai-transport/api/errors.md#errorinfo) with code `40003` when no entry in `runMessages` carries `toolCallId`, since the run does not own that call. ## Example Resolve a pending client tool call, then wake the agent so it picks the result up off the session: ### Javascript ``` // Client code. import { createToolResultFork, createUIMessageCodec } from '@ably/ai-transport/vercel'; const codec = createUIMessageCodec(); async function resolveToolCall(view, tree, pending, toolCallId, output) { const node = tree.getRunNode(view.runOf(pending.codecMessageId).runId); if (!node) return; const { input, sendOptions } = createToolResultFork({ runMessages: codec.getMessages(node.projection), parentCodecMessageId: node.parentCodecMessageId, toolCallId, result: { output }, supersedesRunId: node.runId, }); const forked = await view.send([input], sendOptions); await fetch('/api/chat', { method: 'POST', body: JSON.stringify(forked.toInvocation().toJSON()), }); } ``` ## Related Topics - [Chat transport](https://ably.com/docs/ai-transport/api/javascript/vercel/chat-transport.md): API reference for the AI Transport Vercel ChatTransport adapter and the Vercel-bound createClientSession and createAgentSession factories. - [Codec](https://ably.com/docs/ai-transport/api/javascript/vercel/codec.md): API reference for createUIMessageCodec, the factory for the pre-built AI Transport codec for the Vercel AI SDK. - [Run outcome](https://ably.com/docs/ai-transport/api/javascript/vercel/run-outcome.md): API reference for vercelRunOutcome, the helper that maps a Vercel streamText finishReason and run.pipe result to a VercelRunOutcome object for run.suspend or run.end. ## Documentation Index To discover additional Ably documentation: 1. Fetch [llms.txt](https://ably.com/llms.txt) for the canonical list of available pages. 2. Identify relevant URLs from that index. 3. Fetch target pages as needed. Avoid using assumed or outdated documentation paths.