[{"data":1,"prerenderedAt":2953},["ShallowReactive",2],{"docs:/docs/agents/examples":3},{"id":4,"title":5,"body":6,"description":2946,"extension":2947,"meta":2948,"navigation":78,"path":2949,"seo":2950,"stem":2951,"__hash__":2952},"docs/docs/agents/examples.md","Agent Examples",{"type":7,"value":8,"toc":2938},"minimark",[9,14,18,21,236,241,252,672,679,683,686,1078,1083,1087,1093,1447,1452,1456,1459,1862,1867,1871,1874,2319,2324,2328,2331,2929,2934],[10,11,13],"h1",{"id":12},"examples","Examples",[15,16,17],"p",{},"Canonical recipes for common agent workflows. Each example shows a complete pattern you can adapt.",[15,19,20],{},"Unless an example shows its own setup, it assumes a connected wrapper and room:",[22,23,24],"code-tabs",{},[25,26,32],"pre",{"className":27,"code":28,"filename":29,"language":30,"meta":31,"style":31},"language-typescript shiki shiki-themes github-light github-dark","import { NoLag } from \"@nolag/js-sdk\";\nimport { NoLagAgents } from \"@nolag/agents\";\n\nconst client = NoLag(ACTOR_TOKEN);\nconst agents = new NoLagAgents({\n  client,\n  appName: APP_SLUG, // the slug returned when you created the app\n  agentId: \"orchestrator\",\n  presence: { name: \"orchestrator\", role: \"orchestrator\" },\n});\nawait client.connect();\nawait agents.ready();\n\nconst room = agents.room(\"default-workflow\");\n","Setup","typescript","",[33,34,35,58,73,80,106,125,131,147,159,175,181,196,209,214],"code",{"__ignoreMap":31},[36,37,40,44,48,51,55],"span",{"class":38,"line":39},"line",1,[36,41,43],{"class":42},"szBVR","import",[36,45,47],{"class":46},"sVt8B"," { NoLag } ",[36,49,50],{"class":42},"from",[36,52,54],{"class":53},"sZZnC"," \"@nolag/js-sdk\"",[36,56,57],{"class":46},";\n",[36,59,61,63,66,68,71],{"class":38,"line":60},2,[36,62,43],{"class":42},[36,64,65],{"class":46}," { NoLagAgents } ",[36,67,50],{"class":42},[36,69,70],{"class":53}," \"@nolag/agents\"",[36,72,57],{"class":46},[36,74,76],{"class":38,"line":75},3,[36,77,79],{"emptyLinePlaceholder":78},true,"\n",[36,81,83,86,90,93,97,100,103],{"class":38,"line":82},4,[36,84,85],{"class":42},"const",[36,87,89],{"class":88},"sj4cs"," client",[36,91,92],{"class":42}," =",[36,94,96],{"class":95},"sScJk"," NoLag",[36,98,99],{"class":46},"(",[36,101,102],{"class":88},"ACTOR_TOKEN",[36,104,105],{"class":46},");\n",[36,107,109,111,114,116,119,122],{"class":38,"line":108},5,[36,110,85],{"class":42},[36,112,113],{"class":88}," agents",[36,115,92],{"class":42},[36,117,118],{"class":42}," new",[36,120,121],{"class":95}," NoLagAgents",[36,123,124],{"class":46},"({\n",[36,126,128],{"class":38,"line":127},6,[36,129,130],{"class":46},"  client,\n",[36,132,134,137,140,143],{"class":38,"line":133},7,[36,135,136],{"class":46},"  appName: ",[36,138,139],{"class":88},"APP_SLUG",[36,141,142],{"class":46},", ",[36,144,146],{"class":145},"sJ8bj","// the slug returned when you created the app\n",[36,148,150,153,156],{"class":38,"line":149},8,[36,151,152],{"class":46},"  agentId: ",[36,154,155],{"class":53},"\"orchestrator\"",[36,157,158],{"class":46},",\n",[36,160,162,165,167,170,172],{"class":38,"line":161},9,[36,163,164],{"class":46},"  presence: { name: ",[36,166,155],{"class":53},[36,168,169],{"class":46},", role: ",[36,171,155],{"class":53},[36,173,174],{"class":46}," },\n",[36,176,178],{"class":38,"line":177},10,[36,179,180],{"class":46},"});\n",[36,182,184,187,190,193],{"class":38,"line":183},11,[36,185,186],{"class":42},"await",[36,188,189],{"class":46}," client.",[36,191,192],{"class":95},"connect",[36,194,195],{"class":46},"();\n",[36,197,199,201,204,207],{"class":38,"line":198},12,[36,200,186],{"class":42},[36,202,203],{"class":46}," agents.",[36,205,206],{"class":95},"ready",[36,208,195],{"class":46},[36,210,212],{"class":38,"line":211},13,[36,213,79],{"emptyLinePlaceholder":78},[36,215,217,219,222,224,226,229,231,234],{"class":38,"line":216},14,[36,218,85],{"class":42},[36,220,221],{"class":88}," room",[36,223,92],{"class":42},[36,225,203],{"class":46},[36,227,228],{"class":95},"room",[36,230,99],{"class":46},[36,232,233],{"class":53},"\"default-workflow\"",[36,235,105],{"class":46},[237,238,240],"h2",{"id":239},"agentic-chatbot","Agentic Chatbot",[15,242,243,244,247,248,251],{},"A customer support chatbot that uses ",[33,245,246],{},"@nolag/chat"," for the user interface and ",[33,249,250],{},"@nolag/agents"," for AI-powered responses. Both wrappers share one client. User messages are dispatched as tasks to a support agent and the answer is sent back to the chat room.",[22,253,254],{},[25,255,258],{"className":27,"code":256,"filename":257,"language":30,"meta":31,"style":31},"import { NoLag } from \"@nolag/js-sdk\";\nimport { NoLagChat } from \"@nolag/chat\";\nimport { NoLagAgents, Handoff } from \"@nolag/agents\";\n\nconst client = NoLag(BOT_TOKEN);\nconst chat = new NoLagChat({ client, appName: CHAT_APP_SLUG, username: \"support-bot\" });\nconst agents = new NoLagAgents({\n  client,\n  appName: AGENTS_APP_SLUG,\n  agentId: \"support-bridge\",\n  presence: { name: \"support-bridge\", role: \"orchestrator\" },\n});\nawait client.connect();\nawait Promise.all([chat.ready(), agents.ready()]);\n\nconst chatRoom = chat.joinRoom(\"general\");\nconst handoff = new Handoff(agents.room(\"default-workflow\"));\n\n// Fires for other users' messages only; publishers never receive their own\nchatRoom.on(\"message\", async (msg) => {\n  const result = await handoff.dispatch(\n    \"customer-support\",\n    { userId: msg.userId, text: msg.text, history: chatRoom.getMessages().map((m) => m.text) },\n    { waitForResult: true, timeout: 30000 },\n  );\n  if (result && result.status === \"success\") {\n    chatRoom.sendMessage(String(result.payload.response));\n  }\n});\n","TypeScript",[33,259,260,272,286,299,303,320,349,363,367,376,385,397,401,411,437,442,465,492,497,503,538,561,569,597,614,620,644,661,667],{"__ignoreMap":31},[36,261,262,264,266,268,270],{"class":38,"line":39},[36,263,43],{"class":42},[36,265,47],{"class":46},[36,267,50],{"class":42},[36,269,54],{"class":53},[36,271,57],{"class":46},[36,273,274,276,279,281,284],{"class":38,"line":60},[36,275,43],{"class":42},[36,277,278],{"class":46}," { NoLagChat } ",[36,280,50],{"class":42},[36,282,283],{"class":53}," \"@nolag/chat\"",[36,285,57],{"class":46},[36,287,288,290,293,295,297],{"class":38,"line":75},[36,289,43],{"class":42},[36,291,292],{"class":46}," { NoLagAgents, Handoff } ",[36,294,50],{"class":42},[36,296,70],{"class":53},[36,298,57],{"class":46},[36,300,301],{"class":38,"line":82},[36,302,79],{"emptyLinePlaceholder":78},[36,304,305,307,309,311,313,315,318],{"class":38,"line":108},[36,306,85],{"class":42},[36,308,89],{"class":88},[36,310,92],{"class":42},[36,312,96],{"class":95},[36,314,99],{"class":46},[36,316,317],{"class":88},"BOT_TOKEN",[36,319,105],{"class":46},[36,321,322,324,327,329,331,334,337,340,343,346],{"class":38,"line":127},[36,323,85],{"class":42},[36,325,326],{"class":88}," chat",[36,328,92],{"class":42},[36,330,118],{"class":42},[36,332,333],{"class":95}," NoLagChat",[36,335,336],{"class":46},"({ client, appName: ",[36,338,339],{"class":88},"CHAT_APP_SLUG",[36,341,342],{"class":46},", username: ",[36,344,345],{"class":53},"\"support-bot\"",[36,347,348],{"class":46}," });\n",[36,350,351,353,355,357,359,361],{"class":38,"line":133},[36,352,85],{"class":42},[36,354,113],{"class":88},[36,356,92],{"class":42},[36,358,118],{"class":42},[36,360,121],{"class":95},[36,362,124],{"class":46},[36,364,365],{"class":38,"line":149},[36,366,130],{"class":46},[36,368,369,371,374],{"class":38,"line":161},[36,370,136],{"class":46},[36,372,373],{"class":88},"AGENTS_APP_SLUG",[36,375,158],{"class":46},[36,377,378,380,383],{"class":38,"line":177},[36,379,152],{"class":46},[36,381,382],{"class":53},"\"support-bridge\"",[36,384,158],{"class":46},[36,386,387,389,391,393,395],{"class":38,"line":183},[36,388,164],{"class":46},[36,390,382],{"class":53},[36,392,169],{"class":46},[36,394,155],{"class":53},[36,396,174],{"class":46},[36,398,399],{"class":38,"line":198},[36,400,180],{"class":46},[36,402,403,405,407,409],{"class":38,"line":211},[36,404,186],{"class":42},[36,406,189],{"class":46},[36,408,192],{"class":95},[36,410,195],{"class":46},[36,412,413,415,418,421,424,427,429,432,434],{"class":38,"line":216},[36,414,186],{"class":42},[36,416,417],{"class":88}," Promise",[36,419,420],{"class":46},".",[36,422,423],{"class":95},"all",[36,425,426],{"class":46},"([chat.",[36,428,206],{"class":95},[36,430,431],{"class":46},"(), agents.",[36,433,206],{"class":95},[36,435,436],{"class":46},"()]);\n",[36,438,440],{"class":38,"line":439},15,[36,441,79],{"emptyLinePlaceholder":78},[36,443,445,447,450,452,455,458,460,463],{"class":38,"line":444},16,[36,446,85],{"class":42},[36,448,449],{"class":88}," chatRoom",[36,451,92],{"class":42},[36,453,454],{"class":46}," chat.",[36,456,457],{"class":95},"joinRoom",[36,459,99],{"class":46},[36,461,462],{"class":53},"\"general\"",[36,464,105],{"class":46},[36,466,468,470,473,475,477,480,483,485,487,489],{"class":38,"line":467},17,[36,469,85],{"class":42},[36,471,472],{"class":88}," handoff",[36,474,92],{"class":42},[36,476,118],{"class":42},[36,478,479],{"class":95}," Handoff",[36,481,482],{"class":46},"(agents.",[36,484,228],{"class":95},[36,486,99],{"class":46},[36,488,233],{"class":53},[36,490,491],{"class":46},"));\n",[36,493,495],{"class":38,"line":494},18,[36,496,79],{"emptyLinePlaceholder":78},[36,498,500],{"class":38,"line":499},19,[36,501,502],{"class":145},"// Fires for other users' messages only; publishers never receive their own\n",[36,504,506,509,512,514,517,519,522,525,529,532,535],{"class":38,"line":505},20,[36,507,508],{"class":46},"chatRoom.",[36,510,511],{"class":95},"on",[36,513,99],{"class":46},[36,515,516],{"class":53},"\"message\"",[36,518,142],{"class":46},[36,520,521],{"class":42},"async",[36,523,524],{"class":46}," (",[36,526,528],{"class":527},"s4XuR","msg",[36,530,531],{"class":46},") ",[36,533,534],{"class":42},"=>",[36,536,537],{"class":46}," {\n",[36,539,541,544,547,549,552,555,558],{"class":38,"line":540},21,[36,542,543],{"class":42},"  const",[36,545,546],{"class":88}," result",[36,548,92],{"class":42},[36,550,551],{"class":42}," await",[36,553,554],{"class":46}," handoff.",[36,556,557],{"class":95},"dispatch",[36,559,560],{"class":46},"(\n",[36,562,564,567],{"class":38,"line":563},22,[36,565,566],{"class":53},"    \"customer-support\"",[36,568,158],{"class":46},[36,570,572,575,578,581,584,587,590,592,594],{"class":38,"line":571},23,[36,573,574],{"class":46},"    { userId: msg.userId, text: msg.text, history: chatRoom.",[36,576,577],{"class":95},"getMessages",[36,579,580],{"class":46},"().",[36,582,583],{"class":95},"map",[36,585,586],{"class":46},"((",[36,588,589],{"class":527},"m",[36,591,531],{"class":46},[36,593,534],{"class":42},[36,595,596],{"class":46}," m.text) },\n",[36,598,600,603,606,609,612],{"class":38,"line":599},24,[36,601,602],{"class":46},"    { waitForResult: ",[36,604,605],{"class":88},"true",[36,607,608],{"class":46},", timeout: ",[36,610,611],{"class":88},"30000",[36,613,174],{"class":46},[36,615,617],{"class":38,"line":616},25,[36,618,619],{"class":46},"  );\n",[36,621,623,626,629,632,635,638,641],{"class":38,"line":622},26,[36,624,625],{"class":42},"  if",[36,627,628],{"class":46}," (result ",[36,630,631],{"class":42},"&&",[36,633,634],{"class":46}," result.status ",[36,636,637],{"class":42},"===",[36,639,640],{"class":53}," \"success\"",[36,642,643],{"class":46},") {\n",[36,645,647,650,653,655,658],{"class":38,"line":646},27,[36,648,649],{"class":46},"    chatRoom.",[36,651,652],{"class":95},"sendMessage",[36,654,99],{"class":46},[36,656,657],{"class":95},"String",[36,659,660],{"class":46},"(result.payload.response));\n",[36,662,664],{"class":38,"line":663},28,[36,665,666],{"class":46},"  }\n",[36,668,670],{"class":38,"line":669},29,[36,671,180],{"class":46},[15,673,674,678],{},[675,676,677],"strong",{},"Patterns used:"," Handoff (task dispatch), composition (one actor on two apps)",[237,680,682],{"id":681},"autonomous-workflow","Autonomous Workflow",[15,684,685],{},"A multi-step pipeline where the orchestrator advances through a plan. Each step's output feeds the next step, and progress is recorded on the Blackboard so every agent (and the portal dashboard) can see where the pipeline is.",[22,687,688],{},[25,689,691],{"className":27,"code":690,"filename":257,"language":30,"meta":31,"style":31},"import { Handoff, Blackboard } from \"@nolag/agents\";\n\nconst handoff = new Handoff(room);\nconst blackboard = new Blackboard(room, agents.agentId);\n\nconst steps = [\"research\", \"analyze\", \"draft\", \"review\"];\nconst results: Record\u003Cstring, unknown> = {};\nblackboard.set(\"plan\", { steps, current: 0, results });\n\nlet input: Record\u003Cstring, unknown> = { topic: \"AI agent coordination\" };\n\nfor (let i = 0; i \u003C steps.length; i++) {\n  const step = steps[i];\n\n  // Each step is a capability; dispatch() throws if no worker advertises it\n  const result = await handoff.dispatch(step, input, { waitForResult: true, timeout: 120000 });\n\n  if (!result || result.status === \"error\") {\n    blackboard.set(\"plan\", { steps, current: i, results, failed: step, error: result ? result.error : undefined });\n    break;\n  }\n\n  results[step] = result.payload;\n  blackboard.set(\"plan\", { steps, current: i + 1, results });\n  input = result.payload; // this step's output is the next step's input\n}\n",[33,692,693,706,710,725,742,746,779,812,834,838,871,875,911,923,927,932,958,962,986,1013,1020,1024,1028,1038,1060,1073],{"__ignoreMap":31},[36,694,695,697,700,702,704],{"class":38,"line":39},[36,696,43],{"class":42},[36,698,699],{"class":46}," { Handoff, Blackboard } ",[36,701,50],{"class":42},[36,703,70],{"class":53},[36,705,57],{"class":46},[36,707,708],{"class":38,"line":60},[36,709,79],{"emptyLinePlaceholder":78},[36,711,712,714,716,718,720,722],{"class":38,"line":75},[36,713,85],{"class":42},[36,715,472],{"class":88},[36,717,92],{"class":42},[36,719,118],{"class":42},[36,721,479],{"class":95},[36,723,724],{"class":46},"(room);\n",[36,726,727,729,732,734,736,739],{"class":38,"line":82},[36,728,85],{"class":42},[36,730,731],{"class":88}," blackboard",[36,733,92],{"class":42},[36,735,118],{"class":42},[36,737,738],{"class":95}," Blackboard",[36,740,741],{"class":46},"(room, agents.agentId);\n",[36,743,744],{"class":38,"line":108},[36,745,79],{"emptyLinePlaceholder":78},[36,747,748,750,753,755,758,761,763,766,768,771,773,776],{"class":38,"line":127},[36,749,85],{"class":42},[36,751,752],{"class":88}," steps",[36,754,92],{"class":42},[36,756,757],{"class":46}," [",[36,759,760],{"class":53},"\"research\"",[36,762,142],{"class":46},[36,764,765],{"class":53},"\"analyze\"",[36,767,142],{"class":46},[36,769,770],{"class":53},"\"draft\"",[36,772,142],{"class":46},[36,774,775],{"class":53},"\"review\"",[36,777,778],{"class":46},"];\n",[36,780,781,783,786,789,792,795,798,800,803,806,809],{"class":38,"line":133},[36,782,85],{"class":42},[36,784,785],{"class":88}," results",[36,787,788],{"class":42},":",[36,790,791],{"class":95}," Record",[36,793,794],{"class":46},"\u003C",[36,796,797],{"class":88},"string",[36,799,142],{"class":46},[36,801,802],{"class":88},"unknown",[36,804,805],{"class":46},"> ",[36,807,808],{"class":42},"=",[36,810,811],{"class":46}," {};\n",[36,813,814,817,820,822,825,828,831],{"class":38,"line":149},[36,815,816],{"class":46},"blackboard.",[36,818,819],{"class":95},"set",[36,821,99],{"class":46},[36,823,824],{"class":53},"\"plan\"",[36,826,827],{"class":46},", { steps, current: ",[36,829,830],{"class":88},"0",[36,832,833],{"class":46},", results });\n",[36,835,836],{"class":38,"line":161},[36,837,79],{"emptyLinePlaceholder":78},[36,839,840,843,846,848,850,852,854,856,858,860,862,865,868],{"class":38,"line":177},[36,841,842],{"class":42},"let",[36,844,845],{"class":46}," input",[36,847,788],{"class":42},[36,849,791],{"class":95},[36,851,794],{"class":46},[36,853,797],{"class":88},[36,855,142],{"class":46},[36,857,802],{"class":88},[36,859,805],{"class":46},[36,861,808],{"class":42},[36,863,864],{"class":46}," { topic: ",[36,866,867],{"class":53},"\"AI agent coordination\"",[36,869,870],{"class":46}," };\n",[36,872,873],{"class":38,"line":183},[36,874,79],{"emptyLinePlaceholder":78},[36,876,877,880,882,884,887,889,892,895,897,900,903,906,909],{"class":38,"line":198},[36,878,879],{"class":42},"for",[36,881,524],{"class":46},[36,883,842],{"class":42},[36,885,886],{"class":46}," i ",[36,888,808],{"class":42},[36,890,891],{"class":88}," 0",[36,893,894],{"class":46},"; i ",[36,896,794],{"class":42},[36,898,899],{"class":46}," steps.",[36,901,902],{"class":88},"length",[36,904,905],{"class":46},"; i",[36,907,908],{"class":42},"++",[36,910,643],{"class":46},[36,912,913,915,918,920],{"class":38,"line":211},[36,914,543],{"class":42},[36,916,917],{"class":88}," step",[36,919,92],{"class":42},[36,921,922],{"class":46}," steps[i];\n",[36,924,925],{"class":38,"line":216},[36,926,79],{"emptyLinePlaceholder":78},[36,928,929],{"class":38,"line":439},[36,930,931],{"class":145},"  // Each step is a capability; dispatch() throws if no worker advertises it\n",[36,933,934,936,938,940,942,944,946,949,951,953,956],{"class":38,"line":444},[36,935,543],{"class":42},[36,937,546],{"class":88},[36,939,92],{"class":42},[36,941,551],{"class":42},[36,943,554],{"class":46},[36,945,557],{"class":95},[36,947,948],{"class":46},"(step, input, { waitForResult: ",[36,950,605],{"class":88},[36,952,608],{"class":46},[36,954,955],{"class":88},"120000",[36,957,348],{"class":46},[36,959,960],{"class":38,"line":467},[36,961,79],{"emptyLinePlaceholder":78},[36,963,964,966,968,971,974,977,979,981,984],{"class":38,"line":494},[36,965,625],{"class":42},[36,967,524],{"class":46},[36,969,970],{"class":42},"!",[36,972,973],{"class":46},"result ",[36,975,976],{"class":42},"||",[36,978,634],{"class":46},[36,980,637],{"class":42},[36,982,983],{"class":53}," \"error\"",[36,985,643],{"class":46},[36,987,988,991,993,995,997,1000,1003,1006,1008,1011],{"class":38,"line":499},[36,989,990],{"class":46},"    blackboard.",[36,992,819],{"class":95},[36,994,99],{"class":46},[36,996,824],{"class":53},[36,998,999],{"class":46},", { steps, current: i, results, failed: step, error: result ",[36,1001,1002],{"class":42},"?",[36,1004,1005],{"class":46}," result.error ",[36,1007,788],{"class":42},[36,1009,1010],{"class":88}," undefined",[36,1012,348],{"class":46},[36,1014,1015,1018],{"class":38,"line":505},[36,1016,1017],{"class":42},"    break",[36,1019,57],{"class":46},[36,1021,1022],{"class":38,"line":540},[36,1023,666],{"class":46},[36,1025,1026],{"class":38,"line":563},[36,1027,79],{"emptyLinePlaceholder":78},[36,1029,1030,1033,1035],{"class":38,"line":571},[36,1031,1032],{"class":46},"  results[step] ",[36,1034,808],{"class":42},[36,1036,1037],{"class":46}," result.payload;\n",[36,1039,1040,1043,1045,1047,1049,1052,1055,1058],{"class":38,"line":599},[36,1041,1042],{"class":46},"  blackboard.",[36,1044,819],{"class":95},[36,1046,99],{"class":46},[36,1048,824],{"class":53},[36,1050,1051],{"class":46},", { steps, current: i ",[36,1053,1054],{"class":42},"+",[36,1056,1057],{"class":88}," 1",[36,1059,833],{"class":46},[36,1061,1062,1065,1067,1070],{"class":38,"line":616},[36,1063,1064],{"class":46},"  input ",[36,1066,808],{"class":42},[36,1068,1069],{"class":46}," result.payload; ",[36,1071,1072],{"class":145},"// this step's output is the next step's input\n",[36,1074,1075],{"class":38,"line":622},[36,1076,1077],{"class":46},"}\n",[15,1079,1080,1082],{},[675,1081,677],{}," Handoff (task dispatch), Blackboard (workflow state)",[237,1084,1086],{"id":1085},"copilot-pattern","Copilot Pattern",[15,1088,1089,1090,1092],{},"An AI copilot that watches editor state via the Blackboard and returns suggestions the same way. The editor writes its state to one key, a copilot process reacts to changes by dispatching a task to a ",[33,1091,33],{}," worker, and writes the suggestion to another key the editor watches.",[22,1094,1095,1266],{},[25,1096,1099],{"className":27,"code":1097,"filename":1098,"language":30,"meta":31,"style":31},"import { Blackboard } from \"@nolag/agents\";\n\nconst blackboard = new Blackboard(room, agents.agentId);\n\n// Publish editor state as the user types\neditor.on(\"change\", (content: string) => {\n  blackboard.set(\"editor-state\", {\n    content,\n    cursor: editor.getCursorPosition(),\n    language: editor.getLanguage(),\n  });\n});\n\n// Show suggestions as they arrive\nblackboard.onChange(\"suggestion\", (envelope) => {\n  editor.showSuggestion(envelope.value);\n});\n","Editor",[33,1100,1101,1114,1118,1132,1136,1141,1170,1184,1189,1200,1210,1215,1219,1223,1228,1251,1262],{"__ignoreMap":31},[36,1102,1103,1105,1108,1110,1112],{"class":38,"line":39},[36,1104,43],{"class":42},[36,1106,1107],{"class":46}," { Blackboard } ",[36,1109,50],{"class":42},[36,1111,70],{"class":53},[36,1113,57],{"class":46},[36,1115,1116],{"class":38,"line":60},[36,1117,79],{"emptyLinePlaceholder":78},[36,1119,1120,1122,1124,1126,1128,1130],{"class":38,"line":75},[36,1121,85],{"class":42},[36,1123,731],{"class":88},[36,1125,92],{"class":42},[36,1127,118],{"class":42},[36,1129,738],{"class":95},[36,1131,741],{"class":46},[36,1133,1134],{"class":38,"line":82},[36,1135,79],{"emptyLinePlaceholder":78},[36,1137,1138],{"class":38,"line":108},[36,1139,1140],{"class":145},"// Publish editor state as the user types\n",[36,1142,1143,1146,1148,1150,1153,1156,1159,1161,1164,1166,1168],{"class":38,"line":127},[36,1144,1145],{"class":46},"editor.",[36,1147,511],{"class":95},[36,1149,99],{"class":46},[36,1151,1152],{"class":53},"\"change\"",[36,1154,1155],{"class":46},", (",[36,1157,1158],{"class":527},"content",[36,1160,788],{"class":42},[36,1162,1163],{"class":88}," string",[36,1165,531],{"class":46},[36,1167,534],{"class":42},[36,1169,537],{"class":46},[36,1171,1172,1174,1176,1178,1181],{"class":38,"line":133},[36,1173,1042],{"class":46},[36,1175,819],{"class":95},[36,1177,99],{"class":46},[36,1179,1180],{"class":53},"\"editor-state\"",[36,1182,1183],{"class":46},", {\n",[36,1185,1186],{"class":38,"line":149},[36,1187,1188],{"class":46},"    content,\n",[36,1190,1191,1194,1197],{"class":38,"line":161},[36,1192,1193],{"class":46},"    cursor: editor.",[36,1195,1196],{"class":95},"getCursorPosition",[36,1198,1199],{"class":46},"(),\n",[36,1201,1202,1205,1208],{"class":38,"line":177},[36,1203,1204],{"class":46},"    language: editor.",[36,1206,1207],{"class":95},"getLanguage",[36,1209,1199],{"class":46},[36,1211,1212],{"class":38,"line":183},[36,1213,1214],{"class":46},"  });\n",[36,1216,1217],{"class":38,"line":198},[36,1218,180],{"class":46},[36,1220,1221],{"class":38,"line":211},[36,1222,79],{"emptyLinePlaceholder":78},[36,1224,1225],{"class":38,"line":216},[36,1226,1227],{"class":145},"// Show suggestions as they arrive\n",[36,1229,1230,1232,1235,1237,1240,1242,1245,1247,1249],{"class":38,"line":439},[36,1231,816],{"class":46},[36,1233,1234],{"class":95},"onChange",[36,1236,99],{"class":46},[36,1238,1239],{"class":53},"\"suggestion\"",[36,1241,1155],{"class":46},[36,1243,1244],{"class":527},"envelope",[36,1246,531],{"class":46},[36,1248,534],{"class":42},[36,1250,537],{"class":46},[36,1252,1253,1256,1259],{"class":38,"line":444},[36,1254,1255],{"class":46},"  editor.",[36,1257,1258],{"class":95},"showSuggestion",[36,1260,1261],{"class":46},"(envelope.value);\n",[36,1263,1264],{"class":38,"line":467},[36,1265,180],{"class":46},[25,1267,1270],{"className":27,"code":1268,"filename":1269,"language":30,"meta":31,"style":31},"import { Handoff, Blackboard } from \"@nolag/agents\";\n\nconst handoff = new Handoff(room);\nconst blackboard = new Blackboard(room, agents.agentId);\n\n// React to editor changes with a suggestion task\nblackboard.onChange(\"editor-state\", async (envelope) => {\n  const result = await handoff.dispatch(\n    \"code\",\n    envelope.value as Record\u003Cstring, unknown>,\n    { waitForResult: true, timeout: 10000 },\n  );\n  if (result && result.status === \"success\") {\n    blackboard.set(\"suggestion\", result.payload.suggestion);\n  }\n});\n","Copilot",[33,1271,1272,1284,1288,1302,1316,1320,1325,1349,1365,1372,1393,1406,1410,1426,1439,1443],{"__ignoreMap":31},[36,1273,1274,1276,1278,1280,1282],{"class":38,"line":39},[36,1275,43],{"class":42},[36,1277,699],{"class":46},[36,1279,50],{"class":42},[36,1281,70],{"class":53},[36,1283,57],{"class":46},[36,1285,1286],{"class":38,"line":60},[36,1287,79],{"emptyLinePlaceholder":78},[36,1289,1290,1292,1294,1296,1298,1300],{"class":38,"line":75},[36,1291,85],{"class":42},[36,1293,472],{"class":88},[36,1295,92],{"class":42},[36,1297,118],{"class":42},[36,1299,479],{"class":95},[36,1301,724],{"class":46},[36,1303,1304,1306,1308,1310,1312,1314],{"class":38,"line":82},[36,1305,85],{"class":42},[36,1307,731],{"class":88},[36,1309,92],{"class":42},[36,1311,118],{"class":42},[36,1313,738],{"class":95},[36,1315,741],{"class":46},[36,1317,1318],{"class":38,"line":108},[36,1319,79],{"emptyLinePlaceholder":78},[36,1321,1322],{"class":38,"line":127},[36,1323,1324],{"class":145},"// React to editor changes with a suggestion task\n",[36,1326,1327,1329,1331,1333,1335,1337,1339,1341,1343,1345,1347],{"class":38,"line":133},[36,1328,816],{"class":46},[36,1330,1234],{"class":95},[36,1332,99],{"class":46},[36,1334,1180],{"class":53},[36,1336,142],{"class":46},[36,1338,521],{"class":42},[36,1340,524],{"class":46},[36,1342,1244],{"class":527},[36,1344,531],{"class":46},[36,1346,534],{"class":42},[36,1348,537],{"class":46},[36,1350,1351,1353,1355,1357,1359,1361,1363],{"class":38,"line":149},[36,1352,543],{"class":42},[36,1354,546],{"class":88},[36,1356,92],{"class":42},[36,1358,551],{"class":42},[36,1360,554],{"class":46},[36,1362,557],{"class":95},[36,1364,560],{"class":46},[36,1366,1367,1370],{"class":38,"line":161},[36,1368,1369],{"class":53},"    \"code\"",[36,1371,158],{"class":46},[36,1373,1374,1377,1380,1382,1384,1386,1388,1390],{"class":38,"line":177},[36,1375,1376],{"class":46},"    envelope.value ",[36,1378,1379],{"class":42},"as",[36,1381,791],{"class":95},[36,1383,794],{"class":46},[36,1385,797],{"class":88},[36,1387,142],{"class":46},[36,1389,802],{"class":88},[36,1391,1392],{"class":46},">,\n",[36,1394,1395,1397,1399,1401,1404],{"class":38,"line":183},[36,1396,602],{"class":46},[36,1398,605],{"class":88},[36,1400,608],{"class":46},[36,1402,1403],{"class":88},"10000",[36,1405,174],{"class":46},[36,1407,1408],{"class":38,"line":198},[36,1409,619],{"class":46},[36,1411,1412,1414,1416,1418,1420,1422,1424],{"class":38,"line":211},[36,1413,625],{"class":42},[36,1415,628],{"class":46},[36,1417,631],{"class":42},[36,1419,634],{"class":46},[36,1421,637],{"class":42},[36,1423,640],{"class":53},[36,1425,643],{"class":46},[36,1427,1428,1430,1432,1434,1436],{"class":38,"line":216},[36,1429,990],{"class":46},[36,1431,819],{"class":95},[36,1433,99],{"class":46},[36,1435,1239],{"class":53},[36,1437,1438],{"class":46},", result.payload.suggestion);\n",[36,1440,1441],{"class":38,"line":439},[36,1442,666],{"class":46},[36,1444,1445],{"class":38,"line":444},[36,1446,180],{"class":46},[15,1448,1449,1451],{},[675,1450,677],{}," Blackboard (shared state), Handoff (suggestion generation)",[237,1453,1455],{"id":1454},"compliance-approval-workflow","Compliance / Approval Workflow",[15,1457,1458],{},"An agent generates a report and requests human approval before publishing. The human can approve, reject, or defer, with an optional reason. Each outcome is emitted with Observe so the flow is auditable in the Event Stream.",[22,1460,1461,1732],{},[25,1462,1465],{"className":27,"code":1463,"filename":1464,"language":30,"meta":31,"style":31},"import { Approve, Observe } from \"@nolag/agents\";\n\nconst approve = new Approve(room, agents.agentId);\nconst observe = new Observe(room, agents.agentId);\n\nconst draft = await generateReport(data);\n\ntry {\n  const approval = await approve.request(\n    \"publish-report\",\n    { title: \"Q3 earnings report\", author: \"finance-agent\", content: draft },\n    { urgency: \"high\", timeout: 3600000 }, // 1 hour, then the promise rejects\n  );\n\n  if (approval.decision === \"approved\") {\n    await publishReport(draft);\n    observe.emit(\"report:published\", { approvedBy: approval.respondedBy });\n  } else {\n    observe.emit(\"report:rejected\", { decision: approval.decision, reason: approval.reason }, \"warning\");\n  }\n} catch (err) {\n  observe.emit(\"report:unanswered\", { message: String(err) }, \"error\");\n}\n","Agent",[33,1466,1467,1480,1484,1500,1516,1520,1537,1541,1548,1567,1574,1591,1610,1614,1618,1632,1643,1659,1669,1688,1692,1703,1728],{"__ignoreMap":31},[36,1468,1469,1471,1474,1476,1478],{"class":38,"line":39},[36,1470,43],{"class":42},[36,1472,1473],{"class":46}," { Approve, Observe } ",[36,1475,50],{"class":42},[36,1477,70],{"class":53},[36,1479,57],{"class":46},[36,1481,1482],{"class":38,"line":60},[36,1483,79],{"emptyLinePlaceholder":78},[36,1485,1486,1488,1491,1493,1495,1498],{"class":38,"line":75},[36,1487,85],{"class":42},[36,1489,1490],{"class":88}," approve",[36,1492,92],{"class":42},[36,1494,118],{"class":42},[36,1496,1497],{"class":95}," Approve",[36,1499,741],{"class":46},[36,1501,1502,1504,1507,1509,1511,1514],{"class":38,"line":82},[36,1503,85],{"class":42},[36,1505,1506],{"class":88}," observe",[36,1508,92],{"class":42},[36,1510,118],{"class":42},[36,1512,1513],{"class":95}," Observe",[36,1515,741],{"class":46},[36,1517,1518],{"class":38,"line":108},[36,1519,79],{"emptyLinePlaceholder":78},[36,1521,1522,1524,1527,1529,1531,1534],{"class":38,"line":127},[36,1523,85],{"class":42},[36,1525,1526],{"class":88}," draft",[36,1528,92],{"class":42},[36,1530,551],{"class":42},[36,1532,1533],{"class":95}," generateReport",[36,1535,1536],{"class":46},"(data);\n",[36,1538,1539],{"class":38,"line":133},[36,1540,79],{"emptyLinePlaceholder":78},[36,1542,1543,1546],{"class":38,"line":149},[36,1544,1545],{"class":42},"try",[36,1547,537],{"class":46},[36,1549,1550,1552,1555,1557,1559,1562,1565],{"class":38,"line":161},[36,1551,543],{"class":42},[36,1553,1554],{"class":88}," approval",[36,1556,92],{"class":42},[36,1558,551],{"class":42},[36,1560,1561],{"class":46}," approve.",[36,1563,1564],{"class":95},"request",[36,1566,560],{"class":46},[36,1568,1569,1572],{"class":38,"line":177},[36,1570,1571],{"class":53},"    \"publish-report\"",[36,1573,158],{"class":46},[36,1575,1576,1579,1582,1585,1588],{"class":38,"line":183},[36,1577,1578],{"class":46},"    { title: ",[36,1580,1581],{"class":53},"\"Q3 earnings report\"",[36,1583,1584],{"class":46},", author: ",[36,1586,1587],{"class":53},"\"finance-agent\"",[36,1589,1590],{"class":46},", content: draft },\n",[36,1592,1593,1596,1599,1601,1604,1607],{"class":38,"line":198},[36,1594,1595],{"class":46},"    { urgency: ",[36,1597,1598],{"class":53},"\"high\"",[36,1600,608],{"class":46},[36,1602,1603],{"class":88},"3600000",[36,1605,1606],{"class":46}," }, ",[36,1608,1609],{"class":145},"// 1 hour, then the promise rejects\n",[36,1611,1612],{"class":38,"line":211},[36,1613,619],{"class":46},[36,1615,1616],{"class":38,"line":216},[36,1617,79],{"emptyLinePlaceholder":78},[36,1619,1620,1622,1625,1627,1630],{"class":38,"line":439},[36,1621,625],{"class":42},[36,1623,1624],{"class":46}," (approval.decision ",[36,1626,637],{"class":42},[36,1628,1629],{"class":53}," \"approved\"",[36,1631,643],{"class":46},[36,1633,1634,1637,1640],{"class":38,"line":444},[36,1635,1636],{"class":42},"    await",[36,1638,1639],{"class":95}," publishReport",[36,1641,1642],{"class":46},"(draft);\n",[36,1644,1645,1648,1651,1653,1656],{"class":38,"line":467},[36,1646,1647],{"class":46},"    observe.",[36,1649,1650],{"class":95},"emit",[36,1652,99],{"class":46},[36,1654,1655],{"class":53},"\"report:published\"",[36,1657,1658],{"class":46},", { approvedBy: approval.respondedBy });\n",[36,1660,1661,1664,1667],{"class":38,"line":494},[36,1662,1663],{"class":46},"  } ",[36,1665,1666],{"class":42},"else",[36,1668,537],{"class":46},[36,1670,1671,1673,1675,1677,1680,1683,1686],{"class":38,"line":499},[36,1672,1647],{"class":46},[36,1674,1650],{"class":95},[36,1676,99],{"class":46},[36,1678,1679],{"class":53},"\"report:rejected\"",[36,1681,1682],{"class":46},", { decision: approval.decision, reason: approval.reason }, ",[36,1684,1685],{"class":53},"\"warning\"",[36,1687,105],{"class":46},[36,1689,1690],{"class":38,"line":505},[36,1691,666],{"class":46},[36,1693,1694,1697,1700],{"class":38,"line":540},[36,1695,1696],{"class":46},"} ",[36,1698,1699],{"class":42},"catch",[36,1701,1702],{"class":46}," (err) {\n",[36,1704,1705,1708,1710,1712,1715,1718,1720,1723,1726],{"class":38,"line":563},[36,1706,1707],{"class":46},"  observe.",[36,1709,1650],{"class":95},[36,1711,99],{"class":46},[36,1713,1714],{"class":53},"\"report:unanswered\"",[36,1716,1717],{"class":46},", { message: ",[36,1719,657],{"class":95},[36,1721,1722],{"class":46},"(err) }, ",[36,1724,1725],{"class":53},"\"error\"",[36,1727,105],{"class":46},[36,1729,1730],{"class":38,"line":571},[36,1731,1077],{"class":46},[25,1733,1736],{"className":27,"code":1734,"filename":1735,"language":30,"meta":31,"style":31},"import { Approve } from \"@nolag/agents\";\n\nconst approve = new Approve(room, agents.agentId);\n\n// A human-facing app renders the request and forwards the decision\napprove.onRequest((request, respond) => {\n  showApprovalDialog(request.action, request.context, request.urgency, (approved: boolean, reason?: string) => {\n    respond(approved ? \"approved\" : \"rejected\", reason);\n  });\n});\n","Approver",[33,1737,1738,1751,1755,1769,1773,1778,1801,1833,1854,1858],{"__ignoreMap":31},[36,1739,1740,1742,1745,1747,1749],{"class":38,"line":39},[36,1741,43],{"class":42},[36,1743,1744],{"class":46}," { Approve } ",[36,1746,50],{"class":42},[36,1748,70],{"class":53},[36,1750,57],{"class":46},[36,1752,1753],{"class":38,"line":60},[36,1754,79],{"emptyLinePlaceholder":78},[36,1756,1757,1759,1761,1763,1765,1767],{"class":38,"line":75},[36,1758,85],{"class":42},[36,1760,1490],{"class":88},[36,1762,92],{"class":42},[36,1764,118],{"class":42},[36,1766,1497],{"class":95},[36,1768,741],{"class":46},[36,1770,1771],{"class":38,"line":82},[36,1772,79],{"emptyLinePlaceholder":78},[36,1774,1775],{"class":38,"line":108},[36,1776,1777],{"class":145},"// A human-facing app renders the request and forwards the decision\n",[36,1779,1780,1783,1786,1788,1790,1792,1795,1797,1799],{"class":38,"line":127},[36,1781,1782],{"class":46},"approve.",[36,1784,1785],{"class":95},"onRequest",[36,1787,586],{"class":46},[36,1789,1564],{"class":527},[36,1791,142],{"class":46},[36,1793,1794],{"class":527},"respond",[36,1796,531],{"class":46},[36,1798,534],{"class":42},[36,1800,537],{"class":46},[36,1802,1803,1806,1809,1812,1814,1817,1819,1822,1825,1827,1829,1831],{"class":38,"line":133},[36,1804,1805],{"class":95},"  showApprovalDialog",[36,1807,1808],{"class":46},"(request.action, request.context, request.urgency, (",[36,1810,1811],{"class":527},"approved",[36,1813,788],{"class":42},[36,1815,1816],{"class":88}," boolean",[36,1818,142],{"class":46},[36,1820,1821],{"class":527},"reason",[36,1823,1824],{"class":42},"?:",[36,1826,1163],{"class":88},[36,1828,531],{"class":46},[36,1830,534],{"class":42},[36,1832,537],{"class":46},[36,1834,1835,1838,1841,1843,1845,1848,1851],{"class":38,"line":149},[36,1836,1837],{"class":95},"    respond",[36,1839,1840],{"class":46},"(approved ",[36,1842,1002],{"class":42},[36,1844,1629],{"class":53},[36,1846,1847],{"class":42}," :",[36,1849,1850],{"class":53}," \"rejected\"",[36,1852,1853],{"class":46},", reason);\n",[36,1855,1856],{"class":38,"line":161},[36,1857,1214],{"class":46},[36,1859,1860],{"class":38,"line":177},[36,1861,180],{"class":46},[15,1863,1864,1866],{},[675,1865,677],{}," Approve (human-in-the-loop), Observe (audit trail)",[237,1868,1870],{"id":1869},"tool-augmented-agent","Tool-Augmented Agent",[15,1872,1873],{},"A tool server registers handlers for web search and database queries. A worker invokes them by name while handling a task. Handlers are local to the server that registered them; callers need to know the tool names.",[22,1875,1876,2040],{},[25,1877,1880],{"className":27,"code":1878,"filename":1879,"language":30,"meta":31,"style":31},"import { Tools } from \"@nolag/agents\";\n\nconst tools = new Tools(room, agents.agentId);\n\ntools.register(\"web-search\", async (args) => {\n  return { results: await searchWeb(args.query as string) };\n});\n\ntools.register(\"database-query\", async (args) => {\n  return { rows: await db.query(args.sql as string, args.params as unknown[]) };\n});\n","Tool server",[33,1881,1882,1895,1899,1915,1919,1947,1970,1974,1978,2003,2036],{"__ignoreMap":31},[36,1883,1884,1886,1889,1891,1893],{"class":38,"line":39},[36,1885,43],{"class":42},[36,1887,1888],{"class":46}," { Tools } ",[36,1890,50],{"class":42},[36,1892,70],{"class":53},[36,1894,57],{"class":46},[36,1896,1897],{"class":38,"line":60},[36,1898,79],{"emptyLinePlaceholder":78},[36,1900,1901,1903,1906,1908,1910,1913],{"class":38,"line":75},[36,1902,85],{"class":42},[36,1904,1905],{"class":88}," tools",[36,1907,92],{"class":42},[36,1909,118],{"class":42},[36,1911,1912],{"class":95}," Tools",[36,1914,741],{"class":46},[36,1916,1917],{"class":38,"line":82},[36,1918,79],{"emptyLinePlaceholder":78},[36,1920,1921,1924,1927,1929,1932,1934,1936,1938,1941,1943,1945],{"class":38,"line":108},[36,1922,1923],{"class":46},"tools.",[36,1925,1926],{"class":95},"register",[36,1928,99],{"class":46},[36,1930,1931],{"class":53},"\"web-search\"",[36,1933,142],{"class":46},[36,1935,521],{"class":42},[36,1937,524],{"class":46},[36,1939,1940],{"class":527},"args",[36,1942,531],{"class":46},[36,1944,534],{"class":42},[36,1946,537],{"class":46},[36,1948,1949,1952,1955,1957,1960,1963,1965,1967],{"class":38,"line":127},[36,1950,1951],{"class":42},"  return",[36,1953,1954],{"class":46}," { results: ",[36,1956,186],{"class":42},[36,1958,1959],{"class":95}," searchWeb",[36,1961,1962],{"class":46},"(args.query ",[36,1964,1379],{"class":42},[36,1966,1163],{"class":88},[36,1968,1969],{"class":46},") };\n",[36,1971,1972],{"class":38,"line":133},[36,1973,180],{"class":46},[36,1975,1976],{"class":38,"line":149},[36,1977,79],{"emptyLinePlaceholder":78},[36,1979,1980,1982,1984,1986,1989,1991,1993,1995,1997,1999,2001],{"class":38,"line":161},[36,1981,1923],{"class":46},[36,1983,1926],{"class":95},[36,1985,99],{"class":46},[36,1987,1988],{"class":53},"\"database-query\"",[36,1990,142],{"class":46},[36,1992,521],{"class":42},[36,1994,524],{"class":46},[36,1996,1940],{"class":527},[36,1998,531],{"class":46},[36,2000,534],{"class":42},[36,2002,537],{"class":46},[36,2004,2005,2007,2010,2012,2015,2018,2021,2023,2025,2028,2030,2033],{"class":38,"line":177},[36,2006,1951],{"class":42},[36,2008,2009],{"class":46}," { rows: ",[36,2011,186],{"class":42},[36,2013,2014],{"class":46}," db.",[36,2016,2017],{"class":95},"query",[36,2019,2020],{"class":46},"(args.sql ",[36,2022,1379],{"class":42},[36,2024,1163],{"class":88},[36,2026,2027],{"class":46},", args.params ",[36,2029,1379],{"class":42},[36,2031,2032],{"class":88}," unknown",[36,2034,2035],{"class":46},"[]) };\n",[36,2037,2038],{"class":38,"line":183},[36,2039,180],{"class":46},[25,2041,2044],{"className":27,"code":2042,"filename":2043,"language":30,"meta":31,"style":31},"import { Handoff, Tools } from \"@nolag/agents\";\n\nconst handoff = new Handoff(room);\nconst tools = new Tools(room, agents.agentId);\n\nhandoff.onTask([\"answer\"], async (task, respond) => {\n  const search = await tools.invoke(\"web-search\", { query: task.payload.question });\n  const metrics = await tools.invoke(\"database-query\", {\n    sql: \"SELECT * FROM metrics WHERE topic = $1\",\n    params: [task.payload.topic],\n  });\n\n  if (search.status === \"error\" || metrics.status === \"error\") {\n    respond(\"error\", {}, { code: \"tool_failed\", message: search.error?.message ?? metrics.error?.message ?? \"\" });\n    return;\n  }\n\n  const answer = await llm.complete({\n    prompt: task.payload.question,\n    context: { search: search.result, metrics: metrics.result },\n  });\n\n  respond(\"success\", { answer });\n});\n","Worker",[33,2045,2046,2059,2063,2077,2091,2095,2129,2153,2174,2184,2189,2193,2197,2220,2250,2257,2261,2265,2284,2289,2294,2298,2302,2315],{"__ignoreMap":31},[36,2047,2048,2050,2053,2055,2057],{"class":38,"line":39},[36,2049,43],{"class":42},[36,2051,2052],{"class":46}," { Handoff, Tools } ",[36,2054,50],{"class":42},[36,2056,70],{"class":53},[36,2058,57],{"class":46},[36,2060,2061],{"class":38,"line":60},[36,2062,79],{"emptyLinePlaceholder":78},[36,2064,2065,2067,2069,2071,2073,2075],{"class":38,"line":75},[36,2066,85],{"class":42},[36,2068,472],{"class":88},[36,2070,92],{"class":42},[36,2072,118],{"class":42},[36,2074,479],{"class":95},[36,2076,724],{"class":46},[36,2078,2079,2081,2083,2085,2087,2089],{"class":38,"line":82},[36,2080,85],{"class":42},[36,2082,1905],{"class":88},[36,2084,92],{"class":42},[36,2086,118],{"class":42},[36,2088,1912],{"class":95},[36,2090,741],{"class":46},[36,2092,2093],{"class":38,"line":108},[36,2094,79],{"emptyLinePlaceholder":78},[36,2096,2097,2100,2103,2106,2109,2112,2114,2116,2119,2121,2123,2125,2127],{"class":38,"line":127},[36,2098,2099],{"class":46},"handoff.",[36,2101,2102],{"class":95},"onTask",[36,2104,2105],{"class":46},"([",[36,2107,2108],{"class":53},"\"answer\"",[36,2110,2111],{"class":46},"], ",[36,2113,521],{"class":42},[36,2115,524],{"class":46},[36,2117,2118],{"class":527},"task",[36,2120,142],{"class":46},[36,2122,1794],{"class":527},[36,2124,531],{"class":46},[36,2126,534],{"class":42},[36,2128,537],{"class":46},[36,2130,2131,2133,2136,2138,2140,2143,2146,2148,2150],{"class":38,"line":133},[36,2132,543],{"class":42},[36,2134,2135],{"class":88}," search",[36,2137,92],{"class":42},[36,2139,551],{"class":42},[36,2141,2142],{"class":46}," tools.",[36,2144,2145],{"class":95},"invoke",[36,2147,99],{"class":46},[36,2149,1931],{"class":53},[36,2151,2152],{"class":46},", { query: task.payload.question });\n",[36,2154,2155,2157,2160,2162,2164,2166,2168,2170,2172],{"class":38,"line":149},[36,2156,543],{"class":42},[36,2158,2159],{"class":88}," metrics",[36,2161,92],{"class":42},[36,2163,551],{"class":42},[36,2165,2142],{"class":46},[36,2167,2145],{"class":95},[36,2169,99],{"class":46},[36,2171,1988],{"class":53},[36,2173,1183],{"class":46},[36,2175,2176,2179,2182],{"class":38,"line":161},[36,2177,2178],{"class":46},"    sql: ",[36,2180,2181],{"class":53},"\"SELECT * FROM metrics WHERE topic = $1\"",[36,2183,158],{"class":46},[36,2185,2186],{"class":38,"line":177},[36,2187,2188],{"class":46},"    params: [task.payload.topic],\n",[36,2190,2191],{"class":38,"line":183},[36,2192,1214],{"class":46},[36,2194,2195],{"class":38,"line":198},[36,2196,79],{"emptyLinePlaceholder":78},[36,2198,2199,2201,2204,2206,2208,2211,2214,2216,2218],{"class":38,"line":211},[36,2200,625],{"class":42},[36,2202,2203],{"class":46}," (search.status ",[36,2205,637],{"class":42},[36,2207,983],{"class":53},[36,2209,2210],{"class":42}," ||",[36,2212,2213],{"class":46}," metrics.status ",[36,2215,637],{"class":42},[36,2217,983],{"class":53},[36,2219,643],{"class":46},[36,2221,2222,2224,2226,2228,2231,2234,2237,2240,2243,2245,2248],{"class":38,"line":216},[36,2223,1837],{"class":95},[36,2225,99],{"class":46},[36,2227,1725],{"class":53},[36,2229,2230],{"class":46},", {}, { code: ",[36,2232,2233],{"class":53},"\"tool_failed\"",[36,2235,2236],{"class":46},", message: search.error?.message ",[36,2238,2239],{"class":42},"??",[36,2241,2242],{"class":46}," metrics.error?.message ",[36,2244,2239],{"class":42},[36,2246,2247],{"class":53}," \"\"",[36,2249,348],{"class":46},[36,2251,2252,2255],{"class":38,"line":439},[36,2253,2254],{"class":42},"    return",[36,2256,57],{"class":46},[36,2258,2259],{"class":38,"line":444},[36,2260,666],{"class":46},[36,2262,2263],{"class":38,"line":467},[36,2264,79],{"emptyLinePlaceholder":78},[36,2266,2267,2269,2272,2274,2276,2279,2282],{"class":38,"line":494},[36,2268,543],{"class":42},[36,2270,2271],{"class":88}," answer",[36,2273,92],{"class":42},[36,2275,551],{"class":42},[36,2277,2278],{"class":46}," llm.",[36,2280,2281],{"class":95},"complete",[36,2283,124],{"class":46},[36,2285,2286],{"class":38,"line":499},[36,2287,2288],{"class":46},"    prompt: task.payload.question,\n",[36,2290,2291],{"class":38,"line":505},[36,2292,2293],{"class":46},"    context: { search: search.result, metrics: metrics.result },\n",[36,2295,2296],{"class":38,"line":540},[36,2297,1214],{"class":46},[36,2299,2300],{"class":38,"line":563},[36,2301,79],{"emptyLinePlaceholder":78},[36,2303,2304,2307,2309,2312],{"class":38,"line":571},[36,2305,2306],{"class":95},"  respond",[36,2308,99],{"class":46},[36,2310,2311],{"class":53},"\"success\"",[36,2313,2314],{"class":46},", { answer });\n",[36,2316,2317],{"class":38,"line":599},[36,2318,180],{"class":46},[15,2320,2321,2323],{},[675,2322,677],{}," Tools (remote invocation), Handoff (task dispatch)",[237,2325,2327],{"id":2326},"monitoring-dashboard","Monitoring Dashboard",[15,2329,2330],{},"A monitoring agent that counts tasks, collects the Observe event stream, and alerts operations when a worker reports a failure or an agent leaves the room. Handoff emits no events of its own, so the worker emits the timing events the monitor aggregates.",[22,2332,2333,2553],{},[25,2334,2336],{"className":27,"code":2335,"filename":2043,"language":30,"meta":31,"style":31},"import { Handoff, Observe } from \"@nolag/agents\";\n\nconst handoff = new Handoff(room);\nconst observe = new Observe(room, agents.agentId);\n\nhandoff.onTask([\"summarize\"], async (task, respond) => {\n  const started = Date.now();\n  try {\n    const summary = await summarize(task.payload);\n    respond(\"success\", { summary });\n    observe.emit(\"task:completed\", { taskId: task.taskId, duration: Date.now() - started });\n  } catch (err) {\n    respond(\"error\", {}, { code: \"summarize_failed\", message: String(err) });\n    observe.emit(\"task:failed\", { taskId: task.taskId, message: String(err) }, \"error\");\n  }\n});\n",[33,2337,2338,2351,2355,2369,2383,2387,2416,2433,2440,2458,2469,2494,2502,2523,2545,2549],{"__ignoreMap":31},[36,2339,2340,2342,2345,2347,2349],{"class":38,"line":39},[36,2341,43],{"class":42},[36,2343,2344],{"class":46}," { Handoff, Observe } ",[36,2346,50],{"class":42},[36,2348,70],{"class":53},[36,2350,57],{"class":46},[36,2352,2353],{"class":38,"line":60},[36,2354,79],{"emptyLinePlaceholder":78},[36,2356,2357,2359,2361,2363,2365,2367],{"class":38,"line":75},[36,2358,85],{"class":42},[36,2360,472],{"class":88},[36,2362,92],{"class":42},[36,2364,118],{"class":42},[36,2366,479],{"class":95},[36,2368,724],{"class":46},[36,2370,2371,2373,2375,2377,2379,2381],{"class":38,"line":82},[36,2372,85],{"class":42},[36,2374,1506],{"class":88},[36,2376,92],{"class":42},[36,2378,118],{"class":42},[36,2380,1513],{"class":95},[36,2382,741],{"class":46},[36,2384,2385],{"class":38,"line":108},[36,2386,79],{"emptyLinePlaceholder":78},[36,2388,2389,2391,2393,2395,2398,2400,2402,2404,2406,2408,2410,2412,2414],{"class":38,"line":127},[36,2390,2099],{"class":46},[36,2392,2102],{"class":95},[36,2394,2105],{"class":46},[36,2396,2397],{"class":53},"\"summarize\"",[36,2399,2111],{"class":46},[36,2401,521],{"class":42},[36,2403,524],{"class":46},[36,2405,2118],{"class":527},[36,2407,142],{"class":46},[36,2409,1794],{"class":527},[36,2411,531],{"class":46},[36,2413,534],{"class":42},[36,2415,537],{"class":46},[36,2417,2418,2420,2423,2425,2428,2431],{"class":38,"line":133},[36,2419,543],{"class":42},[36,2421,2422],{"class":88}," started",[36,2424,92],{"class":42},[36,2426,2427],{"class":46}," Date.",[36,2429,2430],{"class":95},"now",[36,2432,195],{"class":46},[36,2434,2435,2438],{"class":38,"line":149},[36,2436,2437],{"class":42},"  try",[36,2439,537],{"class":46},[36,2441,2442,2445,2448,2450,2452,2455],{"class":38,"line":161},[36,2443,2444],{"class":42},"    const",[36,2446,2447],{"class":88}," summary",[36,2449,92],{"class":42},[36,2451,551],{"class":42},[36,2453,2454],{"class":95}," summarize",[36,2456,2457],{"class":46},"(task.payload);\n",[36,2459,2460,2462,2464,2466],{"class":38,"line":177},[36,2461,1837],{"class":95},[36,2463,99],{"class":46},[36,2465,2311],{"class":53},[36,2467,2468],{"class":46},", { summary });\n",[36,2470,2471,2473,2475,2477,2480,2483,2485,2488,2491],{"class":38,"line":183},[36,2472,1647],{"class":46},[36,2474,1650],{"class":95},[36,2476,99],{"class":46},[36,2478,2479],{"class":53},"\"task:completed\"",[36,2481,2482],{"class":46},", { taskId: task.taskId, duration: Date.",[36,2484,2430],{"class":95},[36,2486,2487],{"class":46},"() ",[36,2489,2490],{"class":42},"-",[36,2492,2493],{"class":46}," started });\n",[36,2495,2496,2498,2500],{"class":38,"line":198},[36,2497,1663],{"class":46},[36,2499,1699],{"class":42},[36,2501,1702],{"class":46},[36,2503,2504,2506,2508,2510,2512,2515,2518,2520],{"class":38,"line":211},[36,2505,1837],{"class":95},[36,2507,99],{"class":46},[36,2509,1725],{"class":53},[36,2511,2230],{"class":46},[36,2513,2514],{"class":53},"\"summarize_failed\"",[36,2516,2517],{"class":46},", message: ",[36,2519,657],{"class":95},[36,2521,2522],{"class":46},"(err) });\n",[36,2524,2525,2527,2529,2531,2534,2537,2539,2541,2543],{"class":38,"line":216},[36,2526,1647],{"class":46},[36,2528,1650],{"class":95},[36,2530,99],{"class":46},[36,2532,2533],{"class":53},"\"task:failed\"",[36,2535,2536],{"class":46},", { taskId: task.taskId, message: ",[36,2538,657],{"class":95},[36,2540,1722],{"class":46},[36,2542,1725],{"class":53},[36,2544,105],{"class":46},[36,2546,2547],{"class":38,"line":439},[36,2548,666],{"class":46},[36,2550,2551],{"class":38,"line":444},[36,2552,180],{"class":46},[25,2554,2557],{"className":27,"code":2555,"filename":2556,"language":30,"meta":31,"style":31},"import { Observe } from \"@nolag/agents\";\n\nconst observe = new Observe(room, agents.agentId);\nconst metrics = { tasks: 0, completed: 0, failed: 0, avgDuration: 0 };\nconst durations: number[] = [];\n\n// Every task envelope on the room reaches the monitor\nroom.on(\"task\", () => metrics.tasks++);\n\nobserve.on((event) => {\n  metrics.completed++;\n  durations.push(Number(event.payload.duration));\n  metrics.avgDuration = durations.reduce((a, b) => a + b, 0) / durations.length;\n}, { category: \"task:completed\" });\n\nobserve.on((event) => {\n  metrics.failed++;\n  alertOps(\"Task failed\", event.payload);\n}, { category: \"task:failed\" });\n\n// Agent health from room presence\nroom.on(\"presenceJoin\", (actorId, presence) => {\n  console.log(\"Agent online:\", presence.name, presence.capabilities);\n});\nroom.on(\"presenceLeave\", (actorId) => {\n  alertOps(\"Agent disconnected\", { actorId, remaining: room.getConnectedAgents().length });\n});\n","Monitor",[33,2558,2559,2572,2576,2590,2620,2640,2644,2649,2673,2677,2695,2704,2720,2768,2777,2781,2797,2806,2819,2827,2831,2836,2863,2879,2883,2904,2925],{"__ignoreMap":31},[36,2560,2561,2563,2566,2568,2570],{"class":38,"line":39},[36,2562,43],{"class":42},[36,2564,2565],{"class":46}," { Observe } ",[36,2567,50],{"class":42},[36,2569,70],{"class":53},[36,2571,57],{"class":46},[36,2573,2574],{"class":38,"line":60},[36,2575,79],{"emptyLinePlaceholder":78},[36,2577,2578,2580,2582,2584,2586,2588],{"class":38,"line":75},[36,2579,85],{"class":42},[36,2581,1506],{"class":88},[36,2583,92],{"class":42},[36,2585,118],{"class":42},[36,2587,1513],{"class":95},[36,2589,741],{"class":46},[36,2591,2592,2594,2596,2598,2601,2603,2606,2608,2611,2613,2616,2618],{"class":38,"line":82},[36,2593,85],{"class":42},[36,2595,2159],{"class":88},[36,2597,92],{"class":42},[36,2599,2600],{"class":46}," { tasks: ",[36,2602,830],{"class":88},[36,2604,2605],{"class":46},", completed: ",[36,2607,830],{"class":88},[36,2609,2610],{"class":46},", failed: ",[36,2612,830],{"class":88},[36,2614,2615],{"class":46},", avgDuration: ",[36,2617,830],{"class":88},[36,2619,870],{"class":46},[36,2621,2622,2624,2627,2629,2632,2635,2637],{"class":38,"line":108},[36,2623,85],{"class":42},[36,2625,2626],{"class":88}," durations",[36,2628,788],{"class":42},[36,2630,2631],{"class":88}," number",[36,2633,2634],{"class":46},"[] ",[36,2636,808],{"class":42},[36,2638,2639],{"class":46}," [];\n",[36,2641,2642],{"class":38,"line":127},[36,2643,79],{"emptyLinePlaceholder":78},[36,2645,2646],{"class":38,"line":133},[36,2647,2648],{"class":145},"// Every task envelope on the room reaches the monitor\n",[36,2650,2651,2654,2656,2658,2661,2664,2666,2669,2671],{"class":38,"line":149},[36,2652,2653],{"class":46},"room.",[36,2655,511],{"class":95},[36,2657,99],{"class":46},[36,2659,2660],{"class":53},"\"task\"",[36,2662,2663],{"class":46},", () ",[36,2665,534],{"class":42},[36,2667,2668],{"class":46}," metrics.tasks",[36,2670,908],{"class":42},[36,2672,105],{"class":46},[36,2674,2675],{"class":38,"line":161},[36,2676,79],{"emptyLinePlaceholder":78},[36,2678,2679,2682,2684,2686,2689,2691,2693],{"class":38,"line":177},[36,2680,2681],{"class":46},"observe.",[36,2683,511],{"class":95},[36,2685,586],{"class":46},[36,2687,2688],{"class":527},"event",[36,2690,531],{"class":46},[36,2692,534],{"class":42},[36,2694,537],{"class":46},[36,2696,2697,2700,2702],{"class":38,"line":183},[36,2698,2699],{"class":46},"  metrics.completed",[36,2701,908],{"class":42},[36,2703,57],{"class":46},[36,2705,2706,2709,2712,2714,2717],{"class":38,"line":198},[36,2707,2708],{"class":46},"  durations.",[36,2710,2711],{"class":95},"push",[36,2713,99],{"class":46},[36,2715,2716],{"class":95},"Number",[36,2718,2719],{"class":46},"(event.payload.duration));\n",[36,2721,2722,2725,2727,2730,2733,2735,2738,2740,2743,2745,2747,2750,2752,2755,2757,2759,2762,2764,2766],{"class":38,"line":211},[36,2723,2724],{"class":46},"  metrics.avgDuration ",[36,2726,808],{"class":42},[36,2728,2729],{"class":46}," durations.",[36,2731,2732],{"class":95},"reduce",[36,2734,586],{"class":46},[36,2736,2737],{"class":527},"a",[36,2739,142],{"class":46},[36,2741,2742],{"class":527},"b",[36,2744,531],{"class":46},[36,2746,534],{"class":42},[36,2748,2749],{"class":46}," a ",[36,2751,1054],{"class":42},[36,2753,2754],{"class":46}," b, ",[36,2756,830],{"class":88},[36,2758,531],{"class":46},[36,2760,2761],{"class":42},"/",[36,2763,2729],{"class":46},[36,2765,902],{"class":88},[36,2767,57],{"class":46},[36,2769,2770,2773,2775],{"class":38,"line":216},[36,2771,2772],{"class":46},"}, { category: ",[36,2774,2479],{"class":53},[36,2776,348],{"class":46},[36,2778,2779],{"class":38,"line":439},[36,2780,79],{"emptyLinePlaceholder":78},[36,2782,2783,2785,2787,2789,2791,2793,2795],{"class":38,"line":444},[36,2784,2681],{"class":46},[36,2786,511],{"class":95},[36,2788,586],{"class":46},[36,2790,2688],{"class":527},[36,2792,531],{"class":46},[36,2794,534],{"class":42},[36,2796,537],{"class":46},[36,2798,2799,2802,2804],{"class":38,"line":467},[36,2800,2801],{"class":46},"  metrics.failed",[36,2803,908],{"class":42},[36,2805,57],{"class":46},[36,2807,2808,2811,2813,2816],{"class":38,"line":494},[36,2809,2810],{"class":95},"  alertOps",[36,2812,99],{"class":46},[36,2814,2815],{"class":53},"\"Task failed\"",[36,2817,2818],{"class":46},", event.payload);\n",[36,2820,2821,2823,2825],{"class":38,"line":499},[36,2822,2772],{"class":46},[36,2824,2533],{"class":53},[36,2826,348],{"class":46},[36,2828,2829],{"class":38,"line":505},[36,2830,79],{"emptyLinePlaceholder":78},[36,2832,2833],{"class":38,"line":540},[36,2834,2835],{"class":145},"// Agent health from room presence\n",[36,2837,2838,2840,2842,2844,2847,2849,2852,2854,2857,2859,2861],{"class":38,"line":563},[36,2839,2653],{"class":46},[36,2841,511],{"class":95},[36,2843,99],{"class":46},[36,2845,2846],{"class":53},"\"presenceJoin\"",[36,2848,1155],{"class":46},[36,2850,2851],{"class":527},"actorId",[36,2853,142],{"class":46},[36,2855,2856],{"class":527},"presence",[36,2858,531],{"class":46},[36,2860,534],{"class":42},[36,2862,537],{"class":46},[36,2864,2865,2868,2871,2873,2876],{"class":38,"line":571},[36,2866,2867],{"class":46},"  console.",[36,2869,2870],{"class":95},"log",[36,2872,99],{"class":46},[36,2874,2875],{"class":53},"\"Agent online:\"",[36,2877,2878],{"class":46},", presence.name, presence.capabilities);\n",[36,2880,2881],{"class":38,"line":599},[36,2882,180],{"class":46},[36,2884,2885,2887,2889,2891,2894,2896,2898,2900,2902],{"class":38,"line":616},[36,2886,2653],{"class":46},[36,2888,511],{"class":95},[36,2890,99],{"class":46},[36,2892,2893],{"class":53},"\"presenceLeave\"",[36,2895,1155],{"class":46},[36,2897,2851],{"class":527},[36,2899,531],{"class":46},[36,2901,534],{"class":42},[36,2903,537],{"class":46},[36,2905,2906,2908,2910,2913,2916,2919,2921,2923],{"class":38,"line":622},[36,2907,2810],{"class":95},[36,2909,99],{"class":46},[36,2911,2912],{"class":53},"\"Agent disconnected\"",[36,2914,2915],{"class":46},", { actorId, remaining: room.",[36,2917,2918],{"class":95},"getConnectedAgents",[36,2920,580],{"class":46},[36,2922,902],{"class":88},[36,2924,348],{"class":46},[36,2926,2927],{"class":38,"line":646},[36,2928,180],{"class":46},[15,2930,2931,2933],{},[675,2932,677],{}," Observe (event stream), Presence (agent health)",[2935,2936,2937],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}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 .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":31,"searchDepth":60,"depth":60,"links":2939},[2940,2941,2942,2943,2944,2945],{"id":239,"depth":60,"text":240},{"id":681,"depth":60,"text":682},{"id":1085,"depth":60,"text":1086},{"id":1454,"depth":60,"text":1455},{"id":1869,"depth":60,"text":1870},{"id":2326,"depth":60,"text":2327},"Canonical recipes for common agent workflows: agentic chatbot, autonomous workflow, copilot, compliance, tool-augmented agent, and monitoring.","md",{},"/docs/agents/examples",{"title":5,"description":2946},"docs/agents/examples","FtOwBv_odwr2rIIejqaSrqof8fNeZycO_wITC2-iXeg",1789869418303]