[{"data":1,"prerenderedAt":2159},["ShallowReactive",2],{"page-\u002Fworkflows\u002Fagents":3,"all-pages":1825},{"id":4,"title":5,"body":6,"description":1816,"extension":1817,"meta":1818,"navigation":1631,"path":1819,"robots":1820,"seo":1821,"sitemap":1822,"stem":1823,"__hash__":1824},"content\u002F01.workflows\u002F09.agents.md","Agents",{"type":7,"value":8,"toc":1794},"minimark",[9,17,22,30,70,73,208,230,234,239,246,273,281,286,295,304,313,316,320,335,448,543,561,589,603,606,610,613,664,667,671,680,767,814,820,824,830,839,904,911,914,980,984,990,999,1044,1057,1067,1071,1074,1089,1092,1096,1100,1103,1210,1214,1217,1314,1318,1342,1364,1399,1423,1437,1441,1454,1584,1617,1677,1683,1721,1745,1749,1790],[10,11,12,16],"p",{},[13,14,15],"code",{},"step.agent"," is a first-class execution primitive for AI agents inside\nworkflows. Use it for work that needs judgment rather than a fixed command:\ntriaging nuclei findings, deduplicating noisy scan results, summarizing what\nchanged on a target since last week.",[18,19,21],"h2",{"id":20},"the-principle-explicit-capability-granting","The Principle: Explicit Capability Granting",[10,23,24,25,29],{},"An agent receives ",[26,27,28],"strong",{},"only"," what you explicitly give it:",[31,32,33,40,46,52,58,64],"ul",{},[34,35,36,39],"li",{},[13,37,38],{},"prompt"," — its instructions.",[34,41,42,45],{},[13,43,44],{},"context"," — named resources it may read.",[34,47,48,51],{},[13,49,50],{},"tools"," — the capabilities it may act with (shell, MCP servers).",[34,53,54,57],{},[13,55,56],{},"output"," — the file it must write its result to, and in what format.",[34,59,60,63],{},[13,61,62],{},"mode"," — whether it runs unattended, asks before side effects, or plans first.",[34,65,66,69],{},[13,67,68],{},"iterations"," — an optional cap on the agent's loop.",[10,71,72],{},"Nothing from the workflow leaks in implicitly. This makes agent steps safe to\nreason about: you always know exactly what an agent can see and do.",[74,75,80],"pre",{"className":76,"code":77,"language":78,"meta":79,"style":79},"language-bhw shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","step.agent(\n    prompt = \"\"\"\n        You are triaging vulnerability scanner results for a bug bounty\n        target. For each finding, decide whether it is a real, exploitable\n        issue or scanner noise. Discard findings on out-of-scope hosts.\n    \"\"\",\n    provider = provider.key(\"anthropic\u002Fpersonal\"),\n    model = model(\"default\"),\n    context = [\n        agent.context.path(\n            description = \"Raw nuclei findings to triage.\",\n            path = path.file(\"findings.txt\"),\n        ),\n        agent.context.path(\n            description = \"In-scope hosts; discard anything else.\",\n            path = path.file(\"scope.txt\"),\n        ),\n    ],\n    tools = [tool.shell(), mcp.server(\"github\")],\n    output = agent.output(path = path.file(\"agent-output.txt\")),\n)\n","bhw","",[13,81,82,90,96,102,108,114,120,126,132,138,144,150,156,162,167,173,179,184,190,196,202],{"__ignoreMap":79},[83,84,87],"span",{"class":85,"line":86},"line",1,[83,88,89],{},"step.agent(\n",[83,91,93],{"class":85,"line":92},2,[83,94,95],{},"    prompt = \"\"\"\n",[83,97,99],{"class":85,"line":98},3,[83,100,101],{},"        You are triaging vulnerability scanner results for a bug bounty\n",[83,103,105],{"class":85,"line":104},4,[83,106,107],{},"        target. For each finding, decide whether it is a real, exploitable\n",[83,109,111],{"class":85,"line":110},5,[83,112,113],{},"        issue or scanner noise. Discard findings on out-of-scope hosts.\n",[83,115,117],{"class":85,"line":116},6,[83,118,119],{},"    \"\"\",\n",[83,121,123],{"class":85,"line":122},7,[83,124,125],{},"    provider = provider.key(\"anthropic\u002Fpersonal\"),\n",[83,127,129],{"class":85,"line":128},8,[83,130,131],{},"    model = model(\"default\"),\n",[83,133,135],{"class":85,"line":134},9,[83,136,137],{},"    context = [\n",[83,139,141],{"class":85,"line":140},10,[83,142,143],{},"        agent.context.path(\n",[83,145,147],{"class":85,"line":146},11,[83,148,149],{},"            description = \"Raw nuclei findings to triage.\",\n",[83,151,153],{"class":85,"line":152},12,[83,154,155],{},"            path = path.file(\"findings.txt\"),\n",[83,157,159],{"class":85,"line":158},13,[83,160,161],{},"        ),\n",[83,163,165],{"class":85,"line":164},14,[83,166,143],{},[83,168,170],{"class":85,"line":169},15,[83,171,172],{},"            description = \"In-scope hosts; discard anything else.\",\n",[83,174,176],{"class":85,"line":175},16,[83,177,178],{},"            path = path.file(\"scope.txt\"),\n",[83,180,182],{"class":85,"line":181},17,[83,183,161],{},[83,185,187],{"class":85,"line":186},18,[83,188,189],{},"    ],\n",[83,191,193],{"class":85,"line":192},19,[83,194,195],{},"    tools = [tool.shell(), mcp.server(\"github\")],\n",[83,197,199],{"class":85,"line":198},20,[83,200,201],{},"    output = agent.output(path = path.file(\"agent-output.txt\")),\n",[83,203,205],{"class":85,"line":204},21,[83,206,207],{},")\n",[10,209,210,213,214,217,218,221,222,225,226,229],{},[13,211,212],{},"provider"," is ",[26,215,216],{},"required",": every agent names the project-enabled provider\nkey it runs with via ",[13,219,220],{},"provider.key(\"provider\u002Fkey-name\")",". The key must be\nenabled for the project; otherwise the editor reports an\n",[13,223,224],{},"unknown_provider_key"," diagnostic and the run fails. ",[13,227,228],{},"model"," is optional and\nonly selects which configured model to use.",[18,231,233],{"id":232},"parameters","Parameters",[235,236,237],"h3",{"id":38},[13,238,38],{},[10,240,241,242,245],{},"The instructions for the agent. A plain string, or a function evaluated at\nruntime with the run context (same as ",[13,243,244],{},"step.script"," content):",[74,247,249],{"className":76,"code":248,"language":78,"meta":79,"style":79},"step.agent(\n    prompt = lambda run: \"Summarize new findings for {}\".format(run.inputs[\"domain\"]),\n    ...\n    output = agent.output(path = path.file(\"agent-output.txt\")),\n)\n",[13,250,251,255,260,265,269],{"__ignoreMap":79},[83,252,253],{"class":85,"line":86},[83,254,89],{},[83,256,257],{"class":85,"line":92},[83,258,259],{},"    prompt = lambda run: \"Summarize new findings for {}\".format(run.inputs[\"domain\"]),\n",[83,261,262],{"class":85,"line":98},[83,263,264],{},"    ...\n",[83,266,267],{"class":85,"line":104},[83,268,201],{},[83,270,271],{"class":85,"line":110},[83,272,207],{},[235,274,276,278,279],{"id":275},"provider-and-model",[13,277,212],{}," and ",[13,280,228],{},[10,282,283,285],{},[13,284,212],{}," is mandatory and selects a stored API key; key values never appear\nin the workflow:",[74,287,289],{"className":76,"code":288,"language":78,"meta":79,"style":79},"provider = provider.key(\"anthropic\u002Fpersonal\")\n",[13,290,291],{"__ignoreMap":79},[83,292,293],{"class":85,"line":86},[83,294,288],{},[10,296,297,298,300,301,303],{},"The referenced key must be enabled for the project (the editor flags other\nreferences with an ",[13,299,224],{}," diagnostic). ",[13,302,228],{}," is optional:",[74,305,307],{"className":76,"code":306,"language":78,"meta":79,"style":79},"model(\"default\")\n",[13,308,309],{"__ignoreMap":79},[83,310,311],{"class":85,"line":86},[83,312,306],{},[10,314,315],{},"The name selects which configured model to use; the workflow stores only the\nreference.",[235,317,318],{"id":44},[13,319,44],{},[10,321,322,323,326,327,330,331,334],{},"A ",[26,324,325],{},"list"," of typed items built with ",[13,328,329],{},"agent.context.*"," (a dict is rejected).\nEach item pairs an LLM-facing ",[13,332,333],{},"description"," with a value passed by reference —\ncontents are never injected wholesale into the model context:",[74,336,338],{"className":76,"code":337,"language":78,"meta":79,"style":79},"context = [\n    # Inline text: plain strings, module inputs, config refs.\n    agent.context.text(\n        description = \"Target domain under review.\",\n        value = config.var(\"target_domain\"),\n    ),\n    # A file or directory (or glob) exposed through file tooling.\n    agent.context.path(\n        description = \"Raw nuclei output to triage.\",\n        path = path.file(\"findings.txt\"),\n    ),\n    # An artifact produced by step.upload_artifact or \u003Cactivity>.artifacts.\u003Cname>.\n    agent.context.artifact(\n        description = \"Signed scan results from the previous phase.\",\n        artifact = scan.artifacts.findings,\n    ),\n    # A project dataset table exposed through dataset tooling.\n    agent.context.dataset(\n        description = \"Previously seen subdomains for dedup.\",\n        dataset = dataset.table(\"subdomains\"),\n    ),\n]\n",[13,339,340,345,350,355,360,365,370,375,380,385,390,394,399,404,409,414,418,423,428,433,438,442],{"__ignoreMap":79},[83,341,342],{"class":85,"line":86},[83,343,344],{},"context = [\n",[83,346,347],{"class":85,"line":92},[83,348,349],{},"    # Inline text: plain strings, module inputs, config refs.\n",[83,351,352],{"class":85,"line":98},[83,353,354],{},"    agent.context.text(\n",[83,356,357],{"class":85,"line":104},[83,358,359],{},"        description = \"Target domain under review.\",\n",[83,361,362],{"class":85,"line":110},[83,363,364],{},"        value = config.var(\"target_domain\"),\n",[83,366,367],{"class":85,"line":116},[83,368,369],{},"    ),\n",[83,371,372],{"class":85,"line":122},[83,373,374],{},"    # A file or directory (or glob) exposed through file tooling.\n",[83,376,377],{"class":85,"line":128},[83,378,379],{},"    agent.context.path(\n",[83,381,382],{"class":85,"line":134},[83,383,384],{},"        description = \"Raw nuclei output to triage.\",\n",[83,386,387],{"class":85,"line":140},[83,388,389],{},"        path = path.file(\"findings.txt\"),\n",[83,391,392],{"class":85,"line":146},[83,393,369],{},[83,395,396],{"class":85,"line":152},[83,397,398],{},"    # An artifact produced by step.upload_artifact or \u003Cactivity>.artifacts.\u003Cname>.\n",[83,400,401],{"class":85,"line":158},[83,402,403],{},"    agent.context.artifact(\n",[83,405,406],{"class":85,"line":164},[83,407,408],{},"        description = \"Signed scan results from the previous phase.\",\n",[83,410,411],{"class":85,"line":169},[83,412,413],{},"        artifact = scan.artifacts.findings,\n",[83,415,416],{"class":85,"line":175},[83,417,369],{},[83,419,420],{"class":85,"line":181},[83,421,422],{},"    # A project dataset table exposed through dataset tooling.\n",[83,424,425],{"class":85,"line":186},[83,426,427],{},"    agent.context.dataset(\n",[83,429,430],{"class":85,"line":192},[83,431,432],{},"        description = \"Previously seen subdomains for dedup.\",\n",[83,434,435],{"class":85,"line":198},[83,436,437],{},"        dataset = dataset.table(\"subdomains\"),\n",[83,439,440],{"class":85,"line":204},[83,441,369],{},[83,443,445],{"class":85,"line":444},22,[83,446,447],{},"]\n",[449,450,451,467],"table",{},[452,453,454],"thead",{},[455,456,457,461,464],"tr",{},[458,459,460],"th",{},"Constructor",[458,462,463],{},"Value",[458,465,466],{},"Meaning",[468,469,470,487,509,528],"tbody",{},[455,471,472,478,484],{},[473,474,475],"td",{},[13,476,477],{},"agent.context.text(description, value)",[473,479,480,481],{},"string \u002F input \u002F ",[13,482,483],{},"config.*",[473,485,486],{},"Inline text, resolved at execution time",[455,488,489,494,506],{},[473,490,491],{},[13,492,493],{},"agent.context.path(description, path)",[473,495,496,499,500,499,503],{},[13,497,498],{},"path.file"," \u002F ",[13,501,502],{},"path.directory",[13,504,505],{},"path.glob",[473,507,508],{},"File access by reference",[455,510,511,516,525],{},[473,512,513],{},[13,514,515],{},"agent.context.artifact(description, artifact)",[473,517,518,521,522],{},[13,519,520],{},"step.upload_artifact(...)"," result or ",[13,523,524],{},"\u003Cactivity>.artifacts.\u003Cname>",[473,526,527],{},"Artifact by reference",[455,529,530,535,540],{},[473,531,532],{},[13,533,534],{},"agent.context.dataset(description, dataset)",[473,536,537],{},[13,538,539],{},"dataset.table(\"name\")",[473,541,542],{},"Dataset table by reference",[10,544,545,546,549,550,278,553,556,557,560],{},"Before the agent starts, every ",[13,547,548],{},"path",", ",[13,551,552],{},"artifact",[13,554,555],{},"dataset"," item is\n",[26,558,559],{},"materialized into its workspace",", and the preamble tells the agent where to\nfind each one:",[31,562,563,569,579],{},[34,564,565,568],{},[13,566,567],{},"agent.context.path"," — used in place (it is already a workspace path).",[34,570,571,574,575,578],{},[13,572,573],{},"agent.context.artifact"," — downloaded and extracted under ",[13,576,577],{},"context\u002F\u003Cactivity>\u002F\u003Cartifact>\u002F",".",[34,580,581,584,585,588],{},[13,582,583],{},"agent.context.dataset"," — exported to ",[13,586,587],{},"context\u002F\u003Ctable>.jsonl",", one record per line.\nThe export is bounded (1000 rows \u002F 4 MiB); when it is cut short the preamble\nsays so, so the agent treats it as a subset rather than the whole table.",[10,590,591,592,278,595,598,599,602],{},"Declaring any of them also grants the agent the ",[13,593,594],{},"read_file",[13,596,597],{},"list_dir","\ntools, so it can actually fetch what you gave it instead of only being told it\nexists. ",[13,600,601],{},"agent.context.text"," is resolved and inlined into the preamble instead.",[10,604,605],{},"Declaration order is preserved. Duplicate handling aside, keep descriptions\nspecific: they are the agent's only map to what each reference contains.",[235,607,608],{"id":50},[13,609,50],{},[10,611,612],{},"Grant capabilities explicitly. Without them, the agent can only read its\ncontext and produce text.",[449,614,615,624],{},[452,616,617],{},[455,618,619,622],{},[458,620,621],{},"Grant",[458,623,466],{},[468,625,626,636,650],{},[455,627,628,633],{},[473,629,630],{},[13,631,632],{},"tool.shell()",[473,634,635],{},"May run shell commands",[455,637,638,643],{},[473,639,640],{},[13,641,642],{},"mcp.server(name)",[473,644,645,646,649],{},"May use an already-configured MCP server (e.g. ",[13,647,648],{},"\"github\"",")",[455,651,652,657],{},[473,653,654],{},[13,655,656],{},"tool.task()",[473,658,659,660,663],{},"May delegate work to the specialized subagents declared in ",[13,661,662],{},"harness"," (see below)",[10,665,666],{},"MCP references point at connections configured outside the workflow;\ncredentials never appear in your workflow file. Grant the minimum needed: a\ntriage agent usually only needs read access to context plus one MCP server,\nwhile a report-drafting agent may need nothing but its context.",[235,668,670],{"id":669},"specialized-agents-harness","Specialized agents (harness)",[10,672,673,674,676,677,679],{},"A single agent runs every delegated task on its own model. When some work is\neasy (reconnaissance, parsing, triage) and some is hard (exploitation,\nreporting), that wastes money. Declare a ",[26,675,662],{}," so the agent can delegate\nthrough ",[13,678,656],{}," to specialized subagents, each with its own provider key\nand model:",[74,681,683],{"className":76,"code":682,"language":78,"meta":79,"style":79},"step.agent(\n    prompt = \"Map the target, then validate the most promising finding.\",\n    provider = provider.key(\"anthropic\u002Fmain\"),\n    model = model(\"claude-sonnet-4-5\"),\n    tools = [tool.shell(), tool.task()],\n    harness = agent.harness([\n        # A builtin role: only the model is overridden; recon's preamble and\n        # tools are inherited.\n        agent.specialist.recon(\n            provider = provider.key(\"openai\u002Fcheap\"),\n            model = model(\"gpt-4o-mini\"),\n        ),\n        # A builtin role on the strong model.\n        agent.specialist.exploit(model = model(\"claude-sonnet-4-5\")),\n    ]),\n    output = agent.output(path = path.file(\"report.md\")),\n)\n",[13,684,685,689,694,699,704,709,714,719,724,729,734,739,743,748,753,758,763],{"__ignoreMap":79},[83,686,687],{"class":85,"line":86},[83,688,89],{},[83,690,691],{"class":85,"line":92},[83,692,693],{},"    prompt = \"Map the target, then validate the most promising finding.\",\n",[83,695,696],{"class":85,"line":98},[83,697,698],{},"    provider = provider.key(\"anthropic\u002Fmain\"),\n",[83,700,701],{"class":85,"line":104},[83,702,703],{},"    model = model(\"claude-sonnet-4-5\"),\n",[83,705,706],{"class":85,"line":110},[83,707,708],{},"    tools = [tool.shell(), tool.task()],\n",[83,710,711],{"class":85,"line":116},[83,712,713],{},"    harness = agent.harness([\n",[83,715,716],{"class":85,"line":122},[83,717,718],{},"        # A builtin role: only the model is overridden; recon's preamble and\n",[83,720,721],{"class":85,"line":128},[83,722,723],{},"        # tools are inherited.\n",[83,725,726],{"class":85,"line":134},[83,727,728],{},"        agent.specialist.recon(\n",[83,730,731],{"class":85,"line":140},[83,732,733],{},"            provider = provider.key(\"openai\u002Fcheap\"),\n",[83,735,736],{"class":85,"line":146},[83,737,738],{},"            model = model(\"gpt-4o-mini\"),\n",[83,740,741],{"class":85,"line":152},[83,742,161],{},[83,744,745],{"class":85,"line":158},[83,746,747],{},"        # A builtin role on the strong model.\n",[83,749,750],{"class":85,"line":164},[83,751,752],{},"        agent.specialist.exploit(model = model(\"claude-sonnet-4-5\")),\n",[83,754,755],{"class":85,"line":169},[83,756,757],{},"    ]),\n",[83,759,760],{"class":85,"line":175},[83,761,762],{},"    output = agent.output(path = path.file(\"report.md\")),\n",[83,764,765],{"class":85,"line":181},[83,766,207],{},[31,768,769,778,794,805],{},[34,770,771,774,775,777],{},[13,772,773],{},"agent.harness([...])"," declares the delegation targets; the agent reaches\nthem only when ",[13,776,656],{}," is granted.",[34,779,780,549,783,549,786,789,790,793],{},[13,781,782],{},"agent.specialist.recon(...)",[13,784,785],{},".exploit(...)",[13,787,788],{},".triage(...)"," and\n",[13,791,792],{},".report(...)"," — one method per builtin role. Each inherits that role's\npreamble and tools; declaring the same role twice is rejected.",[34,795,796,797,278,799,801,802,804],{},"Each specialist's ",[13,798,212],{},[13,800,228],{}," default to the step's, so a\nspecialist only names what it overrides. ",[13,803,212],{}," may point at a different\nkey than the step's; every referenced key must be enabled for the project.",[34,806,807,808,810,811,813],{},"Subagents cannot delegate further; declaring ",[13,809,656],{}," inside a\nspecialist's ",[13,812,50],{}," is rejected.",[10,815,816,817,819],{},"Every specialist provider key must be enabled for the project, exactly like\nthe step's own ",[13,818,212],{},". Delegation is bounded — subagents run at depth one\nand return distilled results, not transcripts.",[235,821,822],{"id":56},[13,823,56],{},[10,825,826,829],{},[26,827,828],{},"Required."," Declares where the agent writes its final response and in what\nformat. The file becomes an ordinary workspace resource, so later steps read it\ndirectly, push it into a dataset, or publish it as an artifact:",[74,831,833],{"className":76,"code":832,"language":78,"meta":79,"style":79},"output = agent.output(path = path.file(\"findings.json\"), format = \"json\")\n",[13,834,835],{"__ignoreMap":79},[83,836,837],{"class":85,"line":86},[83,838,832],{},[449,840,841,856],{},[452,842,843],{},[455,844,845,850,853],{},[458,846,847],{},[13,848,849],{},"format",[458,851,852],{},"The runner requires",[458,854,855],{},"Use for",[468,857,858,872,885],{},[455,859,860,866,869],{},[473,861,862,865],{},[13,863,864],{},"\"text\""," (default)",[473,867,868],{},"nothing",[473,870,871],{},"Reports, summaries, prose",[455,873,874,879,882],{},[473,875,876],{},[13,877,878],{},"\"json\"",[473,880,881],{},"the whole response is one valid JSON value",[473,883,884],{},"A single structured result",[455,886,887,892,895],{},[473,888,889],{},[13,890,891],{},"\"jsonl\"",[473,893,894],{},"each non-empty line is a JSON object",[473,896,897,898,278,901],{},"Record streams that feed ",[13,899,900],{},"transform.jsonl()",[13,902,903],{},"step.update_dataset",[10,905,906,907,910],{},"The format is enforced at run time: a response that does not satisfy it fails\nthe step (unless ",[13,908,909],{},"allow_failure = True","). The runner also tells the agent the\ndestination file and the required format before it starts.",[10,912,913],{},"Chaining off an agent's output is just ordinary file handling:",[74,915,917],{"className":76,"code":916,"language":78,"meta":79,"style":79},"step.agent(\n    prompt = \"Return one JSON object with an `endpoints` array.\",\n    provider = provider.key(\"anthropic\u002Fpersonal\"),\n    context = [agent.context.path(description = \"Live hosts.\", path = path.file(\"live.txt\"))],\n    output = agent.output(path = path.file(\"endpoints.jsonl\"), format = \"jsonl\"),\n)\nstep.update_dataset(\n    table = \"endpoints\",\n    source = path.file(\"endpoints.jsonl\"),\n    pipeline = transform.jsonl(),\n    mapping = {\"url\": row.url, \"status\": row.status},\n    mode = \"upsert\",\n)\n",[13,918,919,923,928,932,937,942,946,951,956,961,966,971,976],{"__ignoreMap":79},[83,920,921],{"class":85,"line":86},[83,922,89],{},[83,924,925],{"class":85,"line":92},[83,926,927],{},"    prompt = \"Return one JSON object with an `endpoints` array.\",\n",[83,929,930],{"class":85,"line":98},[83,931,125],{},[83,933,934],{"class":85,"line":104},[83,935,936],{},"    context = [agent.context.path(description = \"Live hosts.\", path = path.file(\"live.txt\"))],\n",[83,938,939],{"class":85,"line":110},[83,940,941],{},"    output = agent.output(path = path.file(\"endpoints.jsonl\"), format = \"jsonl\"),\n",[83,943,944],{"class":85,"line":116},[83,945,207],{},[83,947,948],{"class":85,"line":122},[83,949,950],{},"step.update_dataset(\n",[83,952,953],{"class":85,"line":128},[83,954,955],{},"    table = \"endpoints\",\n",[83,957,958],{"class":85,"line":134},[83,959,960],{},"    source = path.file(\"endpoints.jsonl\"),\n",[83,962,963],{"class":85,"line":140},[83,964,965],{},"    pipeline = transform.jsonl(),\n",[83,967,968],{"class":85,"line":146},[83,969,970],{},"    mapping = {\"url\": row.url, \"status\": row.status},\n",[83,972,973],{"class":85,"line":152},[83,974,975],{},"    mode = \"upsert\",\n",[83,977,978],{"class":85,"line":158},[83,979,207],{},[235,981,982],{"id":62},[13,983,62],{},[10,985,986,987,578],{},"How the agent handles approvals and side effects. Defaults to ",[13,988,989],{},"auto",[74,991,993],{"className":76,"code":992,"language":78,"meta":79,"style":79},"mode = agent.mode.interactive\n",[13,994,995],{"__ignoreMap":79},[83,996,997],{"class":85,"line":86},[83,998,992],{},[449,1000,1001,1012],{},[452,1002,1003],{},[455,1004,1005,1009],{},[458,1006,1007],{},[13,1008,62],{},[458,1010,1011],{},"Behaviour",[468,1013,1014,1024,1034],{},[455,1015,1016,1021],{},[473,1017,1018],{},[13,1019,1020],{},"agent.mode.auto",[473,1022,1023],{},"Run to completion without asking. Safe for unattended\u002Fscheduled runs.",[455,1025,1026,1031],{},[473,1027,1028],{},[13,1029,1030],{},"agent.mode.interactive",[473,1032,1033],{},"Pause and ask before side-effectful actions (shell commands, etc.). Needs a human to answer.",[455,1035,1036,1041],{},[473,1037,1038],{},[13,1039,1040],{},"agent.mode.plan",[473,1042,1043],{},"Investigate read-only, present a plan, and wait for approval before running anything that changes state.",[10,1045,1046,1048,1049,1052,1053,1056],{},[13,1047,989],{}," is the default because a cron-triggered workflow has nobody to answer an\napproval prompt. Choose ",[13,1050,1051],{},"interactive"," for attended runs and ",[13,1054,1055],{},"plan"," when you want\nto review the agent's intended steps first.",[10,1058,1059,1060,1062,1063,1066],{},"In ",[13,1061,1055],{}," mode the agent's mutating tools are blocked until it calls\n",[13,1064,1065],{},"present_plan"," and the user approves the plan; read-only tools stay available\nthroughout. On approval the block lifts and the same session continues with the\nstep's full capabilities — the agent keeps its context across the decision. On\nrejection the step fails.",[235,1068,1069],{"id":68},[13,1070,68],{},[10,1072,1073],{},"The maximum number of agent loop iterations before the step fails. Defaults to\nunlimited.",[74,1075,1077],{"className":76,"code":1076,"language":78,"meta":79,"style":79},"iterations = 25                    # a cap\niterations = agent.iterations.unlimited   # explicit: no cap (the default)\n",[13,1078,1079,1084],{"__ignoreMap":79},[83,1080,1081],{"class":85,"line":86},[83,1082,1083],{},"iterations = 25                    # a cap\n",[83,1085,1086],{"class":85,"line":92},[83,1087,1088],{},"iterations = agent.iterations.unlimited   # explicit: no cap (the default)\n",[10,1090,1091],{},"Use a cap to bound cost and catch a looping agent; each iteration is one\nmodel turn (which may include several tool calls).",[18,1093,1095],{"id":1094},"realistic-patterns","Realistic Patterns",[235,1097,1099],{"id":1098},"triage-scanner-noise","Triage scanner noise",[10,1101,1102],{},"Nuclei on a wide surface produces noise. Let an agent filter before you ever\nsee it:",[74,1104,1106],{"className":76,"code":1105,"language":78,"meta":79,"style":79},"activity(\n    name = \"triage\",\n    triggers = [trigger.on(scan.succeeded())],\n    steps = [\n        step.download_artifact(scan.artifacts.findings),\n        step.agent(\n            prompt = \"\"\"\n                Classify each finding as EXPLOITABLE, LIKELY_NOISE, or\n                OUT_OF_SCOPE based on the scope file. For exploitable ones,\n                include reproduction steps.\n            \"\"\",\n            provider = provider.key(\"anthropic\u002Fpersonal\"),\n            model = model(\"default\"),\n            context = [\n                agent.context.path(description = \"Findings to classify.\", path = path.file(\"findings.txt\")),\n                agent.context.path(description = \"Scope definition.\", path = path.file(\"scope.txt\")),\n            ],\n            output = agent.output(path = path.file(\"agent-output.txt\")),\n        ),\n    ],\n)\n",[13,1107,1108,1113,1118,1123,1128,1133,1138,1143,1148,1153,1158,1163,1168,1173,1178,1183,1188,1193,1198,1202,1206],{"__ignoreMap":79},[83,1109,1110],{"class":85,"line":86},[83,1111,1112],{},"activity(\n",[83,1114,1115],{"class":85,"line":92},[83,1116,1117],{},"    name = \"triage\",\n",[83,1119,1120],{"class":85,"line":98},[83,1121,1122],{},"    triggers = [trigger.on(scan.succeeded())],\n",[83,1124,1125],{"class":85,"line":104},[83,1126,1127],{},"    steps = [\n",[83,1129,1130],{"class":85,"line":110},[83,1131,1132],{},"        step.download_artifact(scan.artifacts.findings),\n",[83,1134,1135],{"class":85,"line":116},[83,1136,1137],{},"        step.agent(\n",[83,1139,1140],{"class":85,"line":122},[83,1141,1142],{},"            prompt = \"\"\"\n",[83,1144,1145],{"class":85,"line":128},[83,1146,1147],{},"                Classify each finding as EXPLOITABLE, LIKELY_NOISE, or\n",[83,1149,1150],{"class":85,"line":134},[83,1151,1152],{},"                OUT_OF_SCOPE based on the scope file. For exploitable ones,\n",[83,1154,1155],{"class":85,"line":140},[83,1156,1157],{},"                include reproduction steps.\n",[83,1159,1160],{"class":85,"line":146},[83,1161,1162],{},"            \"\"\",\n",[83,1164,1165],{"class":85,"line":152},[83,1166,1167],{},"            provider = provider.key(\"anthropic\u002Fpersonal\"),\n",[83,1169,1170],{"class":85,"line":158},[83,1171,1172],{},"            model = model(\"default\"),\n",[83,1174,1175],{"class":85,"line":164},[83,1176,1177],{},"            context = [\n",[83,1179,1180],{"class":85,"line":169},[83,1181,1182],{},"                agent.context.path(description = \"Findings to classify.\", path = path.file(\"findings.txt\")),\n",[83,1184,1185],{"class":85,"line":175},[83,1186,1187],{},"                agent.context.path(description = \"Scope definition.\", path = path.file(\"scope.txt\")),\n",[83,1189,1190],{"class":85,"line":181},[83,1191,1192],{},"            ],\n",[83,1194,1195],{"class":85,"line":186},[83,1196,1197],{},"            output = agent.output(path = path.file(\"agent-output.txt\")),\n",[83,1199,1200],{"class":85,"line":192},[83,1201,161],{},[83,1203,1204],{"class":85,"line":198},[83,1205,189],{},[83,1207,1208],{"class":85,"line":204},[83,1209,207],{},[235,1211,1213],{"id":1212},"investigate-a-suspicious-change","Investigate a suspicious change",[10,1215,1216],{},"Combine scheduled diffing with an agent that investigates:",[74,1218,1220],{"className":76,"code":1219,"language":78,"meta":79,"style":79},"activity(\n    name = \"investigate\",\n    triggers = [trigger.on(diff.succeeded())],\n    steps = [\n        step.agent(\n            prompt = \"\"\"\n                A new endpoint appeared on this target since yesterday.\n                Investigate whether it exposes sensitive data or an admin\n                interface, and draft a finding summary if so.\n            \"\"\",\n            provider = provider.key(\"anthropic\u002Fpersonal\"),\n            model = model(\"default\"),\n            context = [\n                agent.context.path(description = \"Observed changes.\", path = path.file(\"changes.txt\")),\n            ],\n            tools = [tool.shell()],\n            allow_failure = True,   # investigation is best-effort\n            output = agent.output(path = path.file(\"agent-output.txt\")),\n        ),\n    ],\n)\n",[13,1221,1222,1226,1231,1236,1240,1244,1248,1253,1258,1263,1267,1271,1275,1279,1284,1288,1293,1298,1302,1306,1310],{"__ignoreMap":79},[83,1223,1224],{"class":85,"line":86},[83,1225,1112],{},[83,1227,1228],{"class":85,"line":92},[83,1229,1230],{},"    name = \"investigate\",\n",[83,1232,1233],{"class":85,"line":98},[83,1234,1235],{},"    triggers = [trigger.on(diff.succeeded())],\n",[83,1237,1238],{"class":85,"line":104},[83,1239,1127],{},[83,1241,1242],{"class":85,"line":110},[83,1243,1137],{},[83,1245,1246],{"class":85,"line":116},[83,1247,1142],{},[83,1249,1250],{"class":85,"line":122},[83,1251,1252],{},"                A new endpoint appeared on this target since yesterday.\n",[83,1254,1255],{"class":85,"line":128},[83,1256,1257],{},"                Investigate whether it exposes sensitive data or an admin\n",[83,1259,1260],{"class":85,"line":134},[83,1261,1262],{},"                interface, and draft a finding summary if so.\n",[83,1264,1265],{"class":85,"line":140},[83,1266,1162],{},[83,1268,1269],{"class":85,"line":146},[83,1270,1167],{},[83,1272,1273],{"class":85,"line":152},[83,1274,1172],{},[83,1276,1277],{"class":85,"line":158},[83,1278,1177],{},[83,1280,1281],{"class":85,"line":164},[83,1282,1283],{},"                agent.context.path(description = \"Observed changes.\", path = path.file(\"changes.txt\")),\n",[83,1285,1286],{"class":85,"line":169},[83,1287,1192],{},[83,1289,1290],{"class":85,"line":175},[83,1291,1292],{},"            tools = [tool.shell()],\n",[83,1294,1295],{"class":85,"line":181},[83,1296,1297],{},"            allow_failure = True,   # investigation is best-effort\n",[83,1299,1300],{"class":85,"line":186},[83,1301,1197],{},[83,1303,1304],{"class":85,"line":192},[83,1305,161],{},[83,1307,1308],{"class":85,"line":198},[83,1309,189],{},[83,1311,1312],{"class":85,"line":204},[83,1313,207],{},[18,1315,1317],{"id":1316},"agents-the-platform-does-not-own","Agents the Platform Does Not Own",[10,1319,1320,1321,1323,1324,1326,1327,1330,1331,1334,1335,1338,1339,578],{},"Not every agent is a ",[13,1322,15],{},". You can run any agent CLI in a shell step\n(",[13,1325,244],{},"\u002F",[13,1328,1329],{},"step.exec","). When such an agent needs a human decision, the\nrunner has already provisioned the way to ask: it installs the ",[13,1332,1333],{},"bh"," CLI on the\nstep's ",[13,1336,1337],{},"PATH"," and exports the per-step endpoint as ",[13,1340,1341],{},"BOUNTYHUB_ASK_URL",[74,1343,1347],{"className":1344,"code":1345,"language":1346,"meta":79,"style":79},"language-sh shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","bh ask \"Which environment should I deploy to?\"\nbh ask --kind choice --option staging --option production \"Pick one\"\nbh ask --kind confirm \"Delete the staging database?\"   # prints yes or no\n","sh",[13,1348,1349,1354,1359],{"__ignoreMap":79},[83,1350,1351],{"class":85,"line":86},[83,1352,1353],{},"bh ask \"Which environment should I deploy to?\"\n",[83,1355,1356],{"class":85,"line":92},[83,1357,1358],{},"bh ask --kind choice --option staging --option production \"Pick one\"\n",[83,1360,1361],{"class":85,"line":98},[83,1362,1363],{},"bh ask --kind confirm \"Delete the staging database?\"   # prints yes or no\n",[10,1365,1366,1369,1370,1373,1374,1377,1378,1381,1382,549,1385,549,1388,1391,1392,1394,1395,1398],{},[13,1367,1368],{},"bh ask"," posts the question to the platform, blocks until the operator answers\n(the run parks as ",[13,1371,1372],{},"WAITING_FOR_INPUT"," meanwhile), and prints the answer. It\nneeds no token, so it works in a step that has none. A declined request exits\nwith status ",[13,1375,1376],{},"1","; use ",[13,1379,1380],{},"bh --json ask ..."," when the step needs the full answer\n(",[13,1383,1384],{},"text",[13,1386,1387],{},"confirmed",[13,1389,1390],{},"declined",") — for example to branch on the ",[13,1393,1387],{},"\nflag of a ",[13,1396,1397],{},"--kind confirm"," question.",[74,1400,1402],{"className":76,"code":1401,"language":78,"meta":79,"style":79},"step.exec(\n    command = [\"my-agent\", \"--instructions\", \"Ask before any destructive action.\"],\n    stdout = path.file(\"agent-report.txt\"),\n)\n",[13,1403,1404,1409,1414,1419],{"__ignoreMap":79},[83,1405,1406],{"class":85,"line":86},[83,1407,1408],{},"step.exec(\n",[83,1410,1411],{"class":85,"line":92},[83,1412,1413],{},"    command = [\"my-agent\", \"--instructions\", \"Ask before any destructive action.\"],\n",[83,1415,1416],{"class":85,"line":98},[83,1417,1418],{},"    stdout = path.file(\"agent-report.txt\"),\n",[83,1420,1421],{"class":85,"line":104},[83,1422,207],{},[10,1424,1425,1426,1429,1430,1432,1433,1436],{},"For the agent to discover this, the runner writes an ",[13,1427,1428],{},"AGENTS.md"," in the step\nworkspace (only when one is not already there) describing ",[13,1431,1368],{},", and hosts a\nloopback MCP server that exposes the same decision as the ",[13,1434,1435],{},"request_user_input","\ntool. An agent that speaks MCP can call it directly.",[235,1438,1440],{"id":1439},"platform-modules-for-agent-clis","Platform modules for agent CLIs",[10,1442,1443,1444,1446,1447,1450,1451,1453],{},"You do not have to hand-roll the ",[13,1445,1329],{}," wrapper. The platform ships\nready-made modules for the common agent CLIs, so you invoke them with\n",[13,1448,1449],{},"step.module"," using the same prompt → output shape as ",[13,1452,15],{},":",[449,1455,1456,1469],{},[452,1457,1458],{},[455,1459,1460,1463,1466],{},[458,1461,1462],{},"Module",[458,1464,1465],{},"Wraps",[458,1467,1468],{},"Extra inputs",[468,1470,1471,1508,1531,1553],{},[455,1472,1473,1478,1484],{},[473,1474,1475],{},[13,1476,1477],{},"bountyhub\u002Fclaude",[473,1479,1480,1481,649],{},"Claude Code (",[13,1482,1483],{},"claude -p",[473,1485,1486,549,1488,549,1491,549,1493,549,1496,549,1499,549,1502,549,1505],{},[13,1487,228],{},[13,1489,1490],{},"permission_mode",[13,1492,50],{},[13,1494,1495],{},"allowed_tools",[13,1497,1498],{},"disallowed_tools",[13,1500,1501],{},"append_system_prompt",[13,1503,1504],{},"max_turns",[13,1506,1507],{},"output_format",[455,1509,1510,1515,1521],{},[473,1511,1512],{},[13,1513,1514],{},"bountyhub\u002Fcodex",[473,1516,1517,1518,649],{},"OpenAI Codex (",[13,1519,1520],{},"codex exec",[473,1522,1523,549,1525,549,1528],{},[13,1524,228],{},[13,1526,1527],{},"sandbox",[13,1529,1530],{},"output_schema",[455,1532,1533,1538,1544],{},[473,1534,1535],{},[13,1536,1537],{},"bountyhub\u002Fhermes",[473,1539,1540,1541,649],{},"Hermes Agent (",[13,1542,1543],{},"hermes chat -q",[473,1545,1546,549,1548,549,1550],{},[13,1547,228],{},[13,1549,212],{},[13,1551,1552],{},"skills",[455,1554,1555,1560,1566],{},[473,1556,1557],{},[13,1558,1559],{},"bountyhub\u002Fopencode",[473,1561,1562,1563,649],{},"opencode (",[13,1564,1565],{},"opencode run",[473,1567,1568,1570,1571,1574,1575,549,1578,549,1581],{},[13,1569,228],{}," (",[13,1572,1573],{},"provider\u002Fmodel","), ",[13,1576,1577],{},"agent",[13,1579,1580],{},"config",[13,1582,1583],{},"permission",[10,1585,1586,1587,1589,1590,1593,1594,1596,1597,1600,1601,1604,1605,549,1608,549,1611,1614,1615,578],{},"Each one takes a required ",[13,1588,38],{},", runs in its ",[26,1591,1592],{},"own isolated workspace","\n(only its declared file\u002Fdirectory inputs are copied in; files from earlier\nsteps are not visible unless passed explicitly), and declares two file outputs:\n",[13,1595,56],{}," (the agent's final response) and ",[13,1598,1599],{},"log"," (the CLI's stderr transcript).\nCredentials are optional secret inputs bound from ",[13,1602,1603],{},"config.secret(...)"," — e.g.\n",[13,1606,1607],{},"anthropic_api_key",[13,1609,1610],{},"openai_api_key",[13,1612,1613],{},"openrouter_api_key"," — mapped to the\nCLI's conventional environment variables. When you do not bind them, the CLI\nfalls back to its own auth store, so the runner host must have the CLI on\n",[13,1616,1337],{},[74,1618,1620],{"className":76,"code":1619,"language":78,"meta":79,"style":79},"load(\"bountyhub\u002Fclaude\", \"claude\")\n\nreview = step.module(claude, inputs = {\n    \"prompt\": \"Review src\u002F for injection sinks and write findings.md.\",\n    \"model\": \"sonnet\",\n    \"permission_mode\": \"acceptEdits\",\n    \"anthropic_api_key\": config.secret(\"anthropic_api_key\"),\n})\n\n# review.outputs.output — the agent's final response\n# review.outputs.log    — stderr transcript\n",[13,1621,1622,1627,1633,1638,1643,1648,1653,1658,1663,1667,1672],{"__ignoreMap":79},[83,1623,1624],{"class":85,"line":86},[83,1625,1626],{},"load(\"bountyhub\u002Fclaude\", \"claude\")\n",[83,1628,1629],{"class":85,"line":92},[83,1630,1632],{"emptyLinePlaceholder":1631},true,"\n",[83,1634,1635],{"class":85,"line":98},[83,1636,1637],{},"review = step.module(claude, inputs = {\n",[83,1639,1640],{"class":85,"line":104},[83,1641,1642],{},"    \"prompt\": \"Review src\u002F for injection sinks and write findings.md.\",\n",[83,1644,1645],{"class":85,"line":110},[83,1646,1647],{},"    \"model\": \"sonnet\",\n",[83,1649,1650],{"class":85,"line":116},[83,1651,1652],{},"    \"permission_mode\": \"acceptEdits\",\n",[83,1654,1655],{"class":85,"line":122},[83,1656,1657],{},"    \"anthropic_api_key\": config.secret(\"anthropic_api_key\"),\n",[83,1659,1660],{"class":85,"line":128},[83,1661,1662],{},"})\n",[83,1664,1665],{"class":85,"line":134},[83,1666,1632],{"emptyLinePlaceholder":1631},[83,1668,1669],{"class":85,"line":140},[83,1670,1671],{},"# review.outputs.output — the agent's final response\n",[83,1673,1674],{"class":85,"line":146},[83,1675,1676],{},"# review.outputs.log    — stderr transcript\n",[10,1678,1679,1680,1682],{},"Because the modules are ordinary ",[13,1681,1449],{}," invocations, their outputs chain\nlike any other step. A read-only Codex triage pass, for example:",[74,1684,1686],{"className":76,"code":1685,"language":78,"meta":79,"style":79},"load(\"bountyhub\u002Fcodex\", \"codex\")\n\ntriage = step.module(codex, inputs = {\n    \"prompt\": \"Triage the findings in findings.jsonl and rank by exploitability.\",\n    \"sandbox\": \"read-only\",\n    \"codex_api_key\": config.secret(\"codex_api_key\"),\n})\n",[13,1687,1688,1693,1697,1702,1707,1712,1717],{"__ignoreMap":79},[83,1689,1690],{"class":85,"line":86},[83,1691,1692],{},"load(\"bountyhub\u002Fcodex\", \"codex\")\n",[83,1694,1695],{"class":85,"line":92},[83,1696,1632],{"emptyLinePlaceholder":1631},[83,1698,1699],{"class":85,"line":98},[83,1700,1701],{},"triage = step.module(codex, inputs = {\n",[83,1703,1704],{"class":85,"line":104},[83,1705,1706],{},"    \"prompt\": \"Triage the findings in findings.jsonl and rank by exploitability.\",\n",[83,1708,1709],{"class":85,"line":110},[83,1710,1711],{},"    \"sandbox\": \"read-only\",\n",[83,1713,1714],{"class":85,"line":116},[83,1715,1716],{},"    \"codex_api_key\": config.secret(\"codex_api_key\"),\n",[83,1718,1719],{"class":85,"line":122},[83,1720,1662],{},[10,1722,1723,1724,1727,1728,1731,1732,1735,1736,1738,1739,1741,1742,1744],{},"The safety defaults keep unattended runs non-destructive: Codex starts in a\nread-only sandbox (pass ",[13,1725,1726],{},"sandbox = \"workspace-write\""," to allow edits), Claude\nCode gets no ",[13,1729,1730],{},"bypassPermissions",", Hermes one-shot sessions deny dangerous\ncommands, and the opencode module never passes ",[13,1733,1734],{},"--auto",". Configure permissions\nper module through the CLI-specific inputs (for opencode, ",[13,1737,1580],{}," \u002F\n",[13,1740,1583],{},"; for Codex, ",[13,1743,1527],{},").",[18,1746,1748],{"id":1747},"notes","Notes",[31,1750,1751,1757,1780],{},[34,1752,1753,1754,1756],{},"Agent steps participate in the normal lifecycle, including waiting for input\n(",[13,1755,1372],{},") when the platform asks them something mid-run.",[34,1758,1759,1761,1762,549,1765,1768,1769,1772,1773,1776,1777,578],{},[13,1760,15],{}," accepts ",[13,1763,1764],{},"name",[13,1766,1767],{},"allow_failure",", and ",[13,1770,1771],{},"timeout"," like other\nsteps, but it accepts neither ",[13,1774,1775],{},"id"," nor ",[13,1778,1779],{},"cond",[34,1781,1782,1783,1789],{},"Secrets are safest kept out of prompts entirely; reference configuration via\n",[1784,1785,1787],"a",{"href":1786},"\u002Fworkflows\u002Fconfig",[13,1788,483],{}," when a tool or MCP server needs credentials —\nresolution happens at execution time and values are never serialized into\nyour workflow.",[1791,1792,1793],"style",{},"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":79,"searchDepth":110,"depth":104,"links":1795},[1796,1797,1808,1812,1815],{"id":20,"depth":92,"text":21},{"id":232,"depth":92,"text":233,"children":1798},[1799,1800,1802,1803,1804,1805,1806,1807],{"id":38,"depth":98,"text":38},{"id":275,"depth":98,"text":1801},"provider and model",{"id":44,"depth":98,"text":44},{"id":50,"depth":98,"text":50},{"id":669,"depth":98,"text":670},{"id":56,"depth":98,"text":56},{"id":62,"depth":98,"text":62},{"id":68,"depth":98,"text":68},{"id":1094,"depth":92,"text":1095,"children":1809},[1810,1811],{"id":1098,"depth":98,"text":1099},{"id":1212,"depth":98,"text":1213},{"id":1316,"depth":92,"text":1317,"children":1813},[1814],{"id":1439,"depth":98,"text":1440},{"id":1747,"depth":92,"text":1748},"AI agent steps with explicitly granted capabilities: prompt, provider, model, typed context list, tools, and output contracts.","md",{},"\u002Fworkflows\u002Fagents",null,{"title":5,"description":1816},{"loc":1819},"01.workflows\u002F09.agents","SIbfCE2S0aSNQEO5xFY4Lzz45zqM11ffm8jdEEmJ0d0",[1826,1885,1901,1920,1955,1971,1983,1994,2005,2016,2040,2059,2079,2090,2101],{"title":1827,"path":1828,"stem":1829,"children":1830},"Workflows","\u002Fworkflows","01.workflows",[1831,1833,1837,1841,1845,1849,1853,1857,1861,1865,1869,1870,1874,1877,1881],{"title":1827,"path":1828,"stem":1832},"01.workflows\u002Findex",{"title":1834,"path":1835,"stem":1836},"Workflow Quick Reference","\u002Fworkflows\u002Fquick-reference","01.workflows\u002F00.quick-reference",{"title":1838,"path":1839,"stem":1840},"Workflows Overview","\u002Fworkflows\u002Foverview","01.workflows\u002F01.overview",{"title":1842,"path":1843,"stem":1844},"Workflow Syntax Reference","\u002Fworkflows\u002Fsyntax-reference","01.workflows\u002F02.syntax-reference",{"title":1846,"path":1847,"stem":1848},"Steps","\u002Fworkflows\u002Fsteps","01.workflows\u002F03.steps",{"title":1850,"path":1851,"stem":1852},"Step Outputs","\u002Fworkflows\u002Fstep-outputs","01.workflows\u002F04.step-outputs",{"title":1854,"path":1855,"stem":1856},"Concurrency","\u002Fworkflows\u002Fconcurrency","01.workflows\u002F05.concurrency",{"title":1858,"path":1859,"stem":1860},"Transforms","\u002Fworkflows\u002Ftransforms","01.workflows\u002F06.transforms",{"title":1862,"path":1863,"stem":1864},"For Each","\u002Fworkflows\u002Ffor-each","01.workflows\u002F07.for-each",{"title":1866,"path":1867,"stem":1868},"Modules","\u002Fworkflows\u002Fmodules","01.workflows\u002F08.modules",{"title":5,"path":1819,"stem":1823},{"title":1871,"path":1872,"stem":1873},"Decisions","\u002Fworkflows\u002Fdecisions","01.workflows\u002F10.decisions",{"title":1875,"path":1786,"stem":1876},"Configuration References","01.workflows\u002F11.config",{"title":1878,"path":1879,"stem":1880},"Comparison With Other Automation Systems","\u002Fworkflows\u002Fcomparison","01.workflows\u002F12.comparison",{"title":1882,"path":1883,"stem":1884},"Generate with AI","\u002Fworkflows\u002Fai-generation","01.workflows\u002F13.ai-generation",{"title":1886,"path":1887,"stem":1888,"children":1889},"Projects","\u002Fprojects","02.projects",[1890,1893,1897],{"title":1891,"path":1887,"stem":1892},"Projects & Runs","02.projects\u002Findex",{"title":1894,"path":1895,"stem":1896},"Projects Overview","\u002Fprojects\u002Foverview","02.projects\u002F1.overview",{"title":1898,"path":1899,"stem":1900},"Runs & Artifacts","\u002Fprojects\u002Fruns-artifacts","02.projects\u002F2.runs-artifacts",{"title":1902,"path":1903,"stem":1904,"children":1905},"Runners","\u002Frunners","03.runners",[1906,1908,1912,1916],{"title":1902,"path":1903,"stem":1907},"03.runners\u002Findex",{"title":1909,"path":1910,"stem":1911},"Runner Overview","\u002Frunners\u002Foverview","03.runners\u002F1.overview",{"title":1913,"path":1914,"stem":1915},"Getting Started with Runners","\u002Frunners\u002Fgetting-started","03.runners\u002F2.getting-started",{"title":1917,"path":1918,"stem":1919},"Custom Runner Images","\u002Frunners\u002Fcustom-image","03.runners\u002F3.custom-image",{"title":1921,"path":1922,"stem":1923,"children":1924},"Datasets","\u002Fdatasets","04.datasets",[1925,1927,1931,1935,1939,1943,1947,1951],{"title":1921,"path":1922,"stem":1926},"04.datasets\u002Findex",{"title":1928,"path":1929,"stem":1930},"Datasets Overview","\u002Fdatasets\u002Foverview","04.datasets\u002F1.overview",{"title":1932,"path":1933,"stem":1934},"Dataset Schemas and Identity","\u002Fdatasets\u002Fschema","04.datasets\u002F2.schema",{"title":1936,"path":1937,"stem":1938},"Pushing and Reading Dataset Rows","\u002Fdatasets\u002Fworkflows","04.datasets\u002F3.workflows",{"title":1940,"path":1941,"stem":1942},"Dataset SQL Reference","\u002Fdatasets\u002Fsql","04.datasets\u002F4.sql",{"title":1944,"path":1945,"stem":1946},"Dataset Structured Filters","\u002Fdatasets\u002Ffilters","04.datasets\u002F5.filters",{"title":1948,"path":1949,"stem":1950},"Dataset Saved Views","\u002Fdatasets\u002Fviews","04.datasets\u002F6.views",{"title":1952,"path":1953,"stem":1954},"Datasets API and CLI","\u002Fdatasets\u002Fapi-cli","04.datasets\u002F7.api-cli",{"title":1956,"path":1957,"stem":1958,"children":1959},"Agent","\u002Fagent","05.agent",[1960,1963,1967],{"title":1961,"path":1957,"stem":1962},"BH Agent","05.agent\u002Findex",{"title":1964,"path":1965,"stem":1966},"BH Agent Overview","\u002Fagent\u002Foverview","05.agent\u002F1.overview",{"title":1968,"path":1969,"stem":1970},"MCP servers","\u002Fagent\u002Fmcp-servers","05.agent\u002F2.mcp-servers",{"title":1972,"path":1973,"stem":1974,"children":1975},"Bhlast","\u002Fbhlast","06.bhlast",[1976,1979],{"title":1977,"path":1973,"stem":1978},"Bhlast Servers","06.bhlast\u002Findex",{"title":1980,"path":1981,"stem":1982},"Bhlast servers overview","\u002Fbhlast\u002Foverview","06.bhlast\u002F1.overview",{"title":1984,"path":1985,"stem":1986,"children":1987},"Notifications","\u002Fnotifications","07.notifications",[1988,1990],{"title":1984,"path":1985,"stem":1989},"07.notifications\u002Findex",{"title":1991,"path":1992,"stem":1993},"Notifications Overview","\u002Fnotifications\u002Foverview","07.notifications\u002F1.overview",{"title":1995,"path":1996,"stem":1997,"children":1998},"Blob Storage","\u002Fblob-storage","08.blob-storage",[1999,2001],{"title":1995,"path":1996,"stem":2000},"08.blob-storage\u002Findex",{"title":2002,"path":2003,"stem":2004},"Blob Storage Overview","\u002Fblob-storage\u002Foverview","08.blob-storage\u002F1.overview",{"title":2006,"path":2007,"stem":2008,"children":2009},"Payloads","\u002Fpayloads","09.payloads",[2010,2012],{"title":2006,"path":2007,"stem":2011},"09.payloads\u002Findex",{"title":2013,"path":2014,"stem":2015},"Payloads overview","\u002Fpayloads\u002Foverview","09.payloads\u002F1.overview",{"title":2017,"path":2018,"stem":2019,"children":2020},"Cve Watcher","\u002Fcve-watcher","10.cve-watcher",[2021,2024,2028,2032,2036],{"title":2022,"path":2018,"stem":2023},"CVE Watcher","10.cve-watcher\u002Findex",{"title":2025,"path":2026,"stem":2027},"CVE Watcher Overview","\u002Fcve-watcher\u002Foverview","10.cve-watcher\u002F1.overview",{"title":2029,"path":2030,"stem":2031},"CVE Watcher Search and Filters","\u002Fcve-watcher\u002Fsearch","10.cve-watcher\u002F2.search",{"title":2033,"path":2034,"stem":2035},"CVE Watcher Push Notifications","\u002Fcve-watcher\u002Fnotifications","10.cve-watcher\u002F3.notifications",{"title":2037,"path":2038,"stem":2039},"CVE Watcher API and Scopes","\u002Fcve-watcher\u002Fapi","10.cve-watcher\u002F4.api",{"title":2041,"path":2042,"stem":2043,"children":2044},"Developer","\u002Fdeveloper","11.developer",[2045,2047,2051,2055],{"title":2041,"path":2042,"stem":2046},"11.developer\u002Findex",{"title":2048,"path":2049,"stem":2050},"Developer Overview","\u002Fdeveloper\u002Foverview","11.developer\u002F1.overview",{"title":2052,"path":2053,"stem":2054},"Personal Access Token Scopes","\u002Fdeveloper\u002Fscopes","11.developer\u002F2.scopes",{"title":2056,"path":2057,"stem":2058},"Personal Access Tokens","\u002Fdeveloper\u002Fpersonal-access-tokens","11.developer\u002F3.personal-access-tokens",{"title":2060,"path":2061,"stem":2062,"children":2063},"Bh","\u002Fbh","12.bh",[2064,2067,2071,2075],{"title":2065,"path":2061,"stem":2066},"BH CLI","12.bh\u002Findex",{"title":2068,"path":2069,"stem":2070},"BH CLI Overview","\u002Fbh\u002Foverview","12.bh\u002F1.overview",{"title":2072,"path":2073,"stem":2074},"BH CLI Commands","\u002Fbh\u002Fcommands","12.bh\u002F2.commands",{"title":2076,"path":2077,"stem":2078},"BH CLI Examples","\u002Fbh\u002Fexamples","12.bh\u002F3.examples",{"title":2080,"path":2081,"stem":2082,"children":2083},"Billing","\u002Fbilling","13.billing",[2084,2086],{"title":2080,"path":2081,"stem":2085},"13.billing\u002Findex",{"title":2087,"path":2088,"stem":2089},"Billing Overview","\u002Fbilling\u002Foverview","13.billing\u002F1.overview",{"title":2091,"path":2092,"stem":2093,"children":2094},"Tools","\u002Ftools","14.tools",[2095,2097],{"title":2091,"path":2092,"stem":2096},"14.tools\u002Findex",{"title":2098,"path":2099,"stem":2100},"Cookie Lab","\u002Ftools\u002Fcookie-lab","14.tools\u002F1.cookie-lab",{"title":2102,"path":2103,"stem":2104,"children":2105},"Site Policies","\u002Fsite-policies","99.site-policies",[2106,2108,2121,2125,2129,2133,2137,2141,2145],{"title":2102,"path":2103,"stem":2107},"99.site-policies\u002Findex",{"title":2109,"path":2110,"stem":2111,"children":2112},"Privacy Policy","\u002Fsite-policies\u002Fprivacy-policy","99.site-policies\u002F1.privacy-policy",[2113,2117],{"title":2114,"path":2115,"stem":2116},"Company Processors","\u002Fsite-policies\u002Fprivacy-policy\u002Fcompany-processors","99.site-policies\u002Fprivacy-policy\u002F1.company-processors",{"title":2118,"path":2119,"stem":2120},"Data Export Instructions","\u002Fsite-policies\u002Fprivacy-policy\u002Fdata-export-instructions","99.site-policies\u002Fprivacy-policy\u002F2.data-export-instructions",{"title":2122,"path":2123,"stem":2124},"Terms of Service","\u002Fsite-policies\u002Fterms-of-service","99.site-policies\u002F2.terms-of-service",{"title":2126,"path":2127,"stem":2128},"California Resident Notice at Collection","\u002Fsite-policies\u002Fccpa","99.site-policies\u002F3.ccpa",{"title":2130,"path":2131,"stem":2132},"Cancellation Policy","\u002Fsite-policies\u002Fcancellation-policy","99.site-policies\u002F4.cancellation-policy",{"title":2134,"path":2135,"stem":2136},"Refund Policy","\u002Fsite-policies\u002Frefund-policy","99.site-policies\u002F5.refund-policy",{"title":2138,"path":2139,"stem":2140},"Taxes on Services","\u002Fsite-policies\u002Ftaxes-on-services","99.site-policies\u002F6.taxes-on-services",{"title":2142,"path":2143,"stem":2144},"Disclaimer","\u002Fsite-policies\u002Fdisclaimer","99.site-policies\u002F7.disclaimer",{"title":2146,"path":2147,"stem":2148,"children":2149},"Security","\u002Fsite-policies\u002Fsecurity","99.site-policies\u002Fsecurity\u002Findex",[2150,2151,2155],{"title":2146,"path":2147,"stem":2148},{"title":2152,"path":2153,"stem":2154},"Security Overview","\u002Fsite-policies\u002Fsecurity\u002Fsecurity-overview","99.site-policies\u002Fsecurity\u002F1.security-overview",{"title":2156,"path":2157,"stem":2158},"Security Response","\u002Fsite-policies\u002Fsecurity\u002Fsecurity-response","99.site-policies\u002Fsecurity\u002F2.security-response",1794410312375]