[{"data":1,"prerenderedAt":851},["ShallowReactive",2],{"docs-/docs/development/artifuncs-json":3},{"id":4,"title":5,"body":6,"description":843,"extension":844,"meta":845,"navigation":846,"path":847,"seo":848,"stem":849,"__hash__":850},"docs/docs/development/artifuncs-json.md","artifuncs.json",{"type":7,"value":8,"toc":833},"minimark",[9,16,23,26,31,213,217,364,368,406,409,413,422,520,539,543,554,603,610,627,632,643,726,729,733,736,769,777,781,822,829],[10,11,13],"h1",{"id":12},"artifuncsjson",[14,15,5],"code",{},[17,18,19,20,22],"p",{},"Every tool repo has an ",[14,21,5],{}," at its root. It declares the tool's interface: what type of tool it is, what inputs it takes, what outputs it produces, what settings users can tweak, and which external APIs it's allowed to call.",[17,24,25],{},"The file is read by the sandbox to render your tool's UI and validate its inputs and outputs. Invalid JSON blocks saving and publishing.",[27,28,30],"h2",{"id":29},"minimal-example","Minimal example",[32,33,38],"pre",{"className":34,"code":35,"language":36,"meta":37,"style":37},"language-json shiki shiki-themes github-light github-dark","{\n  \"name\": \"Sum\",\n  \"type\": \"INPUT_OUTPUT\",\n  \"language\": \"PYTHON\",\n  \"fields\": {\n    \"input\": {\n      \"a\": { \"type\": \"number\", \"default\": 0 },\n      \"b\": { \"type\": \"number\", \"default\": 0 }\n    },\n    \"output\": {\n      \"sum\": { \"type\": \"number\" }\n    }\n  }\n}\n","json","",[14,39,40,49,66,79,92,101,109,140,165,171,179,195,201,207],{"__ignoreMap":37},[41,42,45],"span",{"class":43,"line":44},"line",1,[41,46,48],{"class":47},"sVt8B","{\n",[41,50,52,56,59,63],{"class":43,"line":51},2,[41,53,55],{"class":54},"sj4cs","  \"name\"",[41,57,58],{"class":47},": ",[41,60,62],{"class":61},"sZZnC","\"Sum\"",[41,64,65],{"class":47},",\n",[41,67,69,72,74,77],{"class":43,"line":68},3,[41,70,71],{"class":54},"  \"type\"",[41,73,58],{"class":47},[41,75,76],{"class":61},"\"INPUT_OUTPUT\"",[41,78,65],{"class":47},[41,80,82,85,87,90],{"class":43,"line":81},4,[41,83,84],{"class":54},"  \"language\"",[41,86,58],{"class":47},[41,88,89],{"class":61},"\"PYTHON\"",[41,91,65],{"class":47},[41,93,95,98],{"class":43,"line":94},5,[41,96,97],{"class":54},"  \"fields\"",[41,99,100],{"class":47},": {\n",[41,102,104,107],{"class":43,"line":103},6,[41,105,106],{"class":54},"    \"input\"",[41,108,100],{"class":47},[41,110,112,115,118,121,123,126,129,132,134,137],{"class":43,"line":111},7,[41,113,114],{"class":54},"      \"a\"",[41,116,117],{"class":47},": { ",[41,119,120],{"class":54},"\"type\"",[41,122,58],{"class":47},[41,124,125],{"class":61},"\"number\"",[41,127,128],{"class":47},", ",[41,130,131],{"class":54},"\"default\"",[41,133,58],{"class":47},[41,135,136],{"class":54},"0",[41,138,139],{"class":47}," },\n",[41,141,143,146,148,150,152,154,156,158,160,162],{"class":43,"line":142},8,[41,144,145],{"class":54},"      \"b\"",[41,147,117],{"class":47},[41,149,120],{"class":54},[41,151,58],{"class":47},[41,153,125],{"class":61},[41,155,128],{"class":47},[41,157,131],{"class":54},[41,159,58],{"class":47},[41,161,136],{"class":54},[41,163,164],{"class":47}," }\n",[41,166,168],{"class":43,"line":167},9,[41,169,170],{"class":47},"    },\n",[41,172,174,177],{"class":43,"line":173},10,[41,175,176],{"class":54},"    \"output\"",[41,178,100],{"class":47},[41,180,182,185,187,189,191,193],{"class":43,"line":181},11,[41,183,184],{"class":54},"      \"sum\"",[41,186,117],{"class":47},[41,188,120],{"class":54},[41,190,58],{"class":47},[41,192,125],{"class":61},[41,194,164],{"class":47},[41,196,198],{"class":43,"line":197},12,[41,199,200],{"class":47},"    }\n",[41,202,204],{"class":43,"line":203},13,[41,205,206],{"class":47},"  }\n",[41,208,210],{"class":43,"line":209},14,[41,211,212],{"class":47},"}\n",[27,214,216],{"id":215},"top-level-keys","Top-level keys",[218,219,220,236],"table",{},[221,222,223],"thead",{},[224,225,226,230,233],"tr",{},[227,228,229],"th",{},"Key",[227,231,232],{},"Required",[227,234,235],{},"Description",[237,238,239,253,272,287,307,328,340,352],"tbody",{},[224,240,241,247,250],{},[242,243,244],"td",{},[14,245,246],{},"name",[242,248,249],{},"yes",[242,251,252],{},"Display name shown on the tool card.",[224,254,255,260,262],{},[242,256,257],{},[14,258,259],{},"type",[242,261,249],{},[242,263,264,267,268,271],{},[14,265,266],{},"INPUT_OUTPUT"," or ",[14,269,270],{},"IFRAME",". See below.",[224,273,274,279,281],{},[242,275,276],{},[14,277,278],{},"language",[242,280,249],{},[242,282,283,286],{},[14,284,285],{},"PYTHON",".",[224,288,289,294,297],{},[242,290,291],{},[14,292,293],{},"layout",[242,295,296],{},"no",[242,298,299,302,303,306],{},[14,300,301],{},"HORIZONTAL"," (default) or ",[14,304,305],{},"VERTICAL",". Controls how input and output panels stack.",[224,308,309,314,320],{},[242,310,311],{},[14,312,313],{},"fields",[242,315,316,317,319],{},"yes (for ",[14,318,266],{},")",[242,321,322,323,286],{},"Input and output field declarations. See ",[324,325,327],"a",{"href":326},"/docs/development/fields","Fields",[224,329,330,335,337],{},[242,331,332],{},[14,333,334],{},"settings",[242,336,296],{},[242,338,339],{},"User-tunable values that persist across runs but aren't part of the per-run input.",[224,341,342,347,349],{},[242,343,344],{},[14,345,346],{},"userInstructions",[242,348,296],{},[242,350,351],{},"Free-text usage guidance shown to visitors above the tool form. See below.",[224,353,354,359,361],{},[242,355,356],{},[14,357,358],{},"apis",[242,360,296],{},[242,362,363],{},"Allowlist of external HTTP APIs the tool may call.",[27,365,366],{"id":259},[14,367,259],{},[369,370,371,391],"ul",{},[372,373,374,379,380,383,384,387,388,390],"li",{},[375,376,377],"strong",{},[14,378,266],{}," — The default. Your tool receives an ",[14,381,382],{},"input"," object, returns an ",[14,385,386],{},"output"," object. Inputs and outputs are rendered as forms from the ",[14,389,313],{}," block.",[372,392,393,397,398,402,403,405],{},[375,394,395],{},[14,396,270],{}," — Your tool is a self-contained web page rendered in an iframe (URL configured via the ",[399,400,401],"em",{},"General"," tab of the tool editor). ",[14,404,313],{}," are ignored.",[17,407,408],{},"The type is locked at tool creation and can't be changed.",[27,410,411],{"id":313},[14,412,313],{},[17,414,415,416,418,419,421],{},"Two sub-blocks: ",[14,417,382],{}," and ",[14,420,386],{},". Each maps a field name to a field declaration:",[32,423,425],{"className":34,"code":424,"language":36,"meta":37,"style":37},"\"fields\": {\n  \"input\": {\n    \"source\": { \"type\": \"text-field\", \"label\": \"Source\", \"default\": \"\" }\n  },\n  \"output\": {\n    \"result\": { \"type\": \"text-field\", \"label\": \"Result\" }\n  }\n}\n",[14,426,427,434,441,476,481,488,512,516],{"__ignoreMap":37},[41,428,429,432],{"class":43,"line":44},[41,430,431],{"class":61},"\"fields\"",[41,433,100],{"class":47},[41,435,436,439],{"class":43,"line":51},[41,437,438],{"class":54},"  \"input\"",[41,440,100],{"class":47},[41,442,443,446,448,450,452,455,457,460,462,465,467,469,471,474],{"class":43,"line":68},[41,444,445],{"class":54},"    \"source\"",[41,447,117],{"class":47},[41,449,120],{"class":54},[41,451,58],{"class":47},[41,453,454],{"class":61},"\"text-field\"",[41,456,128],{"class":47},[41,458,459],{"class":54},"\"label\"",[41,461,58],{"class":47},[41,463,464],{"class":61},"\"Source\"",[41,466,128],{"class":47},[41,468,131],{"class":54},[41,470,58],{"class":47},[41,472,473],{"class":61},"\"\"",[41,475,164],{"class":47},[41,477,478],{"class":43,"line":81},[41,479,480],{"class":47},"  },\n",[41,482,483,486],{"class":43,"line":94},[41,484,485],{"class":54},"  \"output\"",[41,487,100],{"class":47},[41,489,490,493,495,497,499,501,503,505,507,510],{"class":43,"line":103},[41,491,492],{"class":54},"    \"result\"",[41,494,117],{"class":47},[41,496,120],{"class":54},[41,498,58],{"class":47},[41,500,454],{"class":61},[41,502,128],{"class":47},[41,504,459],{"class":54},[41,506,58],{"class":47},[41,508,509],{"class":61},"\"Result\"",[41,511,164],{"class":47},[41,513,514],{"class":43,"line":111},[41,515,206],{"class":47},[41,517,518],{"class":43,"line":142},[41,519,212],{"class":47},[17,521,522,523,526,527,529,530,532,533,535,536,538],{},"The field name (e.g. ",[14,524,525],{},"source",") is the key your code reads from ",[14,528,382],{}," and writes to ",[14,531,386],{},". See the ",[324,534,327],{"href":326}," reference for every supported ",[14,537,259],{}," and option.",[27,540,541],{"id":334},[14,542,334],{},[17,544,545,546,549,550,553],{},"Same shape as ",[14,547,548],{},"fields.input",", but values live in a separate ",[399,551,552],{},"Settings"," panel and persist between runs. Use settings for things a user tweaks once and reuses (precision, API keys, default formats).",[32,555,557],{"className":34,"code":556,"language":36,"meta":37,"style":37},"\"settings\": {\n  \"precision\": { \"type\": \"number\", \"label\": \"Decimal places\", \"default\": 2 }\n}\n",[14,558,559,566,599],{"__ignoreMap":37},[41,560,561,564],{"class":43,"line":44},[41,562,563],{"class":61},"\"settings\"",[41,565,100],{"class":47},[41,567,568,571,573,575,577,579,581,583,585,588,590,592,594,597],{"class":43,"line":51},[41,569,570],{"class":54},"  \"precision\"",[41,572,117],{"class":47},[41,574,120],{"class":54},[41,576,58],{"class":47},[41,578,125],{"class":61},[41,580,128],{"class":47},[41,582,459],{"class":54},[41,584,58],{"class":47},[41,586,587],{"class":61},"\"Decimal places\"",[41,589,128],{"class":47},[41,591,131],{"class":54},[41,593,58],{"class":47},[41,595,596],{"class":54},"2",[41,598,164],{"class":47},[41,600,601],{"class":43,"line":68},[41,602,212],{"class":47},[17,604,605,606,609],{},"In your Python code, settings are available as the second argument to ",[14,607,608],{},"process",":",[32,611,615],{"className":612,"code":613,"language":614,"meta":37,"style":37},"language-python shiki shiki-themes github-light github-dark","def process(input, settings):\n    return { \"sum\": round(input[\"a\"] + input[\"b\"], settings[\"precision\"]) }\n","python",[14,616,617,622],{"__ignoreMap":37},[41,618,619],{"class":43,"line":44},[41,620,621],{},"def process(input, settings):\n",[41,623,624],{"class":43,"line":51},[41,625,626],{},"    return { \"sum\": round(input[\"a\"] + input[\"b\"], settings[\"precision\"]) }\n",[27,628,630],{"id":629},"userinstructions",[14,631,346],{},[17,633,634,635,638,639,642],{},"Optional free-text guidance for people using your tool. When set, it's shown in a\n\"How to use\" panel ",[375,636,637],{},"above the tool form"," on the public func page (",[14,640,641],{},"/f/\u003Chandle>",").\nUse it to explain what the tool expects, how to read the output, or any caveats.",[32,644,646],{"className":34,"code":645,"language":36,"meta":37,"style":37},"{\n  \"name\": \"CSV Cleaner\",\n  \"type\": \"INPUT_OUTPUT\",\n  \"language\": \"PYTHON\",\n  \"userInstructions\": \"Upload a CSV with a header row. Empty rows are dropped and columns are trimmed. Large files (>5 MB) may take a few seconds.\",\n  \"fields\": { \"input\": { \"...\": {} }, \"output\": { \"...\": {} } }\n}\n",[14,647,648,652,663,673,683,695,722],{"__ignoreMap":37},[41,649,650],{"class":43,"line":44},[41,651,48],{"class":47},[41,653,654,656,658,661],{"class":43,"line":51},[41,655,55],{"class":54},[41,657,58],{"class":47},[41,659,660],{"class":61},"\"CSV Cleaner\"",[41,662,65],{"class":47},[41,664,665,667,669,671],{"class":43,"line":68},[41,666,71],{"class":54},[41,668,58],{"class":47},[41,670,76],{"class":61},[41,672,65],{"class":47},[41,674,675,677,679,681],{"class":43,"line":81},[41,676,84],{"class":54},[41,678,58],{"class":47},[41,680,89],{"class":61},[41,682,65],{"class":47},[41,684,685,688,690,693],{"class":43,"line":94},[41,686,687],{"class":54},"  \"userInstructions\"",[41,689,58],{"class":47},[41,691,692],{"class":61},"\"Upload a CSV with a header row. Empty rows are dropped and columns are trimmed. Large files (>5 MB) may take a few seconds.\"",[41,694,65],{"class":47},[41,696,697,699,701,704,706,709,712,715,717,719],{"class":43,"line":103},[41,698,97],{"class":54},[41,700,117],{"class":47},[41,702,703],{"class":54},"\"input\"",[41,705,117],{"class":47},[41,707,708],{"class":54},"\"...\"",[41,710,711],{"class":47},": {} }, ",[41,713,714],{"class":54},"\"output\"",[41,716,117],{"class":47},[41,718,708],{"class":54},[41,720,721],{"class":47},": {} } }\n",[41,723,724],{"class":43,"line":111},[41,725,212],{"class":47},[17,727,728],{},"Line breaks in the string are preserved. It's plain text (not Markdown), so write\nit as you'd want it read.",[27,730,731],{"id":358},[14,732,358],{},[17,734,735],{},"Tools run in a locked-down sandbox with no outbound network access by default. To call an external HTTP API, declare it here:",[32,737,739],{"className":34,"code":738,"language":36,"meta":37,"style":37},"\"apis\": {\n  \"openai\": { \"domain\": \"api.openai.com\" }\n}\n",[14,740,741,748,765],{"__ignoreMap":37},[41,742,743,746],{"class":43,"line":44},[41,744,745],{"class":61},"\"apis\"",[41,747,100],{"class":47},[41,749,750,753,755,758,760,763],{"class":43,"line":51},[41,751,752],{"class":54},"  \"openai\"",[41,754,117],{"class":47},[41,756,757],{"class":54},"\"domain\"",[41,759,58],{"class":47},[41,761,762],{"class":61},"\"api.openai.com\"",[41,764,164],{"class":47},[41,766,767],{"class":43,"line":68},[41,768,212],{"class":47},[17,770,771,772,776],{},"Each entry must point to a ",[324,773,775],{"href":774},"/docs/sandbox/running-tools","Trusted API"," the platform recognizes. APIs that aren't on the allowlist will be rejected during review.",[27,778,780],{"id":779},"validation","Validation",[369,782,783,788,797,812,815],{},[372,784,785,787],{},[14,786,5],{}," must be valid JSON. The IDE blocks save on parse errors.",[372,789,790,128,792,128,794,796],{},[14,791,246],{},[14,793,259],{},[14,795,278],{}," are required.",[372,798,799,800,128,802,418,804,807,808,811],{},"For ",[14,801,266],{},[14,803,548],{},[14,805,806],{},"fields.output"," must exist and be objects (they can be empty ",[14,809,810],{},"{}",").",[372,813,814],{},"Field names must be valid identifiers — letters, digits, and underscores only.",[372,816,817,818,821],{},"Field types must be one of the ",[324,819,820],{"href":326},"supported types",". Unknown types render as an error placeholder.",[17,823,824,825,811],{},"Publishing runs the same checks plus a deeper review (see ",[324,826,828],{"href":827},"/docs/development/publishing","Publishing a tool",[830,831,832],"style",{},"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);}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":37,"searchDepth":51,"depth":51,"links":834},[835,836,837,838,839,840,841,842],{"id":29,"depth":51,"text":30},{"id":215,"depth":51,"text":216},{"id":259,"depth":51,"text":259},{"id":313,"depth":51,"text":313},{"id":334,"depth":51,"text":334},{"id":629,"depth":51,"text":346},{"id":358,"depth":51,"text":358},{"id":779,"depth":51,"text":780},"The configuration file at the root of every tool — declares type, fields, settings, and APIs.","md",{},true,"/docs/development/artifuncs-json",{"title":5,"description":843},"docs/development/artifuncs-json","I0cFth5tGXc0pszOcA4gtUVeTpmXbbZE4bnmyHWalbI",1781004913741]