[{"data":1,"prerenderedAt":929},["ShallowReactive",2],{"docs:\u002Fdocs\u002Fguides\u002Ftools":3,"docs:navigation":806,"docs:surround:\u002Fdocs\u002Fguides\u002Ftools":924},{"id":4,"title":5,"body":6,"description":798,"extension":799,"meta":800,"navigation":99,"navigationTitle":801,"path":802,"seo":803,"stem":804,"__hash__":805},"docs\u002Fdocs\u002F3.guides\u002F2.tools.md","Tools",{"type":7,"value":8,"toc":792},"minimark",[9,13,18,38,369,464,467,498,501,505,512,723,734,738,769,773,788],[10,11,12],"p",{},"A model can only describe what to do; a tool lets it act. Tools are typed functions that an\nagent calls with validated arguments, running on your server with your database and secrets.",[14,15,17],"h2",{"id":16},"writing-a-tool","Writing a Tool",[10,19,20,21,25,26,29,30,33,34,37],{},"Each file in ",[22,23,24],"code",{},"server\u002Ftools"," default-exports one tool. ",[22,27,28],{},"defineAgentTool"," is auto-imported in Nuxt;\nin Void, import it from ",[22,31,32],{},"@nuxtagentic-pro\u002Fserver"," and pass the tools to ",[22,35,36],{},"defineVoidAgentic",". This\ntool from the starter calculates monthly recurring revenue:",[39,40,46],"pre",{"className":41,"code":42,"filename":43,"language":44,"meta":45,"style":45},"language-ts shiki shiki-themes github-dark-default","import { and, count, eq } from 'drizzle-orm'\nimport { z } from 'zod'\nimport { customers } from '..\u002Fmodels\u002Fcustomers'\n\nconst monthlyPrice = { free: 0, pro: 49 }\n\nexport default defineAgentTool({\n  name: 'calculate_mrr',\n  description: 'Calculate monthly recurring revenue from customer plans in the current workspace',\n  input: z.object({}),\n  async handler(_input, { actor, database }) {\n    const rows = await database\n      .select({ plan: customers.plan, customers: count() })\n      .from(customers)\n      .where(and(eq(customers.workspace, actor.workspace), eq(customers.ownerId, actor.user.id)))\n      .groupBy(customers.plan)\n    const mrr = rows.reduce((total, row) => total + monthlyPrice[row.plan] * row.customers, 0)\n    return { currency: 'EUR', mrr, plans: rows }\n  },\n})\n","server\u002Ftools\u002Fcalculate-mrr.ts","ts","",[22,47,48,68,81,94,101,129,134,151,163,174,188,203,220,238,248,275,286,340,355,363],{"__ignoreMap":45},[49,50,53,57,61,64],"span",{"class":51,"line":52},"line",1,[49,54,56],{"class":55},"suJrU","import",[49,58,60],{"class":59},"sZEs4"," { and, count, eq } ",[49,62,63],{"class":55},"from",[49,65,67],{"class":66},"s9uIt"," 'drizzle-orm'\n",[49,69,71,73,76,78],{"class":51,"line":70},2,[49,72,56],{"class":55},[49,74,75],{"class":59}," { z } ",[49,77,63],{"class":55},[49,79,80],{"class":66}," 'zod'\n",[49,82,84,86,89,91],{"class":51,"line":83},3,[49,85,56],{"class":55},[49,87,88],{"class":59}," { customers } ",[49,90,63],{"class":55},[49,92,93],{"class":66}," '..\u002Fmodels\u002Fcustomers'\n",[49,95,97],{"class":51,"line":96},4,[49,98,100],{"emptyLinePlaceholder":99},true,"\n",[49,102,104,107,111,114,117,120,123,126],{"class":51,"line":103},5,[49,105,106],{"class":55},"const",[49,108,110],{"class":109},"sFSAA"," monthlyPrice",[49,112,113],{"class":55}," =",[49,115,116],{"class":59}," { free: ",[49,118,119],{"class":109},"0",[49,121,122],{"class":59},", pro: ",[49,124,125],{"class":109},"49",[49,127,128],{"class":59}," }\n",[49,130,132],{"class":51,"line":131},6,[49,133,100],{"emptyLinePlaceholder":99},[49,135,137,140,143,147],{"class":51,"line":136},7,[49,138,139],{"class":55},"export",[49,141,142],{"class":55}," default",[49,144,146],{"class":145},"sc3cj"," defineAgentTool",[49,148,150],{"class":149},"sQhOw","({\n",[49,152,154,157,160],{"class":51,"line":153},8,[49,155,156],{"class":59},"  name: ",[49,158,159],{"class":66},"'calculate_mrr'",[49,161,162],{"class":149},",\n",[49,164,166,169,172],{"class":51,"line":165},9,[49,167,168],{"class":59},"  description: ",[49,170,171],{"class":66},"'Calculate monthly recurring revenue from customer plans in the current workspace'",[49,173,162],{"class":149},[49,175,177,180,183,186],{"class":51,"line":176},10,[49,178,179],{"class":59},"  input: z.",[49,181,182],{"class":145},"object",[49,184,185],{"class":59},"({})",[49,187,162],{"class":149},[49,189,191,194,197,200],{"class":51,"line":190},11,[49,192,193],{"class":55},"  async",[49,195,196],{"class":145}," handler",[49,198,199],{"class":149},"(_input, { actor, database }) ",[49,201,202],{"class":59},"{\n",[49,204,206,209,212,214,217],{"class":51,"line":205},12,[49,207,208],{"class":55},"    const",[49,210,211],{"class":109}," rows",[49,213,113],{"class":55},[49,215,216],{"class":55}," await",[49,218,219],{"class":59}," database\n",[49,221,223,226,229,232,235],{"class":51,"line":222},13,[49,224,225],{"class":59},"      .",[49,227,228],{"class":145},"select",[49,230,231],{"class":59},"({ plan: customers.plan, customers: ",[49,233,234],{"class":145},"count",[49,236,237],{"class":59},"() })\n",[49,239,241,243,245],{"class":51,"line":240},14,[49,242,225],{"class":59},[49,244,63],{"class":145},[49,246,247],{"class":59},"(customers)\n",[49,249,251,253,256,259,262,264,267,270,272],{"class":51,"line":250},15,[49,252,225],{"class":59},[49,254,255],{"class":145},"where",[49,257,258],{"class":59},"(",[49,260,261],{"class":145},"and",[49,263,258],{"class":59},[49,265,266],{"class":145},"eq",[49,268,269],{"class":59},"(customers.workspace, actor.workspace), ",[49,271,266],{"class":145},[49,273,274],{"class":59},"(customers.ownerId, actor.user.id)))\n",[49,276,278,280,283],{"class":51,"line":277},16,[49,279,225],{"class":59},[49,281,282],{"class":145},"groupBy",[49,284,285],{"class":59},"(customers.plan)\n",[49,287,289,291,294,296,299,302,305,308,311,314,317,320,323,326,329,332,335,337],{"class":51,"line":288},17,[49,290,208],{"class":55},[49,292,293],{"class":109}," mrr",[49,295,113],{"class":55},[49,297,298],{"class":59}," rows.",[49,300,301],{"class":145},"reduce",[49,303,304],{"class":59},"((",[49,306,307],{"class":149},"total",[49,309,310],{"class":59},", ",[49,312,313],{"class":149},"row",[49,315,316],{"class":59},") ",[49,318,319],{"class":55},"=>",[49,321,322],{"class":59}," total ",[49,324,325],{"class":55},"+",[49,327,328],{"class":59}," monthlyPrice[row.plan] ",[49,330,331],{"class":55},"*",[49,333,334],{"class":59}," row.customers, ",[49,336,119],{"class":109},[49,338,339],{"class":59},")\n",[49,341,343,346,349,352],{"class":51,"line":342},18,[49,344,345],{"class":55},"    return",[49,347,348],{"class":59}," { currency: ",[49,350,351],{"class":66},"'EUR'",[49,353,354],{"class":59},", mrr, plans: rows }\n",[49,356,358,361],{"class":51,"line":357},19,[49,359,360],{"class":59},"  }",[49,362,162],{"class":149},[49,364,366],{"class":51,"line":365},20,[49,367,368],{"class":149},"})\n",[370,371,372,385],"table",{},[373,374,375],"thead",{},[376,377,378,382],"tr",{},[379,380,381],"th",{},"Option",[379,383,384],{},"Description",[386,387,388,406,416,426,439,452],"tbody",{},[376,389,390,396],{},[391,392,393],"td",{},[22,394,395],{},"name",[391,397,398,399,402,403],{},"What the model calls: letters, digits, ",[22,400,401],{},"_",", and ",[22,404,405],{},"-",[376,407,408,413],{},[391,409,410],{},[22,411,412],{},"description",[391,414,415],{},"Tells the model when to use the tool",[376,417,418,423],{},[391,419,420],{},[22,421,422],{},"input",[391,424,425],{},"A Zod object; arguments are validated before the handler runs",[376,427,428,433],{},[391,429,430],{},[22,431,432],{},"approval",[391,434,435,438],{},[22,436,437],{},"true"," holds every call for a person's approval",[376,440,441,446],{},[391,442,443],{},[22,444,445],{},"readOnly",[391,447,448,449],{},"Marks tools without side effects for MCP clients; defaults to ",[22,450,451],{},"!approval",[376,453,454,459],{},[391,455,456],{},[22,457,458],{},"handler",[391,460,461],{},[22,462,463],{},"(input, { actor, database, env, signal })",[10,465,466],{},"The handler context:",[468,469,470,481,486,492],"ul",{},[471,472,473,476,477,480],"li",{},[22,474,475],{},"actor",": the signed-in user, workspace, and role the agent acts for. Always filter by it, as\nthe example does, because the ",[22,478,479],{},"database"," is not scoped for you.",[471,482,483,485],{},[22,484,479],{},": the Drizzle D1 database.",[471,487,488,491],{},[22,489,490],{},"env",": the Worker bindings and secrets.",[471,493,494,497],{},[22,495,496],{},"signal",": aborts when the run is cancelled.",[10,499,500],{},"A thrown error goes back to the model, which can retry or explain.",[14,502,504],{"id":503},"pausing-risky-calls-for-approval","Pausing Risky Calls for Approval",[10,506,507,508,511],{},"Some calls should never run without a person's say, such as refunds or emails to customers. Set\n",[22,509,510],{},"approval: true",":",[39,513,516],{"className":41,"code":514,"filename":515,"language":44,"meta":45,"style":45},"import { z } from 'zod'\n\nexport default defineAgentTool({\n  name: 'issue_refund',\n  description: 'Refund an order. A person approves every refund before it runs.',\n  input: z.object({\n    orderNumber: z.string().min(1),\n    amount: z.number().positive(),\n    reason: z.string().min(1),\n  }),\n  approval: true,\n  handler: ({ orderNumber, amount }) => ({\n    refundId: `rf_${orderNumber}_${Math.round(amount * 100)}`,\n    status: 'refunded',\n  }),\n})\n","server\u002Ftools\u002Fissue-refund.ts",[22,517,518,528,532,542,551,560,568,590,606,623,630,639,663,703,713,719],{"__ignoreMap":45},[49,519,520,522,524,526],{"class":51,"line":52},[49,521,56],{"class":55},[49,523,75],{"class":59},[49,525,63],{"class":55},[49,527,80],{"class":66},[49,529,530],{"class":51,"line":70},[49,531,100],{"emptyLinePlaceholder":99},[49,533,534,536,538,540],{"class":51,"line":83},[49,535,139],{"class":55},[49,537,142],{"class":55},[49,539,146],{"class":145},[49,541,150],{"class":149},[49,543,544,546,549],{"class":51,"line":96},[49,545,156],{"class":59},[49,547,548],{"class":66},"'issue_refund'",[49,550,162],{"class":149},[49,552,553,555,558],{"class":51,"line":103},[49,554,168],{"class":59},[49,556,557],{"class":66},"'Refund an order. A person approves every refund before it runs.'",[49,559,162],{"class":149},[49,561,562,564,566],{"class":51,"line":131},[49,563,179],{"class":59},[49,565,182],{"class":145},[49,567,150],{"class":59},[49,569,570,573,576,579,582,584,587],{"class":51,"line":136},[49,571,572],{"class":59},"    orderNumber: z.",[49,574,575],{"class":145},"string",[49,577,578],{"class":59},"().",[49,580,581],{"class":145},"min",[49,583,258],{"class":59},[49,585,586],{"class":109},"1",[49,588,589],{"class":59},"),\n",[49,591,592,595,598,600,603],{"class":51,"line":153},[49,593,594],{"class":59},"    amount: z.",[49,596,597],{"class":145},"number",[49,599,578],{"class":59},[49,601,602],{"class":145},"positive",[49,604,605],{"class":59},"(),\n",[49,607,608,611,613,615,617,619,621],{"class":51,"line":165},[49,609,610],{"class":59},"    reason: z.",[49,612,575],{"class":145},[49,614,578],{"class":59},[49,616,581],{"class":145},[49,618,258],{"class":59},[49,620,586],{"class":109},[49,622,589],{"class":59},[49,624,625,628],{"class":51,"line":176},[49,626,627],{"class":59},"  })",[49,629,162],{"class":149},[49,631,632,635,637],{"class":51,"line":190},[49,633,634],{"class":59},"  approval: ",[49,636,437],{"class":109},[49,638,162],{"class":149},[49,640,641,644,647,650,652,655,658,660],{"class":51,"line":205},[49,642,643],{"class":145},"  handler",[49,645,646],{"class":59},": ({ ",[49,648,649],{"class":149},"orderNumber",[49,651,310],{"class":59},[49,653,654],{"class":149},"amount",[49,656,657],{"class":59}," }) ",[49,659,319],{"class":55},[49,661,662],{"class":59}," ({\n",[49,664,665,668,671,673,676,679,682,685,687,689,692,695,698,701],{"class":51,"line":222},[49,666,667],{"class":59},"    refundId: ",[49,669,670],{"class":66},"`rf_${",[49,672,649],{"class":59},[49,674,675],{"class":66},"}_${",[49,677,678],{"class":59},"Math",[49,680,681],{"class":66},".",[49,683,684],{"class":145},"round",[49,686,258],{"class":66},[49,688,654],{"class":59},[49,690,691],{"class":55}," *",[49,693,694],{"class":109}," 100",[49,696,697],{"class":66},")",[49,699,700],{"class":66},"}`",[49,702,162],{"class":59},[49,704,705,708,711],{"class":51,"line":240},[49,706,707],{"class":59},"    status: ",[49,709,710],{"class":66},"'refunded'",[49,712,162],{"class":59},[49,714,715,717],{"class":51,"line":250},[49,716,627],{"class":59},[49,718,162],{"class":149},[49,720,721],{"class":51,"line":277},[49,722,368],{"class":149},[10,724,725,726,729,730,733],{},"When the agent calls ",[22,727,728],{},"issue_refund",", the run pauses in ",[22,731,732],{},"waiting"," and the call appears in the\napprovals inbox with its exact arguments. Approving runs the handler once and resumes the run;\nrejecting ends the call without running it. A replayed call returns the stored result and never\nruns the write twice.",[14,735,737],{"id":736},"tools-you-get-without-writing-code","Tools You Get without Writing Code",[468,739,740,746,762],{},[471,741,742,745],{},[22,743,744],{},"web_fetch",": fetches a public web page as text. Private and local addresses are refused.",[471,747,748,749,752,753,756,757,681],{},"Model tools such as ",[22,750,751],{},"customer_list"," and ",[22,754,755],{},"customer_update",", from\n",[758,759,761],"a",{"href":760},"\u002Fdocs\u002Fguides\u002Fagentic-models","Agentic Models",[471,763,764,765,768],{},"Integration actions such as ",[22,766,767],{},"resend_send_email",", once a workspace connects and grants them.",[14,770,772],{"id":771},"reusing-tools-from-the-free-module","Reusing Tools from the Free Module",[10,774,775,776,778,779,310,781,402,783,785,786,681],{},"Tools written with the free module's ",[22,777,28],{}," keep working under Pro. Their handlers\nalso receive ",[22,780,475],{},[22,782,479],{},[22,784,490],{}," next to ",[22,787,496],{},[789,790,791],"style",{},"html pre.shiki code .suJrU, html code.shiki .suJrU{--shiki-default:#FF7B72}html pre.shiki code .sZEs4, html code.shiki .sZEs4{--shiki-default:#E6EDF3}html pre.shiki code .s9uIt, html code.shiki .s9uIt{--shiki-default:#A5D6FF}html pre.shiki code .sFSAA, html code.shiki .sFSAA{--shiki-default:#79C0FF}html pre.shiki code .sc3cj, html code.shiki .sc3cj{--shiki-default:#D2A8FF}html pre.shiki code .sQhOw, html code.shiki .sQhOw{--shiki-default:#FFA657}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);}",{"title":45,"searchDepth":70,"depth":70,"links":793},[794,795,796,797],{"id":16,"depth":70,"text":17},{"id":503,"depth":70,"text":504},{"id":736,"depth":70,"text":737},{"id":771,"depth":70,"text":772},"Give agents typed functions with defineAgentTool, and hold risky calls for approval.","md",{},null,"\u002Fdocs\u002Fguides\u002Ftools",{"title":5,"description":798},"docs\u002F3.guides\u002F2.tools","x3U47mOBLGx2XGiIEpRkWfrU43I2rAsvF4EVa453CeU",[807],{"title":808,"path":809,"stem":810,"children":811,"navigationTitle":801},"Introduction","\u002Fdocs","docs\u002F0.index",[812,813,831,835,883,887,891,920],{"title":808,"path":809,"stem":810,"navigationTitle":801},{"title":814,"path":815,"stem":816,"children":817,"page":830},"Getting Started","\u002Fdocs\u002Fgetting-started","docs\u002F1.getting-started",[818,822,826],{"title":819,"path":820,"stem":821,"navigationTitle":801},"Free module","\u002Fdocs\u002Fgetting-started\u002Ffree","docs\u002F1.getting-started\u002F1.free",{"title":823,"path":824,"stem":825,"navigationTitle":801},"Pro on Nuxt","\u002Fdocs\u002Fgetting-started\u002Fnuxt","docs\u002F1.getting-started\u002F2.nuxt",{"title":827,"path":828,"stem":829,"navigationTitle":801},"Pro on Void","\u002Fdocs\u002Fgetting-started\u002Fvoid","docs\u002F1.getting-started\u002F3.void",false,{"title":832,"path":833,"stem":834,"navigationTitle":801},"Concepts","\u002Fdocs\u002Fconcepts","docs\u002F2.concepts",{"title":836,"path":837,"stem":838,"children":839,"page":830},"Guides","\u002Fdocs\u002Fguides","docs\u002F3.guides",[840,844,848,852,856,857,861,863,867,871,875,879],{"title":841,"path":842,"stem":843,"navigationTitle":801},"Agents","\u002Fdocs\u002Fguides\u002Fagents","docs\u002F3.guides\u002F1.agents",{"title":845,"path":846,"stem":847,"navigationTitle":801},"Events","\u002Fdocs\u002Fguides\u002Fevents","docs\u002F3.guides\u002F10.events",{"title":849,"path":850,"stem":851,"navigationTitle":801},"Features","\u002Fdocs\u002Fguides\u002Ffeatures","docs\u002F3.guides\u002F11.features",{"title":853,"path":854,"stem":855,"navigationTitle":801},"Coding agents","\u002Fdocs\u002Fguides\u002Fcoding-agents","docs\u002F3.guides\u002F12.coding-agents",{"title":5,"path":802,"stem":804,"navigationTitle":801},{"title":858,"path":859,"stem":860,"navigationTitle":801},"Automations","\u002Fdocs\u002Fguides\u002Fautomations","docs\u002F3.guides\u002F3.automations",{"title":761,"path":760,"stem":862,"navigationTitle":801},"docs\u002F3.guides\u002F4.agentic-models",{"title":864,"path":865,"stem":866,"navigationTitle":801},"Outcomes","\u002Fdocs\u002Fguides\u002Foutcomes","docs\u002F3.guides\u002F5.outcomes",{"title":868,"path":869,"stem":870,"navigationTitle":801},"Integrations","\u002Fdocs\u002Fguides\u002Fintegrations","docs\u002F3.guides\u002F6.integrations",{"title":872,"path":873,"stem":874,"navigationTitle":801},"Prompt","\u002Fdocs\u002Fguides\u002Fprompt","docs\u002F3.guides\u002F7.prompt",{"title":876,"path":877,"stem":878,"navigationTitle":801},"Server logic","\u002Fdocs\u002Fguides\u002Fserver-logic","docs\u002F3.guides\u002F8.server-logic",{"title":880,"path":881,"stem":882,"navigationTitle":801},"Dashboard UI","\u002Fdocs\u002Fguides\u002Fui","docs\u002F3.guides\u002F9.ui",{"title":884,"path":885,"stem":886,"navigationTitle":801},"Deploy to Cloudflare","\u002Fdocs\u002Fdeploy","docs\u002F4.deploy",{"title":888,"path":889,"stem":890,"navigationTitle":801},"Upgrading","\u002Fdocs\u002Fupgrade","docs\u002F5.upgrade",{"title":892,"path":893,"stem":894,"children":895,"page":830},"Reference","\u002Fdocs\u002Freference","docs\u002F6.reference",[896,900,904,908,912,916],{"title":897,"path":898,"stem":899,"navigationTitle":801},"Configuration","\u002Fdocs\u002Freference\u002Fconfiguration","docs\u002F6.reference\u002F1.configuration",{"title":901,"path":902,"stem":903,"navigationTitle":801},"Composables","\u002Fdocs\u002Freference\u002Fcomposables","docs\u002F6.reference\u002F2.composables",{"title":905,"path":906,"stem":907,"navigationTitle":801},"Server utilities","\u002Fdocs\u002Freference\u002Fserver-utils","docs\u002F6.reference\u002F3.server-utils",{"title":909,"path":910,"stem":911,"navigationTitle":801},"Services","\u002Fdocs\u002Freference\u002Fservices","docs\u002F6.reference\u002F4.services",{"title":913,"path":914,"stem":915,"navigationTitle":801},"REST API","\u002Fdocs\u002Freference\u002Frest-api","docs\u002F6.reference\u002F5.rest-api",{"title":917,"path":918,"stem":919,"navigationTitle":801},"CLI","\u002Fdocs\u002Freference\u002Fcli","docs\u002F6.reference\u002F6.cli",{"title":921,"path":922,"stem":923,"navigationTitle":801},"Licensing & FAQ","\u002Fdocs\u002Flicensing","docs\u002F8.licensing",[925,927],{"title":853,"path":854,"stem":855,"description":926,"children":-1},"Let Claude Code or Codex create agents, automations and records in your app over MCP.",{"title":858,"path":859,"stem":860,"description":928,"children":-1},"Run agents on a schedule, from a webhook or on an event, with retries and outcomes.",1792672479672]