[{"data":1,"prerenderedAt":727},["ShallowReactive",2],{"layout-chapters":3,"sidebar-chapters":34,"chapter-appendix":65,"all-chapters":710},[4,6,8,10,12,14,16,18,20,22,24,26,28,30,32],{"slug":5},"intro",{"slug":7},"brief-history",{"slug":9},"factor-1",{"slug":11},"factor-2",{"slug":13},"factor-3",{"slug":15},"factor-4",{"slug":17},"factor-5",{"slug":19},"factor-6",{"slug":21},"factor-7",{"slug":23},"factor-8",{"slug":25},"factor-9",{"slug":27},"factor-10",{"slug":29},"factor-11",{"slug":31},"factor-12",{"slug":33},"appendix",[35,37,39,41,43,45,47,49,51,53,55,57,59,61,63],{"slug":5,"title":36},"Introduction",{"slug":7,"title":38},"A Brief History of Software",{"slug":9,"title":40},"Factor 1: Natural Language to Tool Calls",{"slug":11,"title":42},"Factor 2: Own Your Prompts",{"slug":13,"title":44},"Factor 3: Own Your Context Window",{"slug":15,"title":46},"Factor 4: Tools Are Structured Outputs",{"slug":17,"title":48},"Factor 5: Unify Execution State",{"slug":19,"title":50},"Factor 6: Launch\u002FPause\u002FResume",{"slug":21,"title":52},"Factor 7: Contact Humans with Tools",{"slug":23,"title":54},"Factor 8: Own Your Control Flow",{"slug":25,"title":56},"Factor 9: Compact Errors into Context",{"slug":27,"title":58},"Factor 10: Small, Focused Agents",{"slug":29,"title":60},"Factor 11: Trigger from Anywhere",{"slug":31,"title":62},"Factor 12: Stateless Reducer",{"slug":33,"title":64},"Appendix: Pre-Fetch Context",{"id":66,"title":64,"body":67,"chapterIndex":168,"description":85,"extension":705,"meta":706,"navigation":108,"path":707,"seo":708,"slug":33,"stem":33,"__hash__":709},"chapters\u002Fappendix.md",{"type":68,"value":69,"toc":702},"minimark",[70,75,79,207,210,320,323,440,442,552,555,676,679,687,698],[71,72,74],"h3",{"id":73},"factor-13-pre-fetch-all-the-context-you-might-need","Factor 13 - pre-fetch all the context you might need",[76,77,78],"p",{},"If there's a high chance that your model will call tool X, don't waste token round trips telling the model to fetch it, that is, instead of a pseudo-prompt like:",[80,81,86],"pre",{"className":82,"code":83,"language":84,"meta":85,"style":85},"language-jinja shiki shiki-themes github-light github-dark","When looking at deployments, you will likely want to fetch the list of published git tags,\nso you can use it to deploy to prod.\n\nHere's what happened so far:\n\n{{ thread.events }}\n\nWhat's the next step?\n\nAnswer in JSON format with one of the following intents:\n\n{\n  intent: 'deploy_backend_to_prod',\n  tag: string\n} OR {\n  intent: 'list_git_tags'\n} OR {\n  intent: 'done_for_now',\n  message: string\n}\n","jinja","",[87,88,89,97,103,110,116,121,127,132,138,143,149,154,160,166,172,178,184,189,195,201],"code",{"__ignoreMap":85},[90,91,94],"span",{"class":92,"line":93},"line",1,[90,95,96],{},"When looking at deployments, you will likely want to fetch the list of published git tags,\n",[90,98,100],{"class":92,"line":99},2,[90,101,102],{},"so you can use it to deploy to prod.\n",[90,104,106],{"class":92,"line":105},3,[90,107,109],{"emptyLinePlaceholder":108},true,"\n",[90,111,113],{"class":92,"line":112},4,[90,114,115],{},"Here's what happened so far:\n",[90,117,119],{"class":92,"line":118},5,[90,120,109],{"emptyLinePlaceholder":108},[90,122,124],{"class":92,"line":123},6,[90,125,126],{},"{{ thread.events }}\n",[90,128,130],{"class":92,"line":129},7,[90,131,109],{"emptyLinePlaceholder":108},[90,133,135],{"class":92,"line":134},8,[90,136,137],{},"What's the next step?\n",[90,139,141],{"class":92,"line":140},9,[90,142,109],{"emptyLinePlaceholder":108},[90,144,146],{"class":92,"line":145},10,[90,147,148],{},"Answer in JSON format with one of the following intents:\n",[90,150,152],{"class":92,"line":151},11,[90,153,109],{"emptyLinePlaceholder":108},[90,155,157],{"class":92,"line":156},12,[90,158,159],{},"{\n",[90,161,163],{"class":92,"line":162},13,[90,164,165],{},"  intent: 'deploy_backend_to_prod',\n",[90,167,169],{"class":92,"line":168},14,[90,170,171],{},"  tag: string\n",[90,173,175],{"class":92,"line":174},15,[90,176,177],{},"} OR {\n",[90,179,181],{"class":92,"line":180},16,[90,182,183],{},"  intent: 'list_git_tags'\n",[90,185,187],{"class":92,"line":186},17,[90,188,177],{},[90,190,192],{"class":92,"line":191},18,[90,193,194],{},"  intent: 'done_for_now',\n",[90,196,198],{"class":92,"line":197},19,[90,199,200],{},"  message: string\n",[90,202,204],{"class":92,"line":203},20,[90,205,206],{},"}\n",[76,208,209],{},"and your code looks like",[80,211,215],{"className":212,"code":213,"language":214,"meta":85,"style":85},"language-python shiki shiki-themes github-light github-dark","thread = {\"events\": [initial_message]}\nnext_step = await determine_next_step(thread)\n\nwhile True:\n  switch next_step.intent:\n    case 'list_git_tags':\n      tags = await fetch_git_tags()\n      thread[\"events\"].append({\n        type: 'list_git_tags',\n        data: tags,\n      })\n    case 'deploy_backend_to_prod':\n      deploy_result = await deploy_backend_to_prod(next_step.data.tag)\n      thread[\"events\"].append({\n        \"type\": 'deploy_backend_to_prod',\n        \"data\": deploy_result,\n      })\n    case 'done_for_now':\n      await notify_human(next_step.message)\n      break\n    # ...\n","python",[87,216,217,222,227,231,236,241,246,251,256,261,266,271,276,281,285,290,295,299,304,309,314],{"__ignoreMap":85},[90,218,219],{"class":92,"line":93},[90,220,221],{},"thread = {\"events\": [initial_message]}\n",[90,223,224],{"class":92,"line":99},[90,225,226],{},"next_step = await determine_next_step(thread)\n",[90,228,229],{"class":92,"line":105},[90,230,109],{"emptyLinePlaceholder":108},[90,232,233],{"class":92,"line":112},[90,234,235],{},"while True:\n",[90,237,238],{"class":92,"line":118},[90,239,240],{},"  switch next_step.intent:\n",[90,242,243],{"class":92,"line":123},[90,244,245],{},"    case 'list_git_tags':\n",[90,247,248],{"class":92,"line":129},[90,249,250],{},"      tags = await fetch_git_tags()\n",[90,252,253],{"class":92,"line":134},[90,254,255],{},"      thread[\"events\"].append({\n",[90,257,258],{"class":92,"line":140},[90,259,260],{},"        type: 'list_git_tags',\n",[90,262,263],{"class":92,"line":145},[90,264,265],{},"        data: tags,\n",[90,267,268],{"class":92,"line":151},[90,269,270],{},"      })\n",[90,272,273],{"class":92,"line":156},[90,274,275],{},"    case 'deploy_backend_to_prod':\n",[90,277,278],{"class":92,"line":162},[90,279,280],{},"      deploy_result = await deploy_backend_to_prod(next_step.data.tag)\n",[90,282,283],{"class":92,"line":168},[90,284,255],{},[90,286,287],{"class":92,"line":174},[90,288,289],{},"        \"type\": 'deploy_backend_to_prod',\n",[90,291,292],{"class":92,"line":180},[90,293,294],{},"        \"data\": deploy_result,\n",[90,296,297],{"class":92,"line":186},[90,298,270],{},[90,300,301],{"class":92,"line":191},[90,302,303],{},"    case 'done_for_now':\n",[90,305,306],{"class":92,"line":197},[90,307,308],{},"      await notify_human(next_step.message)\n",[90,310,311],{"class":92,"line":203},[90,312,313],{},"      break\n",[90,315,317],{"class":92,"line":316},21,[90,318,319],{},"    # ...\n",[76,321,322],{},"You might as well just fetch the tags and include them in the context window, like:",[80,324,328],{"className":325,"code":326,"language":327,"meta":85,"style":85},"language-diff shiki shiki-themes github-light github-dark","- When looking at deployments, you will likely want to fetch the list of published git tags,\n- so you can use it to deploy to prod.\n\n+ The current git tags are:\n\n+ {{ git_tags }}\n\n\nHere's what happened so far:\n\n{{ thread.events }}\n\nWhat's the next step?\n\nAnswer in JSON format with one of the following intents:\n\n{\n  intent: 'deploy_backend_to_prod',\n  tag: string\n- } OR {\n-   intent: 'list_git_tags'\n} OR {\n  intent: 'done_for_now',\n  message: string\n}\n\n","diff",[87,329,330,335,340,344,349,353,358,362,366,370,374,378,382,386,390,394,398,402,406,410,415,420,425,430,435],{"__ignoreMap":85},[90,331,332],{"class":92,"line":93},[90,333,334],{},"- When looking at deployments, you will likely want to fetch the list of published git tags,\n",[90,336,337],{"class":92,"line":99},[90,338,339],{},"- so you can use it to deploy to prod.\n",[90,341,342],{"class":92,"line":105},[90,343,109],{"emptyLinePlaceholder":108},[90,345,346],{"class":92,"line":112},[90,347,348],{},"+ The current git tags are:\n",[90,350,351],{"class":92,"line":118},[90,352,109],{"emptyLinePlaceholder":108},[90,354,355],{"class":92,"line":123},[90,356,357],{},"+ {{ git_tags }}\n",[90,359,360],{"class":92,"line":129},[90,361,109],{"emptyLinePlaceholder":108},[90,363,364],{"class":92,"line":134},[90,365,109],{"emptyLinePlaceholder":108},[90,367,368],{"class":92,"line":140},[90,369,115],{},[90,371,372],{"class":92,"line":145},[90,373,109],{"emptyLinePlaceholder":108},[90,375,376],{"class":92,"line":151},[90,377,126],{},[90,379,380],{"class":92,"line":156},[90,381,109],{"emptyLinePlaceholder":108},[90,383,384],{"class":92,"line":162},[90,385,137],{},[90,387,388],{"class":92,"line":168},[90,389,109],{"emptyLinePlaceholder":108},[90,391,392],{"class":92,"line":174},[90,393,148],{},[90,395,396],{"class":92,"line":180},[90,397,109],{"emptyLinePlaceholder":108},[90,399,400],{"class":92,"line":186},[90,401,159],{},[90,403,404],{"class":92,"line":191},[90,405,165],{},[90,407,408],{"class":92,"line":197},[90,409,171],{},[90,411,412],{"class":92,"line":203},[90,413,414],{},"- } OR {\n",[90,416,417],{"class":92,"line":316},[90,418,419],{},"-   intent: 'list_git_tags'\n",[90,421,423],{"class":92,"line":422},22,[90,424,177],{},[90,426,428],{"class":92,"line":427},23,[90,429,194],{},[90,431,433],{"class":92,"line":432},24,[90,434,200],{},[90,436,438],{"class":92,"line":437},25,[90,439,206],{},[76,441,209],{},[80,443,445],{"className":325,"code":444,"language":327,"meta":85,"style":85},"thread = {\"events\": [initial_message]}\n+ git_tags = await fetch_git_tags()\n\n- next_step = await determine_next_step(thread)\n+ next_step = await determine_next_step(thread, git_tags)\n\nwhile True:\n  switch next_step.intent:\n-    case 'list_git_tags':\n-      tags = await fetch_git_tags()\n-      thread[\"events\"].append({\n-        type: 'list_git_tags',\n-        data: tags,\n-      })\n    case 'deploy_backend_to_prod':\n      deploy_result = await deploy_backend_to_prod(next_step.data.tag)\n      thread[\"events\"].append({\n        \"type\": 'deploy_backend_to_prod',\n        \"data\": deploy_result,\n      })\n    case 'done_for_now':\n      await notify_human(next_step.message)\n      break\n    # ...\n",[87,446,447,451,456,460,465,470,474,478,482,487,492,497,502,507,512,516,520,524,528,532,536,540,544,548],{"__ignoreMap":85},[90,448,449],{"class":92,"line":93},[90,450,221],{},[90,452,453],{"class":92,"line":99},[90,454,455],{},"+ git_tags = await fetch_git_tags()\n",[90,457,458],{"class":92,"line":105},[90,459,109],{"emptyLinePlaceholder":108},[90,461,462],{"class":92,"line":112},[90,463,464],{},"- next_step = await determine_next_step(thread)\n",[90,466,467],{"class":92,"line":118},[90,468,469],{},"+ next_step = await determine_next_step(thread, git_tags)\n",[90,471,472],{"class":92,"line":123},[90,473,109],{"emptyLinePlaceholder":108},[90,475,476],{"class":92,"line":129},[90,477,235],{},[90,479,480],{"class":92,"line":134},[90,481,240],{},[90,483,484],{"class":92,"line":140},[90,485,486],{},"-    case 'list_git_tags':\n",[90,488,489],{"class":92,"line":145},[90,490,491],{},"-      tags = await fetch_git_tags()\n",[90,493,494],{"class":92,"line":151},[90,495,496],{},"-      thread[\"events\"].append({\n",[90,498,499],{"class":92,"line":156},[90,500,501],{},"-        type: 'list_git_tags',\n",[90,503,504],{"class":92,"line":162},[90,505,506],{},"-        data: tags,\n",[90,508,509],{"class":92,"line":168},[90,510,511],{},"-      })\n",[90,513,514],{"class":92,"line":174},[90,515,275],{},[90,517,518],{"class":92,"line":180},[90,519,280],{},[90,521,522],{"class":92,"line":186},[90,523,255],{},[90,525,526],{"class":92,"line":191},[90,527,289],{},[90,529,530],{"class":92,"line":197},[90,531,294],{},[90,533,534],{"class":92,"line":203},[90,535,270],{},[90,537,538],{"class":92,"line":316},[90,539,303],{},[90,541,542],{"class":92,"line":422},[90,543,308],{},[90,545,546],{"class":92,"line":427},[90,547,313],{},[90,549,550],{"class":92,"line":432},[90,551,319],{},[76,553,554],{},"or even just include the tags in the thread and remove the specific parameter from your prompt template:",[80,556,558],{"className":325,"code":557,"language":327,"meta":85,"style":85},"thread = {\"events\": [initial_message]}\n+ # add the request\n+ thread[\"events\"].append({\n+  \"type\": 'list_git_tags',\n+ })\n\ngit_tags = await fetch_git_tags()\n\n+ # add the result\n+ thread[\"events\"].append({\n+  \"type\": 'list_git_tags_result',\n+  \"data\": git_tags,\n+ })\n\n- next_step = await determine_next_step(thread, git_tags)\n+ next_step = await determine_next_step(thread)\n\nwhile True:\n  switch next_step.intent:\n    case 'deploy_backend_to_prod':\n      deploy_result = await deploy_backend_to_prod(next_step.data.tag)\n      thread[\"events\"].append(deploy_result)\n    case 'done_for_now':\n      await notify_human(next_step.message)\n      break\n    # ...\n",[87,559,560,564,569,574,579,584,588,593,597,602,606,611,616,620,624,629,634,638,642,646,650,654,659,663,667,671],{"__ignoreMap":85},[90,561,562],{"class":92,"line":93},[90,563,221],{},[90,565,566],{"class":92,"line":99},[90,567,568],{},"+ # add the request\n",[90,570,571],{"class":92,"line":105},[90,572,573],{},"+ thread[\"events\"].append({\n",[90,575,576],{"class":92,"line":112},[90,577,578],{},"+  \"type\": 'list_git_tags',\n",[90,580,581],{"class":92,"line":118},[90,582,583],{},"+ })\n",[90,585,586],{"class":92,"line":123},[90,587,109],{"emptyLinePlaceholder":108},[90,589,590],{"class":92,"line":129},[90,591,592],{},"git_tags = await fetch_git_tags()\n",[90,594,595],{"class":92,"line":134},[90,596,109],{"emptyLinePlaceholder":108},[90,598,599],{"class":92,"line":140},[90,600,601],{},"+ # add the result\n",[90,603,604],{"class":92,"line":145},[90,605,573],{},[90,607,608],{"class":92,"line":151},[90,609,610],{},"+  \"type\": 'list_git_tags_result',\n",[90,612,613],{"class":92,"line":156},[90,614,615],{},"+  \"data\": git_tags,\n",[90,617,618],{"class":92,"line":162},[90,619,583],{},[90,621,622],{"class":92,"line":168},[90,623,109],{"emptyLinePlaceholder":108},[90,625,626],{"class":92,"line":174},[90,627,628],{},"- next_step = await determine_next_step(thread, git_tags)\n",[90,630,631],{"class":92,"line":180},[90,632,633],{},"+ next_step = await determine_next_step(thread)\n",[90,635,636],{"class":92,"line":186},[90,637,109],{"emptyLinePlaceholder":108},[90,639,640],{"class":92,"line":191},[90,641,235],{},[90,643,644],{"class":92,"line":197},[90,645,240],{},[90,647,648],{"class":92,"line":203},[90,649,275],{},[90,651,652],{"class":92,"line":316},[90,653,280],{},[90,655,656],{"class":92,"line":422},[90,657,658],{},"      thread[\"events\"].append(deploy_result)\n",[90,660,661],{"class":92,"line":427},[90,662,303],{},[90,664,665],{"class":92,"line":432},[90,666,308],{},[90,668,669],{"class":92,"line":437},[90,670,313],{},[90,672,674],{"class":92,"line":673},26,[90,675,319],{},[76,677,678],{},"Overall:",[680,681,682],"blockquote",{},[683,684,686],"h4",{"id":685},"if-you-already-know-what-tools-youll-want-the-model-to-call-just-call-them-deterministically-and-let-the-model-do-the-hard-part-of-figuring-out-how-to-use-their-outputs","If you already know what tools you'll want the model to call, just call them DETERMINISTICALLY and let the model do the hard part of figuring out how to use their outputs",[76,688,689,690,697],{},"Again, AI engineering is all about ",[691,692,696],"a",{"href":693,"rel":694},"https:\u002F\u002Fgithub.com\u002Fhumanlayer\u002F12-factor-agents\u002Fblob\u002Fmain\u002Fcontent\u002Ffactor-03-own-your-context-window.md",[695],"nofollow","Context Engineering",".",[699,700,701],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":85,"searchDepth":99,"depth":99,"links":703},[704],{"id":73,"depth":105,"text":74},"md",{},"\u002Fappendix",{"title":64,"description":85},"ktn-udvIIz88zAkI9uMINqrbJRTm3C1nD5pPeUJMG6I",[711,713,714,715,716,717,718,719,720,721,722,723,724,725,726],{"slug":5,"title":36,"chapterIndex":712},0,{"slug":7,"title":38,"chapterIndex":93},{"slug":9,"title":40,"chapterIndex":99},{"slug":11,"title":42,"chapterIndex":105},{"slug":13,"title":44,"chapterIndex":112},{"slug":15,"title":46,"chapterIndex":118},{"slug":17,"title":48,"chapterIndex":123},{"slug":19,"title":50,"chapterIndex":129},{"slug":21,"title":52,"chapterIndex":134},{"slug":23,"title":54,"chapterIndex":140},{"slug":25,"title":56,"chapterIndex":145},{"slug":27,"title":58,"chapterIndex":151},{"slug":29,"title":60,"chapterIndex":156},{"slug":31,"title":62,"chapterIndex":162},{"slug":33,"title":64,"chapterIndex":168},1788741638422]