[{"data":1,"prerenderedAt":298},["ShallowReactive",2],{"navigation_docs":3,"-hosts-ai-sdk":48,"-hosts-ai-sdk-surround":237,"host-views":240},[4,24],{"title":5,"path":6,"stem":7,"children":8,"icon":23},"Guide","\u002Fguide","1.guide\u002F01.index",[9,11,15,19],{"title":10,"path":6,"stem":7},"Getting Started",{"title":12,"path":13,"stem":14},"Defining Tools","\u002Fguide\u002Fdefining-tools","1.guide\u002F02.defining-tools",{"title":16,"path":17,"stem":18},"Validation and Errors","\u002Fguide\u002Fvalidation","1.guide\u002F03.validation",{"title":20,"path":21,"stem":22},"Moving a Package Over","\u002Fguide\u002Fmigrating","1.guide\u002F04.migrating","i-lucide-book-open",{"title":25,"path":26,"stem":27,"children":28,"icon":47},"Hosts","\u002Fhosts","2.hosts\u002F00.index",[29,31,35,39,43],{"title":30,"path":26,"stem":27},"Every host",{"title":32,"path":33,"stem":34},"MCP","\u002Fhosts\u002Fmcp","2.hosts\u002F01.mcp",{"title":36,"path":37,"stem":38},"Pi","\u002Fhosts\u002Fpi","2.hosts\u002F02.pi",{"title":40,"path":41,"stem":42},"OMP","\u002Fhosts\u002Fomp","2.hosts\u002F03.omp",{"title":44,"path":45,"stem":46},"AI SDK","\u002Fhosts\u002Fai-sdk","2.hosts\u002F04.ai-sdk","i-lucide-table",{"id":49,"title":44,"body":50,"description":231,"extension":232,"links":233,"meta":234,"navigation":111,"path":45,"seo":235,"stem":46,"__hash__":236},"docs\u002F2.hosts\u002F04.ai-sdk.md",{"type":51,"value":52,"toc":226},"minimark",[53,57,152,160,165,183,194,198,208,212,222],[54,55],"host-facts",{"name":56},"ai",[58,59,65],"pre",{"className":60,"code":61,"filename":62,"language":63,"meta":64,"style":64},"language-ts shiki shiki-themes tools tools tools","import { toAiTool, toAiTools } from \"@agntn\u002Ftools\u002Fai\";\nimport { slugTool, tools } from \".\u002Ftools.ts\";\n\nconst one = toAiTool(slugTool);\nconst all = toAiTools(tools); \u002F\u002F keyed by tool name\n","agent.ts","ts","",[66,67,68,91,106,113,132],"code",{"__ignoreMap":64},[69,70,73,77,81,84,88],"span",{"class":71,"line":72},"line",1,[69,74,76],{"class":75},"skH_V","import",[69,78,80],{"class":79},"s38Sx"," { toAiTool, toAiTools } ",[69,82,83],{"class":75},"from",[69,85,87],{"class":86},"shU9J"," \"@agntn\u002Ftools\u002Fai\"",[69,89,90],{"class":79},";\n",[69,92,94,96,99,101,104],{"class":71,"line":93},2,[69,95,76],{"class":75},[69,97,98],{"class":79}," { slugTool, tools } ",[69,100,83],{"class":75},[69,102,103],{"class":86}," \".\u002Ftools.ts\"",[69,105,90],{"class":79},[69,107,109],{"class":71,"line":108},3,[69,110,112],{"emptyLinePlaceholder":111},true,"\n",[69,114,116,119,122,125,129],{"class":71,"line":115},4,[69,117,118],{"class":75},"const",[69,120,121],{"class":79}," one ",[69,123,124],{"class":75},"=",[69,126,128],{"class":127},"sK71F"," toAiTool",[69,130,131],{"class":79},"(slugTool);\n",[69,133,135,137,140,142,145,148],{"class":71,"line":134},5,[69,136,118],{"class":75},[69,138,139],{"class":79}," all ",[69,141,124],{"class":75},[69,143,144],{"class":127}," toAiTools",[69,146,147],{"class":79},"(tools); ",[69,149,151],{"class":150},"scIB-","\u002F\u002F keyed by tool name\n",[153,154,155,156,159],"p",{},"The schema goes through the AI SDK's ",[66,157,158],{},"jsonSchema()"," with the core's validator attached. So the model sees the same JSON Schema every other host sees, and a bad input gets refused with the same lines. No second schema in Zod. That used to be the fourth copy.",[161,162,164],"h2",{"id":163},"the-output","The output",[153,166,167,170,171,174,175,178,179,182],{},[66,168,169],{},"execute"," returns the details with the text added: ",[66,172,173],{},"{ ...details, text }",". The AI SDK hands that object to the model as JSON, so it gets the structured facts and the sentence a human would read. When ",[66,176,177],{},"details"," isn't an object, you get ",[66,180,181],{},"{ details, text }",".",[153,184,185,186,189,190,193],{},"A details object with its own ",[66,187,188],{},"text"," field would lose it under the spread, so the adapter throws a ",[66,191,192],{},"ToolDefinitionError"," instead of guessing. Rename the field.",[161,195,197],{"id":196},"failures","Failures",[153,199,200,201,203,204,207],{},"A bad input is refused by the input schema before ",[66,202,169],{},". A result with ",[66,205,206],{},"isError"," throws its text, and the AI SDK turns any throw into a tool error the model can read.",[161,209,211],{"id":210},"types","Types",[153,213,214,217,218,221],{},[66,215,216],{},"toAiTool"," keeps the input and details types. When you export the tool from a package, annotate it with your own types, ",[66,219,220],{},"Tool\u003CSearchParams, AiToolOutput\u003CSearchDetails>>",". The inferred type points into the bundled TypeBox, and your declaration build can't name it.",[223,224,225],"style",{},"html pre.shiki code .skH_V, html code.shiki .skH_V{--shiki-light:var(--shiki-token-keyword);--shiki-default:var(--shiki-token-keyword);--shiki-dark:var(--shiki-token-keyword)}html pre.shiki code .s38Sx, html code.shiki .s38Sx{--shiki-light:var(--ui-text-highlighted);--shiki-default:var(--ui-text-highlighted);--shiki-dark:var(--ui-text-highlighted)}html pre.shiki code .shU9J, html code.shiki .shU9J{--shiki-light:var(--shiki-token-string);--shiki-default:var(--shiki-token-string);--shiki-dark:var(--shiki-token-string)}html pre.shiki code .sK71F, html code.shiki .sK71F{--shiki-light:var(--shiki-token-function);--shiki-default:var(--shiki-token-function);--shiki-dark:var(--shiki-token-function)}html pre.shiki code .scIB-, html code.shiki .scIB-{--shiki-light:var(--shiki-token-comment);--shiki-default:var(--shiki-token-comment);--shiki-dark:var(--shiki-token-comment)}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":64,"searchDepth":93,"depth":93,"links":227},[228,229,230],{"id":163,"depth":93,"text":164},{"id":196,"depth":93,"text":197},{"id":210,"depth":93,"text":211},"toAiTool turns a definition into an AI SDK tool. The TypeBox schema goes in as it is and nobody writes it again in Zod","md",null,{},{"title":44,"description":231},"aJR7t650KIa2EurECbWIge3VBkhxmJG9VjkIxszlskc",[238,233],{"title":40,"path":41,"stem":42,"description":239,"children":-1},"registerOmpTools puts every tool on OMP with an approval tier and a status line. Built around the TypeBox rewrite OMP does behind your back",[241,260,275,288],{"key":242,"rows":243,"registration":256,"fields":257},"mcp",[244,247,250,253],{"label":245,"value":246},"title","Text Slug",{"label":248,"value":249,"accent":111},"hints","readOnly, idempotent",{"label":251,"value":252},"inputSchema","text, separator",{"label":254,"value":255},"failure","isError: true","{\n  \"name\": \"text_slug\",\n  \"title\": \"Text Slug\",\n  \"description\": \"Turn a title into a lowercase URL slug. Letters and digits stay, accents lose their marks, the rest becomes the separator.\",\n  \"inputSchema\": {\n    \"type\": \"object\",\n    \"properties\": {\n      \"text\": {\n        \"type\": \"string\",\n        \"minLength\": 1,\n        \"maxLength\": 200,\n        \"pattern\": \"\\\\S\",\n        \"description\": \"Title to slug\"\n      },\n      \"separator\": {\n        \"enum\": [\n          \"-\",\n          \"_\",\n          \".\"\n        ],\n        \"description\": \"Joins the words. '-' when omitted\"\n      }\n    },\n    \"required\": [\n      \"text\"\n    ],\n    \"additionalProperties\": false\n  },\n  \"annotations\": {\n    \"readOnlyHint\": true,\n    \"destructiveHint\": false,\n    \"idempotentHint\": true,\n    \"openWorldHint\": false\n  }\n}",{"name":258,"label":245,"schema":251,"effect":259,"prompt":233,"run":233},"name","annotations",{"key":261,"rows":262,"registration":272,"fields":273},"pi",[263,265,268,270],{"label":264,"value":246},"label",{"label":266,"value":267,"accent":111},"prompt","snippet, 1 rule",{"label":269,"value":252},"parameters",{"label":254,"value":271},"thrown","{\n  \"name\": \"text_slug\",\n  \"label\": \"Text Slug\",\n  \"description\": \"Turn a title into a lowercase URL slug. Letters and digits stay, accents lose their marks, the rest becomes the separator.\",\n  \"promptSnippet\": \"Use text_slug to turn a title into a URL slug.\",\n  \"promptGuidelines\": [\n    \"Pass separator '_' for identifiers. The default '-' is for URLs.\"\n  ],\n  \"parameters\": {\n    \"type\": \"object\",\n    \"required\": [\n      \"text\"\n    ],\n    \"properties\": {\n      \"text\": {\n        \"type\": \"string\",\n        \"minLength\": 1,\n        \"maxLength\": 200,\n        \"pattern\": \"\\\\S\",\n        \"description\": \"Title to slug\"\n      },\n      \"separator\": {\n        \"enum\": [\n          \"-\",\n          \"_\",\n          \".\"\n        ],\n        \"description\": \"Joins the words. '-' when omitted\"\n      }\n    },\n    \"additionalProperties\": false\n  },\n  \"execute\": \"[function]\"\n}",{"name":258,"label":264,"schema":269,"effect":233,"prompt":274,"run":169},"promptSnippet",{"key":276,"rows":277,"registration":286,"fields":287},"omp",[278,279,282,284],{"label":264,"value":246},{"label":280,"value":281,"accent":111},"approval","read",{"label":269,"value":283},"Type.Unsafe(json)",{"label":254,"value":285},"isError or thrown","{\n  \"name\": \"text_slug\",\n  \"label\": \"Text Slug\",\n  \"description\": \"Turn a title into a lowercase URL slug. Letters and digits stay, accents lose their marks, the rest becomes the separator.\",\n  \"parameters\": {\n    \"unsafe\": {\n      \"type\": \"object\",\n      \"required\": [\n        \"text\"\n      ],\n      \"properties\": {\n        \"text\": {\n          \"type\": \"string\",\n          \"minLength\": 1,\n          \"maxLength\": 200,\n          \"pattern\": \"\\\\S\",\n          \"description\": \"Title to slug\"\n        },\n        \"separator\": {\n          \"enum\": [\n            \"-\",\n            \"_\",\n            \".\"\n          ],\n          \"description\": \"Joins the words. '-' when omitted\"\n        }\n      },\n      \"additionalProperties\": false\n    }\n  },\n  \"approval\": \"read\",\n  \"execute\": \"[function]\",\n  \"renderCall\": \"[function]\",\n  \"renderResult\": \"[function]\"\n}",{"name":258,"label":264,"schema":269,"effect":280,"prompt":233,"run":169},{"key":56,"rows":289,"registration":296,"fields":297},[290,291,292,295],{"label":245,"value":246},{"label":251,"value":158,"accent":111},{"label":293,"value":294},"output","details + text",{"label":254,"value":271},"{\n  \"title\": \"Text Slug\",\n  \"description\": \"Turn a title into a lowercase URL slug. Letters and digits stay, accents lose their marks, the rest becomes the separator.\",\n  \"inputSchema\": {\n    \"type\": \"object\",\n    \"required\": [\n      \"text\"\n    ],\n    \"properties\": {\n      \"text\": {\n        \"type\": \"string\",\n        \"minLength\": 1,\n        \"maxLength\": 200,\n        \"pattern\": \"\\\\S\",\n        \"description\": \"Title to slug\"\n      },\n      \"separator\": {\n        \"enum\": [\n          \"-\",\n          \"_\",\n          \".\"\n        ],\n        \"description\": \"Joins the words. '-' when omitted\"\n      }\n    },\n    \"additionalProperties\": false\n  },\n  \"execute\": \"[function]\"\n}",{"name":233,"label":245,"schema":251,"effect":233,"prompt":233,"run":169},1790784242042]