[{"data":1,"prerenderedAt":426},["ShallowReactive",2],{"layout-chapters":3,"sidebar-chapters":34,"chapter-factor-1":65,"all-chapters":409},[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":40,"body":67,"chapterIndex":119,"description":104,"extension":404,"meta":405,"navigation":320,"path":406,"seo":407,"slug":9,"stem":9,"__hash__":408},"chapters\u002Ffactor-1.md",{"type":68,"value":69,"toc":401},"minimark",[70,75,79,86,89,95,98,245,266,275,376,382,391,397],[71,72,74],"h3",{"id":73},"_1-natural-language-to-tool-calls","1. Natural Language to Tool Calls",[76,77,78],"p",{},"One of the most common patterns in agent building is to convert natural language to structured tool calls. This is a powerful pattern that allows you to build agents that can reason about tasks and execute them.",[76,80,81],{},[82,83],"img",{"alt":84,"src":85},"110-natural-language-tool-calls","https:\u002F\u002Fgithub.com\u002Fhumanlayer\u002F12-factor-agents\u002Fblob\u002Fmain\u002Fimg\u002F110-natural-language-tool-calls.png?raw=true",[76,87,88],{},"This pattern, when applied atomically, is the simple translation of a phrase like",[90,91,92],"blockquote",{},[76,93,94],{},"can you create a payment link for $750 to Terri for sponsoring the february AI tinkerers meetup?",[76,96,97],{},"to a structured object that describes a Stripe API call like",[99,100,105],"pre",{"className":101,"code":102,"language":103,"meta":104,"style":104},"language-json shiki shiki-themes github-light github-dark","{\n  \"function\": {\n    \"name\": \"create_payment_link\",\n    \"parameters\": {\n      \"amount\": 750,\n      \"customer\": \"cust_128934ddasf9\",\n      \"product\": \"prod_8675309\",\n      \"price\": \"prc_09874329fds\",\n      \"quantity\": 1,\n      \"memo\": \"Hey Jeff - see below for the payment link for the february ai tinkerers meetup\"\n    }\n  }\n}\n","json","",[106,107,108,117,127,143,151,164,177,190,203,216,227,233,239],"code",{"__ignoreMap":104},[109,110,113],"span",{"class":111,"line":112},"line",1,[109,114,116],{"class":115},"sVt8B","{\n",[109,118,120,124],{"class":111,"line":119},2,[109,121,123],{"class":122},"sj4cs","  \"function\"",[109,125,126],{"class":115},": {\n",[109,128,130,133,136,140],{"class":111,"line":129},3,[109,131,132],{"class":122},"    \"name\"",[109,134,135],{"class":115},": ",[109,137,139],{"class":138},"sZZnC","\"create_payment_link\"",[109,141,142],{"class":115},",\n",[109,144,146,149],{"class":111,"line":145},4,[109,147,148],{"class":122},"    \"parameters\"",[109,150,126],{"class":115},[109,152,154,157,159,162],{"class":111,"line":153},5,[109,155,156],{"class":122},"      \"amount\"",[109,158,135],{"class":115},[109,160,161],{"class":122},"750",[109,163,142],{"class":115},[109,165,167,170,172,175],{"class":111,"line":166},6,[109,168,169],{"class":122},"      \"customer\"",[109,171,135],{"class":115},[109,173,174],{"class":138},"\"cust_128934ddasf9\"",[109,176,142],{"class":115},[109,178,180,183,185,188],{"class":111,"line":179},7,[109,181,182],{"class":122},"      \"product\"",[109,184,135],{"class":115},[109,186,187],{"class":138},"\"prod_8675309\"",[109,189,142],{"class":115},[109,191,193,196,198,201],{"class":111,"line":192},8,[109,194,195],{"class":122},"      \"price\"",[109,197,135],{"class":115},[109,199,200],{"class":138},"\"prc_09874329fds\"",[109,202,142],{"class":115},[109,204,206,209,211,214],{"class":111,"line":205},9,[109,207,208],{"class":122},"      \"quantity\"",[109,210,135],{"class":115},[109,212,213],{"class":122},"1",[109,215,142],{"class":115},[109,217,219,222,224],{"class":111,"line":218},10,[109,220,221],{"class":122},"      \"memo\"",[109,223,135],{"class":115},[109,225,226],{"class":138},"\"Hey Jeff - see below for the payment link for the february ai tinkerers meetup\"\n",[109,228,230],{"class":111,"line":229},11,[109,231,232],{"class":115},"    }\n",[109,234,236],{"class":111,"line":235},12,[109,237,238],{"class":115},"  }\n",[109,240,242],{"class":111,"line":241},13,[109,243,244],{"class":115},"}\n",[76,246,247,251,252,259,260,265],{},[248,249,250],"strong",{},"Note",": in reality the stripe API is a bit more complex, a ",[253,254,258],"a",{"href":255,"rel":256},"https:\u002F\u002Fgithub.com\u002Fdexhorthy\u002Fmailcrew",[257],"nofollow","real agent that does this"," (",[253,261,264],{"href":262,"rel":263},"https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=f_cKnoPC_Oo",[257],"video",") would list customers, list products, list prices, etc to build this payload with the proper ids, or include those ids in the prompt\u002Fcontext window (we'll see below how those are kinda the same thing though!)",[76,267,268,269,274],{},"From there, deterministic code can pick up the payload and do something with it. (More on this in ",[253,270,273],{"href":271,"rel":272},"https:\u002F\u002Fgithub.com\u002Fhumanlayer\u002F12-factor-agents\u002Fblob\u002Fmain\u002Fcontent\u002Ffactor-03-own-your-context-window.md",[257],"factor 3",")",[99,276,280],{"className":277,"code":278,"language":279,"meta":104,"style":104},"language-python shiki shiki-themes github-light github-dark","# The LLM takes natural language and returns a structured object\nnextStep = await llm.determineNextStep(\n  \"\"\"\n  create a payment link for $750 to Jeff \n  for sponsoring the february AI tinkerers meetup\n  \"\"\"\n  )\n\n# Handle the structured output based on its function\nif nextStep.function == 'create_payment_link':\n    stripe.paymentlinks.create(nextStep.parameters)\n    return  # or whatever you want, see below\nelif nextStep.function == 'something_else':\n    # ... more cases\n    pass\nelse:  # the model didn't call a tool we know about\n    # do something else\n    pass\n","python",[106,281,282,287,292,297,302,307,311,316,322,327,332,337,342,347,353,359,365,371],{"__ignoreMap":104},[109,283,284],{"class":111,"line":112},[109,285,286],{},"# The LLM takes natural language and returns a structured object\n",[109,288,289],{"class":111,"line":119},[109,290,291],{},"nextStep = await llm.determineNextStep(\n",[109,293,294],{"class":111,"line":129},[109,295,296],{},"  \"\"\"\n",[109,298,299],{"class":111,"line":145},[109,300,301],{},"  create a payment link for $750 to Jeff \n",[109,303,304],{"class":111,"line":153},[109,305,306],{},"  for sponsoring the february AI tinkerers meetup\n",[109,308,309],{"class":111,"line":166},[109,310,296],{},[109,312,313],{"class":111,"line":179},[109,314,315],{},"  )\n",[109,317,318],{"class":111,"line":192},[109,319,321],{"emptyLinePlaceholder":320},true,"\n",[109,323,324],{"class":111,"line":205},[109,325,326],{},"# Handle the structured output based on its function\n",[109,328,329],{"class":111,"line":218},[109,330,331],{},"if nextStep.function == 'create_payment_link':\n",[109,333,334],{"class":111,"line":229},[109,335,336],{},"    stripe.paymentlinks.create(nextStep.parameters)\n",[109,338,339],{"class":111,"line":235},[109,340,341],{},"    return  # or whatever you want, see below\n",[109,343,344],{"class":111,"line":241},[109,345,346],{},"elif nextStep.function == 'something_else':\n",[109,348,350],{"class":111,"line":349},14,[109,351,352],{},"    # ... more cases\n",[109,354,356],{"class":111,"line":355},15,[109,357,358],{},"    pass\n",[109,360,362],{"class":111,"line":361},16,[109,363,364],{},"else:  # the model didn't call a tool we know about\n",[109,366,368],{"class":111,"line":367},17,[109,369,370],{},"    # do something else\n",[109,372,374],{"class":111,"line":373},18,[109,375,358],{},[76,377,378,381],{},[248,379,380],{},"NOTE",": While a full agent would then receive the API call result and loop with it, eventually returning something like",[90,383,384],{},[76,385,386,387],{},"I've successfully created a payment link for $750 to Terri for sponsoring the february AI tinkerers meetup. Here's the link: ",[253,388,389],{"href":389,"rel":390},"https:\u002F\u002Fbuy.stripe.com\u002Ftest_1234567890",[257],[76,392,393,396],{},[248,394,395],{},"Instead",", We're actually going to skip that step here, and save it for another factor, which you may or may not want to also incorporate (up to you!)",[398,399,400],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":104,"searchDepth":119,"depth":119,"links":402},[403],{"id":73,"depth":129,"text":74},"md",{},"\u002Ffactor-1",{"title":40,"description":104},"ZflA5ffMRDeXmiSpwBPHjRnwRQehNbv0j-tBQsHMvUE",[410,412,413,414,415,416,417,418,419,420,421,422,423,424,425],{"slug":5,"title":36,"chapterIndex":411},0,{"slug":7,"title":38,"chapterIndex":112},{"slug":9,"title":40,"chapterIndex":119},{"slug":11,"title":42,"chapterIndex":129},{"slug":13,"title":44,"chapterIndex":145},{"slug":15,"title":46,"chapterIndex":153},{"slug":17,"title":48,"chapterIndex":166},{"slug":19,"title":50,"chapterIndex":179},{"slug":21,"title":52,"chapterIndex":192},{"slug":23,"title":54,"chapterIndex":205},{"slug":25,"title":56,"chapterIndex":218},{"slug":27,"title":58,"chapterIndex":229},{"slug":29,"title":60,"chapterIndex":235},{"slug":31,"title":62,"chapterIndex":241},{"slug":33,"title":64,"chapterIndex":349},1788741638420]