[{"data":1,"prerenderedAt":4448},["ShallowReactive",2],{"highlight:import \"github.com/zoobz-io/zyn\"\n\ntype Contact struct {\n    Name  string `json:\"name\"`\n    Email string `json:\"email\"`\n    Role  string `json:\"role\"`\n}\n\nfunc (c Contact) Validate() error {\n    if c.Email == \"\" {\n        return errors.New(\"email required\")\n    }\n    return nil\n}\n\n// Type-safe extraction — LLM output → validated struct\nextractor, _ := zyn.Extract[Contact](\"contact information\", provider)\n\n// Sessions carry conversation context across calls\nsession := zyn.NewSession()\ncontact, _ := extractor.Fire(ctx, session, \"Reach John at john@acme.com, he's the CTO\")\n// contact.Name = \"John\", contact.Email = \"john@acme.com\", contact.Role = \"CTO\"\n\n// 8 synapse types for different reasoning tasks\ndecision, _ := zyn.Binary(\"Is this a business email?\", provider)\nresult, _ := decision.Fire(ctx, session, contact.Email) // true\n\ncategory, _ := zyn.Classification(\"department\", provider, \"engineering\", \"sales\", \"support\")\ndept, _ := category.Fire(ctx, session, \"I need help with the API integration\")\n// dept = \"engineering\"":3,"footer-resources":4,"search-sections-zyn":2444,"nav-zyn":4287,"content-tree-zyn":4368,"content-table-nav-zyn":4408},"\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-keyword)\">import\u003C/span>\u003Cspan style=\"color:var(--shiki-string)\"> \"github.com/zoobz-io/zyn\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-keyword)\">type\u003C/span>\u003Cspan style=\"color:var(--shiki-type)\"> Contact\u003C/span>\u003Cspan style=\"color:var(--shiki-keyword)\"> struct\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-property)\">    Name\u003C/span>\u003Cspan style=\"color:var(--shiki-type)\">  string\u003C/span>\u003Cspan style=\"color:var(--shiki-string)\"> `json:\"name\"`\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-property)\">    Email\u003C/span>\u003Cspan style=\"color:var(--shiki-type)\"> string\u003C/span>\u003Cspan style=\"color:var(--shiki-string)\"> `json:\"email\"`\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-property)\">    Role\u003C/span>\u003Cspan style=\"color:var(--shiki-type)\">  string\u003C/span>\u003Cspan style=\"color:var(--shiki-string)\"> `json:\"role\"`\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-punctuation)\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-keyword)\">func\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\"> (\u003C/span>\u003Cspan style=\"color:var(--shiki-parameter)\">c \u003C/span>\u003Cspan style=\"color:var(--shiki-type)\">Contact\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">)\u003C/span>\u003Cspan style=\"color:var(--shiki-function)\"> Validate\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">()\u003C/span>\u003Cspan style=\"color:var(--shiki-type)\"> error\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-operator)\">    if\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> c\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">.\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\">Email\u003C/span>\u003Cspan style=\"color:var(--shiki-operator)\"> ==\u003C/span>\u003Cspan style=\"color:var(--shiki-string)\"> \"\"\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-operator)\">        return\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> errors\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">.\u003C/span>\u003Cspan style=\"color:var(--shiki-function)\">New\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">(\u003C/span>\u003Cspan style=\"color:var(--shiki-string)\">\"email required\"\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-punctuation)\">    }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-operator)\">    return\u003C/span>\u003Cspan style=\"color:var(--shiki-keyword)\"> nil\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-punctuation)\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-comment)\">// Type-safe extraction — LLM output → validated struct\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-text)\">extractor\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> _\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> :=\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> zyn\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">.\u003C/span>\u003Cspan style=\"color:var(--shiki-function)\">Extract\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">[\u003C/span>\u003Cspan style=\"color:var(--shiki-type)\">Contact\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">](\u003C/span>\u003Cspan style=\"color:var(--shiki-string)\">\"contact information\"\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> provider\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-comment)\">// Sessions carry conversation context across calls\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-text)\">session\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> :=\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> zyn\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">.\u003C/span>\u003Cspan style=\"color:var(--shiki-function)\">NewSession\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">()\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-text)\">contact\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> _\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> :=\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> extractor\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">.\u003C/span>\u003Cspan style=\"color:var(--shiki-function)\">Fire\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">(\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\">ctx\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> session\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-string)\"> \"Reach John at john@acme.com, he's the CTO\"\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-comment)\">// contact.Name = \"John\", contact.Email = \"john@acme.com\", contact.Role = \"CTO\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-comment)\">// 8 synapse types for different reasoning tasks\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-text)\">decision\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> _\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> :=\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> zyn\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">.\u003C/span>\u003Cspan style=\"color:var(--shiki-function)\">Binary\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">(\u003C/span>\u003Cspan style=\"color:var(--shiki-string)\">\"Is this a business email?\"\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> provider\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-text)\">result\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> _\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> :=\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> decision\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">.\u003C/span>\u003Cspan style=\"color:var(--shiki-function)\">Fire\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">(\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\">ctx\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> session\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> contact\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">.\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\">Email\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">)\u003C/span>\u003Cspan style=\"color:var(--shiki-comment)\"> // true\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-text)\">category\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> _\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> :=\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> zyn\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">.\u003C/span>\u003Cspan style=\"color:var(--shiki-function)\">Classification\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">(\u003C/span>\u003Cspan style=\"color:var(--shiki-string)\">\"department\"\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> provider\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-string)\"> \"engineering\"\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-string)\"> \"sales\"\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-string)\"> \"support\"\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-text)\">dept\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> _\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> :=\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> category\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">.\u003C/span>\u003Cspan style=\"color:var(--shiki-function)\">Fire\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">(\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\">ctx\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> session\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-string)\"> \"I need help with the API integration\"\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-comment)\">// dept = \"engineering\"\u003C/span>\u003C/span>",[5,1701,2109],{"id":6,"title":7,"body":8,"description":103,"extension":1694,"icon":1695,"meta":1696,"navigation":175,"path":1697,"seo":1698,"stem":1699,"__hash__":1700},"resources/readme.md","README",{"type":9,"value":10,"toc":1678},"minimark",[11,15,83,86,89,94,97,413,416,613,616,620,637,640,644,1028,1032,1137,1141,1193,1197,1203,1206,1494,1497,1501,1510,1515,1537,1541,1584,1588,1618,1622,1649,1653,1665,1668,1674],[12,13,14],"h1",{"id":14},"zyn",[16,17,18,29,37,45,53,61,68,75],"p",{},[19,20,24],"a",{"href":21,"rel":22},"https://github.com/zoobz-io/zyn/actions/workflows/ci.yml",[23],"nofollow",[25,26],"img",{"alt":27,"src":28},"CI Status","https://github.com/zoobz-io/zyn/workflows/CI/badge.svg",[19,30,33],{"href":31,"rel":32},"https://codecov.io/gh/zoobz-io/zyn",[23],[25,34],{"alt":35,"src":36},"codecov","https://codecov.io/gh/zoobz-io/zyn/graph/badge.svg?branch=main",[19,38,41],{"href":39,"rel":40},"https://goreportcard.com/report/github.com/zoobz-io/zyn",[23],[25,42],{"alt":43,"src":44},"Go Report Card","https://goreportcard.com/badge/github.com/zoobz-io/zyn",[19,46,49],{"href":47,"rel":48},"https://github.com/zoobz-io/zyn/security/code-scanning",[23],[25,50],{"alt":51,"src":52},"CodeQL","https://github.com/zoobz-io/zyn/workflows/CodeQL/badge.svg",[19,54,57],{"href":55,"rel":56},"https://pkg.go.dev/github.com/zoobz-io/zyn",[23],[25,58],{"alt":59,"src":60},"Go Reference","https://pkg.go.dev/badge/github.com/zoobz-io/zyn.svg",[19,62,64],{"href":63},"LICENSE",[25,65],{"alt":66,"src":67},"License","https://img.shields.io/github/license/zoobz-io/zyn",[19,69,71],{"href":70},"go.mod",[25,72],{"alt":73,"src":74},"Go Version","https://img.shields.io/github/go-mod/go-version/zoobz-io/zyn",[19,76,79],{"href":77,"rel":78},"https://github.com/zoobz-io/zyn/releases",[23],[25,80],{"alt":81,"src":82},"Release","https://img.shields.io/github/v/release/zoobz-io/zyn",[16,84,85],{},"Type-safe LLM orchestration for Go.",[16,87,88],{},"Define synapses with typed outputs, fire them with sessions, and get structured responses with built-in reliability.",[90,91,93],"h2",{"id":92},"composable-thinking-synapses","Composable Thinking Synapses",[16,95,96],{},"Synapses wrap LLM interactions with compile-time type safety.",[98,99,104],"pre",{"className":100,"code":101,"language":102,"meta":103,"style":103},"language-go shiki shiki-themes","type Contact struct {\n    Name  string `json:\"name\"`\n    Email string `json:\"email\"`\n    Phone string `json:\"phone\"`\n}\n\nfunc (c Contact) Validate() error {\n    if c.Email == \"\" {\n        return errors.New(\"email required\")\n    }\n    return nil\n}\n\n// Define a synapse — typed extraction from unstructured text\nextractor, _ := zyn.Extract[Contact](\"contact information\", provider)\n\n// Fire it — get structured data back\nsession := zyn.NewSession()\ncontact, _ := extractor.Fire(ctx, session, \"Reach John at john@acme.com or 555-1234\")\n// contact.Name  → \"John\"\n// contact.Email → \"john@acme.com\"\n// contact.Phone → \"555-1234\"\n","go","",[105,106,107,127,141,153,164,170,177,208,233,256,262,271,276,281,288,329,334,340,358,395,401,407],"code",{"__ignoreMap":103},[108,109,112,116,120,123],"span",{"class":110,"line":111},"line",1,[108,113,115],{"class":114},"sUt3r","type",[108,117,119],{"class":118},"sYBwO"," Contact",[108,121,122],{"class":114}," struct",[108,124,126],{"class":125},"sq5bi"," {\n",[108,128,130,134,137],{"class":110,"line":129},2,[108,131,133],{"class":132},"sBGCq","    Name",[108,135,136],{"class":118},"  string",[108,138,140],{"class":139},"sxAnc"," `json:\"name\"`\n",[108,142,144,147,150],{"class":110,"line":143},3,[108,145,146],{"class":132},"    Email",[108,148,149],{"class":118}," string",[108,151,152],{"class":139}," `json:\"email\"`\n",[108,154,156,159,161],{"class":110,"line":155},4,[108,157,158],{"class":132},"    Phone",[108,160,149],{"class":118},[108,162,163],{"class":139}," `json:\"phone\"`\n",[108,165,167],{"class":110,"line":166},5,[108,168,169],{"class":125},"}\n",[108,171,173],{"class":110,"line":172},6,[108,174,176],{"emptyLinePlaceholder":175},true,"\n",[108,178,180,183,186,190,193,196,200,203,206],{"class":110,"line":179},7,[108,181,182],{"class":114},"func",[108,184,185],{"class":125}," (",[108,187,189],{"class":188},"sSYET","c ",[108,191,192],{"class":118},"Contact",[108,194,195],{"class":125},")",[108,197,199],{"class":198},"s5klm"," Validate",[108,201,202],{"class":125},"()",[108,204,205],{"class":118}," error",[108,207,126],{"class":125},[108,209,211,215,219,222,225,228,231],{"class":110,"line":210},8,[108,212,214],{"class":213},"sW3Qg","    if",[108,216,218],{"class":217},"sh8_p"," c",[108,220,221],{"class":125},".",[108,223,224],{"class":217},"Email",[108,226,227],{"class":213}," ==",[108,229,230],{"class":139}," \"\"",[108,232,126],{"class":125},[108,234,236,239,242,244,247,250,253],{"class":110,"line":235},9,[108,237,238],{"class":213},"        return",[108,240,241],{"class":217}," errors",[108,243,221],{"class":125},[108,245,246],{"class":198},"New",[108,248,249],{"class":125},"(",[108,251,252],{"class":139},"\"email required\"",[108,254,255],{"class":125},")\n",[108,257,259],{"class":110,"line":258},10,[108,260,261],{"class":125},"    }\n",[108,263,265,268],{"class":110,"line":264},11,[108,266,267],{"class":213},"    return",[108,269,270],{"class":114}," nil\n",[108,272,274],{"class":110,"line":273},12,[108,275,169],{"class":125},[108,277,279],{"class":110,"line":278},13,[108,280,176],{"emptyLinePlaceholder":175},[108,282,284],{"class":110,"line":283},14,[108,285,287],{"class":286},"sLkEo","// Define a synapse — typed extraction from unstructured text\n",[108,289,291,294,297,300,303,306,308,311,314,316,319,322,324,327],{"class":110,"line":290},15,[108,292,293],{"class":217},"extractor",[108,295,296],{"class":125},",",[108,298,299],{"class":217}," _",[108,301,302],{"class":217}," :=",[108,304,305],{"class":217}," zyn",[108,307,221],{"class":125},[108,309,310],{"class":198},"Extract",[108,312,313],{"class":125},"[",[108,315,192],{"class":118},[108,317,318],{"class":125},"](",[108,320,321],{"class":139},"\"contact information\"",[108,323,296],{"class":125},[108,325,326],{"class":217}," provider",[108,328,255],{"class":125},[108,330,332],{"class":110,"line":331},16,[108,333,176],{"emptyLinePlaceholder":175},[108,335,337],{"class":110,"line":336},17,[108,338,339],{"class":286},"// Fire it — get structured data back\n",[108,341,343,346,348,350,352,355],{"class":110,"line":342},18,[108,344,345],{"class":217},"session",[108,347,302],{"class":217},[108,349,305],{"class":217},[108,351,221],{"class":125},[108,353,354],{"class":198},"NewSession",[108,356,357],{"class":125},"()\n",[108,359,361,364,366,368,370,373,375,378,380,383,385,388,390,393],{"class":110,"line":360},19,[108,362,363],{"class":217},"contact",[108,365,296],{"class":125},[108,367,299],{"class":217},[108,369,302],{"class":217},[108,371,372],{"class":217}," extractor",[108,374,221],{"class":125},[108,376,377],{"class":198},"Fire",[108,379,249],{"class":125},[108,381,382],{"class":217},"ctx",[108,384,296],{"class":125},[108,386,387],{"class":217}," session",[108,389,296],{"class":125},[108,391,392],{"class":139}," \"Reach John at john@acme.com or 555-1234\"",[108,394,255],{"class":125},[108,396,398],{"class":110,"line":397},20,[108,399,400],{"class":286},"// contact.Name  → \"John\"\n",[108,402,404],{"class":110,"line":403},21,[108,405,406],{"class":286},"// contact.Email → \"john@acme.com\"\n",[108,408,410],{"class":110,"line":409},22,[108,411,412],{"class":286},"// contact.Phone → \"555-1234\"\n",[16,414,415],{},"Sessions carry conversation context. Synapses stay focused on their task.",[98,417,419],{"className":100,"code":418,"language":102,"meta":103,"style":103},"// Chain synapses — each sees the full conversation history\nclassifier, _ := zyn.Classification(\"urgency\", []string{\"low\", \"medium\", \"high\"}, provider)\nurgency, _ := classifier.Fire(ctx, session, contact.Name + \"'s request\")\n\nresponder, _ := zyn.Transform(\"write customer response\", provider)\nresponse, _ := responder.Fire(ctx, session, fmt.Sprintf(\"Urgency: %s\", urgency))\n",[105,420,421,426,480,524,528,557],{"__ignoreMap":103},[108,422,423],{"class":110,"line":111},[108,424,425],{"class":286},"// Chain synapses — each sees the full conversation history\n",[108,427,428,431,433,435,437,439,441,444,446,449,451,454,457,460,463,465,468,470,473,476,478],{"class":110,"line":129},[108,429,430],{"class":217},"classifier",[108,432,296],{"class":125},[108,434,299],{"class":217},[108,436,302],{"class":217},[108,438,305],{"class":217},[108,440,221],{"class":125},[108,442,443],{"class":198},"Classification",[108,445,249],{"class":125},[108,447,448],{"class":139},"\"urgency\"",[108,450,296],{"class":125},[108,452,453],{"class":125}," []",[108,455,456],{"class":118},"string",[108,458,459],{"class":125},"{",[108,461,462],{"class":139},"\"low\"",[108,464,296],{"class":125},[108,466,467],{"class":139}," \"medium\"",[108,469,296],{"class":125},[108,471,472],{"class":139}," \"high\"",[108,474,475],{"class":125},"},",[108,477,326],{"class":217},[108,479,255],{"class":125},[108,481,482,485,487,489,491,494,496,498,500,502,504,506,508,511,513,516,519,522],{"class":110,"line":143},[108,483,484],{"class":217},"urgency",[108,486,296],{"class":125},[108,488,299],{"class":217},[108,490,302],{"class":217},[108,492,493],{"class":217}," classifier",[108,495,221],{"class":125},[108,497,377],{"class":198},[108,499,249],{"class":125},[108,501,382],{"class":217},[108,503,296],{"class":125},[108,505,387],{"class":217},[108,507,296],{"class":125},[108,509,510],{"class":217}," contact",[108,512,221],{"class":125},[108,514,515],{"class":217},"Name",[108,517,518],{"class":217}," +",[108,520,521],{"class":139}," \"'s request\"",[108,523,255],{"class":125},[108,525,526],{"class":110,"line":155},[108,527,176],{"emptyLinePlaceholder":175},[108,529,530,533,535,537,539,541,543,546,548,551,553,555],{"class":110,"line":166},[108,531,532],{"class":217},"responder",[108,534,296],{"class":125},[108,536,299],{"class":217},[108,538,302],{"class":217},[108,540,305],{"class":217},[108,542,221],{"class":125},[108,544,545],{"class":198},"Transform",[108,547,249],{"class":125},[108,549,550],{"class":139},"\"write customer response\"",[108,552,296],{"class":125},[108,554,326],{"class":217},[108,556,255],{"class":125},[108,558,559,562,564,566,568,571,573,575,577,579,581,583,585,588,590,593,595,598,602,605,607,610],{"class":110,"line":172},[108,560,561],{"class":217},"response",[108,563,296],{"class":125},[108,565,299],{"class":217},[108,567,302],{"class":217},[108,569,570],{"class":217}," responder",[108,572,221],{"class":125},[108,574,377],{"class":198},[108,576,249],{"class":125},[108,578,382],{"class":217},[108,580,296],{"class":125},[108,582,387],{"class":217},[108,584,296],{"class":125},[108,586,587],{"class":217}," fmt",[108,589,221],{"class":125},[108,591,592],{"class":198},"Sprintf",[108,594,249],{"class":125},[108,596,597],{"class":139},"\"Urgency: ",[108,599,601],{"class":600},"scyPU","%s",[108,603,604],{"class":139},"\"",[108,606,296],{"class":125},[108,608,609],{"class":217}," urgency",[108,611,612],{"class":125},"))\n",[16,614,615],{},"Type-safe at the edges. Conversational in between.",[90,617,619],{"id":618},"install","Install",[98,621,625],{"className":622,"code":623,"language":624,"meta":103,"style":103},"language-bash shiki shiki-themes","go get github.com/zoobz-io/zyn\n","bash",[105,626,627],{"__ignoreMap":103},[108,628,629,631,634],{"class":110,"line":111},[108,630,102],{"class":198},[108,632,633],{"class":139}," get",[108,635,636],{"class":139}," github.com/zoobz-io/zyn\n",[16,638,639],{},"Requires Go 1.24+.",[90,641,643],{"id":642},"quick-start","Quick Start",[98,645,647],{"className":100,"code":646,"language":102,"meta":103,"style":103},"package main\n\nimport (\n    \"context\"\n    \"fmt\"\n    \"os\"\n    \"time\"\n\n    \"github.com/zoobz-io/zyn\"\n    \"github.com/zoobz-io/zyn/openai\"\n)\n\nfunc main() {\n    ctx := context.Background()\n\n    // Create provider\n    provider := openai.New(openai.Config{\n        APIKey: os.Getenv(\"OPENAI_API_KEY\"),\n    })\n\n    // Create synapse with reliability\n    classifier, _ := zyn.Classification(\n        \"email category\",\n        []string{\"spam\", \"urgent\", \"newsletter\", \"personal\"},\n        provider,\n        zyn.WithRetry(3),\n        zyn.WithTimeout(10*time.Second),\n    )\n\n    // Fire with session context\n    session := zyn.NewSession()\n    category, _ := classifier.Fire(ctx, session, \"URGENT: Your account will be suspended!\")\n\n    fmt.Println(\"Category:\", category) // \"urgent\"\n}\n",[105,648,649,657,661,670,675,680,685,690,694,699,704,708,712,723,740,744,749,776,800,805,809,814,834,843,874,882,901,926,932,937,943,959,992,997,1023],{"__ignoreMap":103},[108,650,651,654],{"class":110,"line":111},[108,652,653],{"class":114},"package",[108,655,656],{"class":118}," main\n",[108,658,659],{"class":110,"line":129},[108,660,176],{"emptyLinePlaceholder":175},[108,662,663,666],{"class":110,"line":143},[108,664,665],{"class":114},"import",[108,667,669],{"class":668},"soy-K"," (\n",[108,671,672],{"class":110,"line":155},[108,673,674],{"class":139},"    \"context\"\n",[108,676,677],{"class":110,"line":166},[108,678,679],{"class":139},"    \"fmt\"\n",[108,681,682],{"class":110,"line":172},[108,683,684],{"class":139},"    \"os\"\n",[108,686,687],{"class":110,"line":179},[108,688,689],{"class":139},"    \"time\"\n",[108,691,692],{"class":110,"line":210},[108,693,176],{"emptyLinePlaceholder":175},[108,695,696],{"class":110,"line":235},[108,697,698],{"class":139},"    \"github.com/zoobz-io/zyn\"\n",[108,700,701],{"class":110,"line":258},[108,702,703],{"class":139},"    \"github.com/zoobz-io/zyn/openai\"\n",[108,705,706],{"class":110,"line":264},[108,707,255],{"class":668},[108,709,710],{"class":110,"line":273},[108,711,176],{"emptyLinePlaceholder":175},[108,713,714,716,719,721],{"class":110,"line":278},[108,715,182],{"class":114},[108,717,718],{"class":198}," main",[108,720,202],{"class":125},[108,722,126],{"class":125},[108,724,725,728,730,733,735,738],{"class":110,"line":283},[108,726,727],{"class":217},"    ctx",[108,729,302],{"class":217},[108,731,732],{"class":217}," context",[108,734,221],{"class":125},[108,736,737],{"class":198},"Background",[108,739,357],{"class":125},[108,741,742],{"class":110,"line":290},[108,743,176],{"emptyLinePlaceholder":175},[108,745,746],{"class":110,"line":331},[108,747,748],{"class":286},"    // Create provider\n",[108,750,751,754,756,759,761,763,765,768,770,773],{"class":110,"line":336},[108,752,753],{"class":217},"    provider",[108,755,302],{"class":217},[108,757,758],{"class":217}," openai",[108,760,221],{"class":125},[108,762,246],{"class":198},[108,764,249],{"class":125},[108,766,767],{"class":118},"openai",[108,769,221],{"class":125},[108,771,772],{"class":118},"Config",[108,774,775],{"class":125},"{\n",[108,777,778,781,784,787,789,792,794,797],{"class":110,"line":342},[108,779,780],{"class":132},"        APIKey",[108,782,783],{"class":125},":",[108,785,786],{"class":217}," os",[108,788,221],{"class":125},[108,790,791],{"class":198},"Getenv",[108,793,249],{"class":125},[108,795,796],{"class":139},"\"OPENAI_API_KEY\"",[108,798,799],{"class":125},"),\n",[108,801,802],{"class":110,"line":360},[108,803,804],{"class":125},"    })\n",[108,806,807],{"class":110,"line":397},[108,808,176],{"emptyLinePlaceholder":175},[108,810,811],{"class":110,"line":403},[108,812,813],{"class":286},"    // Create synapse with reliability\n",[108,815,816,819,821,823,825,827,829,831],{"class":110,"line":409},[108,817,818],{"class":217},"    classifier",[108,820,296],{"class":125},[108,822,299],{"class":217},[108,824,302],{"class":217},[108,826,305],{"class":217},[108,828,221],{"class":125},[108,830,443],{"class":198},[108,832,833],{"class":125},"(\n",[108,835,837,840],{"class":110,"line":836},23,[108,838,839],{"class":139},"        \"email category\"",[108,841,842],{"class":125},",\n",[108,844,846,849,851,853,856,858,861,863,866,868,871],{"class":110,"line":845},24,[108,847,848],{"class":125},"        []",[108,850,456],{"class":118},[108,852,459],{"class":125},[108,854,855],{"class":139},"\"spam\"",[108,857,296],{"class":125},[108,859,860],{"class":139}," \"urgent\"",[108,862,296],{"class":125},[108,864,865],{"class":139}," \"newsletter\"",[108,867,296],{"class":125},[108,869,870],{"class":139}," \"personal\"",[108,872,873],{"class":125},"},\n",[108,875,877,880],{"class":110,"line":876},25,[108,878,879],{"class":217},"        provider",[108,881,842],{"class":125},[108,883,885,888,890,893,895,899],{"class":110,"line":884},26,[108,886,887],{"class":217},"        zyn",[108,889,221],{"class":125},[108,891,892],{"class":198},"WithRetry",[108,894,249],{"class":125},[108,896,898],{"class":897},"sMAmT","3",[108,900,799],{"class":125},[108,902,904,906,908,911,913,916,919,921,924],{"class":110,"line":903},27,[108,905,887],{"class":217},[108,907,221],{"class":125},[108,909,910],{"class":198},"WithTimeout",[108,912,249],{"class":125},[108,914,915],{"class":897},"10",[108,917,918],{"class":217},"*time",[108,920,221],{"class":125},[108,922,923],{"class":217},"Second",[108,925,799],{"class":125},[108,927,929],{"class":110,"line":928},28,[108,930,931],{"class":125},"    )\n",[108,933,935],{"class":110,"line":934},29,[108,936,176],{"emptyLinePlaceholder":175},[108,938,940],{"class":110,"line":939},30,[108,941,942],{"class":286},"    // Fire with session context\n",[108,944,946,949,951,953,955,957],{"class":110,"line":945},31,[108,947,948],{"class":217},"    session",[108,950,302],{"class":217},[108,952,305],{"class":217},[108,954,221],{"class":125},[108,956,354],{"class":198},[108,958,357],{"class":125},[108,960,962,965,967,969,971,973,975,977,979,981,983,985,987,990],{"class":110,"line":961},32,[108,963,964],{"class":217},"    category",[108,966,296],{"class":125},[108,968,299],{"class":217},[108,970,302],{"class":217},[108,972,493],{"class":217},[108,974,221],{"class":125},[108,976,377],{"class":198},[108,978,249],{"class":125},[108,980,382],{"class":217},[108,982,296],{"class":125},[108,984,387],{"class":217},[108,986,296],{"class":125},[108,988,989],{"class":139}," \"URGENT: Your account will be suspended!\"",[108,991,255],{"class":125},[108,993,995],{"class":110,"line":994},33,[108,996,176],{"emptyLinePlaceholder":175},[108,998,1000,1003,1005,1008,1010,1013,1015,1018,1020],{"class":110,"line":999},34,[108,1001,1002],{"class":217},"    fmt",[108,1004,221],{"class":125},[108,1006,1007],{"class":198},"Println",[108,1009,249],{"class":125},[108,1011,1012],{"class":139},"\"Category:\"",[108,1014,296],{"class":125},[108,1016,1017],{"class":217}," category",[108,1019,195],{"class":125},[108,1021,1022],{"class":286}," // \"urgent\"\n",[108,1024,1026],{"class":110,"line":1025},35,[108,1027,169],{"class":125},[90,1029,1031],{"id":1030},"capabilities","Capabilities",[1033,1034,1035,1051],"table",{},[1036,1037,1038],"thead",{},[1039,1040,1041,1045,1048],"tr",{},[1042,1043,1044],"th",{},"Feature",[1042,1046,1047],{},"Description",[1042,1049,1050],{},"Docs",[1052,1053,1054,1069,1082,1096,1110,1123],"tbody",{},[1039,1055,1056,1060,1063],{},[1057,1058,1059],"td",{},"8 Synapse Types",[1057,1061,1062],{},"Binary, Classification, Ranking, Sentiment, Extract, Transform, Analyze, Convert",[1057,1064,1065],{},[19,1066,1068],{"href":1067},"docs/reference/cheatsheet","Synapses",[1039,1070,1071,1074,1077],{},[1057,1072,1073],{},"Sessions",[1057,1075,1076],{},"Conversation context across synapse calls",[1057,1078,1079],{},[19,1080,1073],{"href":1081},"docs/guides/sessions",[1039,1083,1084,1087,1090],{},[1057,1085,1086],{},"Structured Prompts",[1057,1088,1089],{},"Type-driven prompt generation prevents divergence",[1057,1091,1092],{},[19,1093,1095],{"href":1094},"docs/learn/concepts","Concepts",[1039,1097,1098,1101,1104],{},[1057,1099,1100],{},"Reliability Patterns",[1057,1102,1103],{},"Retry, timeout, circuit breaker, rate limiting",[1057,1105,1106],{},[19,1107,1109],{"href":1108},"docs/guides/reliability","Reliability",[1039,1111,1112,1115,1118],{},[1057,1113,1114],{},"Observability",[1057,1116,1117],{},"Typed signals via capitan for all LLM operations",[1057,1119,1120],{},[19,1121,1114],{"href":1122},"docs/guides/observability",[1039,1124,1125,1128,1131],{},[1057,1126,1127],{},"Testing Utilities",[1057,1129,1130],{},"Mock provider for deterministic tests",[1057,1132,1133],{},[19,1134,1136],{"href":1135},"docs/guides/testing","Testing",[90,1138,1140],{"id":1139},"why-zyn","Why zyn?",[1142,1143,1144,1152,1158,1164,1176,1187],"ul",{},[1145,1146,1147,1151],"li",{},[1148,1149,1150],"strong",{},"Type-safe"," — Generics enforce output types at compile time",[1145,1153,1154,1157],{},[1148,1155,1156],{},"Structured"," — LLM responses parse directly into your structs",[1145,1159,1160,1163],{},[1148,1161,1162],{},"Conversational"," — Sessions maintain context across synapse calls",[1145,1165,1166,1169,1170,1175],{},[1148,1167,1168],{},"Reliable"," — ",[19,1171,1174],{"href":1172,"rel":1173},"https://github.com/zoobz-io/pipz",[23],"pipz"," patterns built in",[1145,1177,1178,1169,1181,1186],{},[1148,1179,1180],{},"Observable",[19,1182,1185],{"href":1183,"rel":1184},"https://github.com/zoobz-io/capitan",[23],"capitan"," signals for every LLM call",[1145,1188,1189,1192],{},[1148,1190,1191],{},"Testable"," — Mock provider for deterministic unit tests",[90,1194,1196],{"id":1195},"composable-llm-patterns","Composable LLM Patterns",[16,1198,1199,1200,221],{},"Zyn enables a pattern: ",[1148,1201,1202],{},"define synapses, compose with sessions, observe with signals",[16,1204,1205],{},"Your synapses define typed LLM interactions. Sessions chain them into workflows with shared context. Reliability patterns wrap the whole thing. Capitan signals make it observable.",[98,1207,1209],{"className":100,"code":1208,"language":102,"meta":103,"style":103},"// Define synapses for each step\nextractor, _ := zyn.Extract[Customer](\"customer details\", provider)\nclassifier, _ := zyn.Classification(\"urgency\", []string{\"low\", \"high\"}, provider)\nresponder, _ := zyn.Transform(\"write response\", provider)\n\n// Compose via session — each step sees previous context\nsession := zyn.NewSession()\ncustomer, _ := extractor.Fire(ctx, session, ticket)\nurgency, _ := classifier.Fire(ctx, session, customer.Issue)\nresponse, _ := responder.Fire(ctx, session, urgency)\n\n// Observe via capitan — no instrumentation needed\ncapitan.Hook(zyn.RequestCompleted, logRequest)\ncapitan.Hook(zyn.ProviderCallCompleted, trackTokens)\n",[105,1210,1211,1216,1248,1288,1315,1319,1324,1338,1370,1406,1436,1440,1445,1470],{"__ignoreMap":103},[108,1212,1213],{"class":110,"line":111},[108,1214,1215],{"class":286},"// Define synapses for each step\n",[108,1217,1218,1220,1222,1224,1226,1228,1230,1232,1234,1237,1239,1242,1244,1246],{"class":110,"line":129},[108,1219,293],{"class":217},[108,1221,296],{"class":125},[108,1223,299],{"class":217},[108,1225,302],{"class":217},[108,1227,305],{"class":217},[108,1229,221],{"class":125},[108,1231,310],{"class":198},[108,1233,313],{"class":125},[108,1235,1236],{"class":118},"Customer",[108,1238,318],{"class":125},[108,1240,1241],{"class":139},"\"customer details\"",[108,1243,296],{"class":125},[108,1245,326],{"class":217},[108,1247,255],{"class":125},[108,1249,1250,1252,1254,1256,1258,1260,1262,1264,1266,1268,1270,1272,1274,1276,1278,1280,1282,1284,1286],{"class":110,"line":143},[108,1251,430],{"class":217},[108,1253,296],{"class":125},[108,1255,299],{"class":217},[108,1257,302],{"class":217},[108,1259,305],{"class":217},[108,1261,221],{"class":125},[108,1263,443],{"class":198},[108,1265,249],{"class":125},[108,1267,448],{"class":139},[108,1269,296],{"class":125},[108,1271,453],{"class":125},[108,1273,456],{"class":118},[108,1275,459],{"class":125},[108,1277,462],{"class":139},[108,1279,296],{"class":125},[108,1281,472],{"class":139},[108,1283,475],{"class":125},[108,1285,326],{"class":217},[108,1287,255],{"class":125},[108,1289,1290,1292,1294,1296,1298,1300,1302,1304,1306,1309,1311,1313],{"class":110,"line":155},[108,1291,532],{"class":217},[108,1293,296],{"class":125},[108,1295,299],{"class":217},[108,1297,302],{"class":217},[108,1299,305],{"class":217},[108,1301,221],{"class":125},[108,1303,545],{"class":198},[108,1305,249],{"class":125},[108,1307,1308],{"class":139},"\"write response\"",[108,1310,296],{"class":125},[108,1312,326],{"class":217},[108,1314,255],{"class":125},[108,1316,1317],{"class":110,"line":166},[108,1318,176],{"emptyLinePlaceholder":175},[108,1320,1321],{"class":110,"line":172},[108,1322,1323],{"class":286},"// Compose via session — each step sees previous context\n",[108,1325,1326,1328,1330,1332,1334,1336],{"class":110,"line":179},[108,1327,345],{"class":217},[108,1329,302],{"class":217},[108,1331,305],{"class":217},[108,1333,221],{"class":125},[108,1335,354],{"class":198},[108,1337,357],{"class":125},[108,1339,1340,1343,1345,1347,1349,1351,1353,1355,1357,1359,1361,1363,1365,1368],{"class":110,"line":210},[108,1341,1342],{"class":217},"customer",[108,1344,296],{"class":125},[108,1346,299],{"class":217},[108,1348,302],{"class":217},[108,1350,372],{"class":217},[108,1352,221],{"class":125},[108,1354,377],{"class":198},[108,1356,249],{"class":125},[108,1358,382],{"class":217},[108,1360,296],{"class":125},[108,1362,387],{"class":217},[108,1364,296],{"class":125},[108,1366,1367],{"class":217}," ticket",[108,1369,255],{"class":125},[108,1371,1372,1374,1376,1378,1380,1382,1384,1386,1388,1390,1392,1394,1396,1399,1401,1404],{"class":110,"line":235},[108,1373,484],{"class":217},[108,1375,296],{"class":125},[108,1377,299],{"class":217},[108,1379,302],{"class":217},[108,1381,493],{"class":217},[108,1383,221],{"class":125},[108,1385,377],{"class":198},[108,1387,249],{"class":125},[108,1389,382],{"class":217},[108,1391,296],{"class":125},[108,1393,387],{"class":217},[108,1395,296],{"class":125},[108,1397,1398],{"class":217}," customer",[108,1400,221],{"class":125},[108,1402,1403],{"class":217},"Issue",[108,1405,255],{"class":125},[108,1407,1408,1410,1412,1414,1416,1418,1420,1422,1424,1426,1428,1430,1432,1434],{"class":110,"line":258},[108,1409,561],{"class":217},[108,1411,296],{"class":125},[108,1413,299],{"class":217},[108,1415,302],{"class":217},[108,1417,570],{"class":217},[108,1419,221],{"class":125},[108,1421,377],{"class":198},[108,1423,249],{"class":125},[108,1425,382],{"class":217},[108,1427,296],{"class":125},[108,1429,387],{"class":217},[108,1431,296],{"class":125},[108,1433,609],{"class":217},[108,1435,255],{"class":125},[108,1437,1438],{"class":110,"line":264},[108,1439,176],{"emptyLinePlaceholder":175},[108,1441,1442],{"class":110,"line":273},[108,1443,1444],{"class":286},"// Observe via capitan — no instrumentation needed\n",[108,1446,1447,1449,1451,1454,1456,1458,1460,1463,1465,1468],{"class":110,"line":278},[108,1448,1185],{"class":217},[108,1450,221],{"class":125},[108,1452,1453],{"class":198},"Hook",[108,1455,249],{"class":125},[108,1457,14],{"class":217},[108,1459,221],{"class":125},[108,1461,1462],{"class":217},"RequestCompleted",[108,1464,296],{"class":125},[108,1466,1467],{"class":217}," logRequest",[108,1469,255],{"class":125},[108,1471,1472,1474,1476,1478,1480,1482,1484,1487,1489,1492],{"class":110,"line":283},[108,1473,1185],{"class":217},[108,1475,221],{"class":125},[108,1477,1453],{"class":198},[108,1479,249],{"class":125},[108,1481,14],{"class":217},[108,1483,221],{"class":125},[108,1485,1486],{"class":217},"ProviderCallCompleted",[108,1488,296],{"class":125},[108,1490,1491],{"class":217}," trackTokens",[108,1493,255],{"class":125},[16,1495,1496],{},"Three synapses, one session, full observability.",[90,1498,1500],{"id":1499},"documentation","Documentation",[1142,1502,1503],{},[1145,1504,1505,1509],{},[19,1506,1508],{"href":1507},"docs/overview","Overview"," — Design philosophy",[1511,1512,1514],"h3",{"id":1513},"learn","Learn",[1142,1516,1517,1524,1530],{},[1145,1518,1519,1523],{},[19,1520,1522],{"href":1521},"docs/learn/quickstart","Quickstart"," — Build your first synapse",[1145,1525,1526,1529],{},[19,1527,1528],{"href":1094},"Core Concepts"," — Synapses, sessions, providers",[1145,1531,1532,1536],{},[19,1533,1535],{"href":1534},"docs/learn/architecture","Architecture"," — How zyn works under the hood",[1511,1538,1540],{"id":1539},"guides","Guides",[1142,1542,1543,1550,1557,1562,1567,1572,1577],{},[1145,1544,1545,1549],{},[19,1546,1548],{"href":1547},"docs/guides/installation","Installation"," — Installing and configuring",[1145,1551,1552,1556],{},[19,1553,1555],{"href":1554},"docs/guides/providers","Providers"," — LLM provider configuration",[1145,1558,1559,1561],{},[19,1560,1073],{"href":1081}," — Managing conversation context",[1145,1563,1564,1566],{},[19,1565,1109],{"href":1108}," — Retry, timeout, circuit breaker",[1145,1568,1569,1571],{},[19,1570,1114],{"href":1122}," — Monitoring with capitan",[1145,1573,1574,1576],{},[19,1575,1136],{"href":1135}," — Testing strategies",[1145,1578,1579,1583],{},[19,1580,1582],{"href":1581},"docs/guides/best-practices","Best Practices"," — Production guidelines",[1511,1585,1587],{"id":1586},"cookbook","Cookbook",[1142,1589,1590,1597,1604,1611],{},[1145,1591,1592,1596],{},[19,1593,1595],{"href":1594},"docs/cookbook/classification-workflows","Classification Workflows"," — Real-world classification",[1145,1598,1599,1603],{},[19,1600,1602],{"href":1601},"docs/cookbook/extraction-pipelines","Extraction Pipelines"," — Structured data extraction",[1145,1605,1606,1610],{},[19,1607,1609],{"href":1608},"docs/cookbook/multi-turn-conversations","Multi-Turn Conversations"," — Complex workflows",[1145,1612,1613,1617],{},[19,1614,1616],{"href":1615},"docs/cookbook/error-handling","Error Handling"," — Robust error management",[1511,1619,1621],{"id":1620},"reference","Reference",[1142,1623,1624,1630,1635,1642],{},[1145,1625,1626,1629],{},[19,1627,1628],{"href":1067},"Cheatsheet"," — Quick reference",[1145,1631,1632,1634],{},[19,1633,1068],{"href":1067}," — All synapse types",[1145,1636,1637,1641],{},[19,1638,1640],{"href":1639},"docs/reference/options","Options"," — Configuration options",[1145,1643,1644,1648],{},[19,1645,1647],{"href":1646},"docs/reference/session","Session"," — Session API",[90,1650,1652],{"id":1651},"contributing","Contributing",[16,1654,1655,1656,1660,1661,1664],{},"See ",[19,1657,1659],{"href":1658},"CONTRIBUTING","CONTRIBUTING.md"," for guidelines. Run ",[105,1662,1663],{},"make help"," for available commands.",[90,1666,66],{"id":1667},"license",[16,1669,1670,1671,1673],{},"MIT License — see ",[19,1672,63],{"href":63}," for details.",[1675,1676,1677],"style",{},"html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}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 pre.shiki code .scyPU, html code.shiki .scyPU{--shiki-default:var(--shiki-placeholder)}html pre.shiki code .soy-K, html code.shiki .soy-K{--shiki-default:#BBBBBB}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}",{"title":103,"searchDepth":129,"depth":129,"links":1679},[1680,1681,1682,1683,1684,1685,1686,1692,1693],{"id":92,"depth":129,"text":93},{"id":618,"depth":129,"text":619},{"id":642,"depth":129,"text":643},{"id":1030,"depth":129,"text":1031},{"id":1139,"depth":129,"text":1140},{"id":1195,"depth":129,"text":1196},{"id":1499,"depth":129,"text":1500,"children":1687},[1688,1689,1690,1691],{"id":1513,"depth":143,"text":1514},{"id":1539,"depth":143,"text":1540},{"id":1586,"depth":143,"text":1587},{"id":1620,"depth":143,"text":1621},{"id":1651,"depth":129,"text":1652},{"id":1667,"depth":129,"text":66},"md","book-open",{},"/readme",{"title":7,"description":103},"readme","UhaBrIKOTxE7O6Lb79L2cQPAqe02iFLxjw5LFiQQVqM",{"id":1702,"title":1703,"body":1704,"description":103,"extension":1694,"icon":2103,"meta":2104,"navigation":175,"path":2105,"seo":2106,"stem":2107,"__hash__":2108},"resources/security.md","Security",{"type":9,"value":1705,"toc":2091},[1706,1710,1714,1744,1748,1751,1784,1788,1792,1806,1810,1916,1920,1923,1994,1998,2001,2074,2078,2081,2085,2088],[12,1707,1709],{"id":1708},"security-policy","Security Policy",[90,1711,1713],{"id":1712},"supported-versions","Supported Versions",[1033,1715,1716,1726],{},[1036,1717,1718],{},[1039,1719,1720,1723],{},[1042,1721,1722],{},"Version",[1042,1724,1725],{},"Supported",[1052,1727,1728,1736],{},[1039,1729,1730,1733],{},[1057,1731,1732],{},"1.x.x",[1057,1734,1735],{},"✅",[1039,1737,1738,1741],{},[1057,1739,1740],{},"\u003C 1.0",[1057,1742,1743],{},"❌",[90,1745,1747],{"id":1746},"reporting-a-vulnerability","Reporting a Vulnerability",[16,1749,1750],{},"If you discover a security vulnerability in zyn, please follow these steps:",[1752,1753,1754,1760,1767],"ol",{},[1145,1755,1756,1759],{},[1148,1757,1758],{},"DO NOT"," open a public issue",[1145,1761,1762,1763],{},"Email security concerns to: ",[19,1764,1766],{"href":1765},"mailto:security@zoobzio.com","security@zoobzio.com",[1145,1768,1769,1770],{},"Include:\n",[1142,1771,1772,1775,1778,1781],{},[1145,1773,1774],{},"Description of the vulnerability",[1145,1776,1777],{},"Steps to reproduce",[1145,1779,1780],{},"Potential impact",[1145,1782,1783],{},"Suggested fix (if any)",[90,1785,1787],{"id":1786},"security-considerations","Security Considerations",[1511,1789,1791],{"id":1790},"api-keys","API Keys",[1142,1793,1794,1797,1800,1803],{},[1145,1795,1796],{},"Never commit API keys to version control",[1145,1798,1799],{},"Use environment variables for credentials",[1145,1801,1802],{},"Rotate keys regularly",[1145,1804,1805],{},"Use separate keys for development/production",[1511,1807,1809],{"id":1808},"provider-security","Provider Security",[98,1811,1813],{"className":100,"code":1812,"language":102,"meta":103,"style":103},"// Good - API key from environment\nprovider := openai.New(openai.Config{\n    APIKey: os.Getenv(\"OPENAI_API_KEY\"),\n})\n\n// Bad - Hardcoded API key\nprovider := openai.New(openai.Config{\n    APIKey: \"sk-1234567890abcdef\", // NEVER DO THIS\n})\n",[105,1814,1815,1820,1843,1862,1867,1871,1876,1898,1912],{"__ignoreMap":103},[108,1816,1817],{"class":110,"line":111},[108,1818,1819],{"class":286},"// Good - API key from environment\n",[108,1821,1822,1825,1827,1829,1831,1833,1835,1837,1839,1841],{"class":110,"line":129},[108,1823,1824],{"class":217},"provider",[108,1826,302],{"class":217},[108,1828,758],{"class":217},[108,1830,221],{"class":125},[108,1832,246],{"class":198},[108,1834,249],{"class":125},[108,1836,767],{"class":118},[108,1838,221],{"class":125},[108,1840,772],{"class":118},[108,1842,775],{"class":125},[108,1844,1845,1848,1850,1852,1854,1856,1858,1860],{"class":110,"line":143},[108,1846,1847],{"class":132},"    APIKey",[108,1849,783],{"class":125},[108,1851,786],{"class":217},[108,1853,221],{"class":125},[108,1855,791],{"class":198},[108,1857,249],{"class":125},[108,1859,796],{"class":139},[108,1861,799],{"class":125},[108,1863,1864],{"class":110,"line":155},[108,1865,1866],{"class":125},"})\n",[108,1868,1869],{"class":110,"line":166},[108,1870,176],{"emptyLinePlaceholder":175},[108,1872,1873],{"class":110,"line":172},[108,1874,1875],{"class":286},"// Bad - Hardcoded API key\n",[108,1877,1878,1880,1882,1884,1886,1888,1890,1892,1894,1896],{"class":110,"line":179},[108,1879,1824],{"class":217},[108,1881,302],{"class":217},[108,1883,758],{"class":217},[108,1885,221],{"class":125},[108,1887,246],{"class":198},[108,1889,249],{"class":125},[108,1891,767],{"class":118},[108,1893,221],{"class":125},[108,1895,772],{"class":118},[108,1897,775],{"class":125},[108,1899,1900,1902,1904,1907,1909],{"class":110,"line":210},[108,1901,1847],{"class":132},[108,1903,783],{"class":125},[108,1905,1906],{"class":139}," \"sk-1234567890abcdef\"",[108,1908,296],{"class":125},[108,1910,1911],{"class":286}," // NEVER DO THIS\n",[108,1913,1914],{"class":110,"line":235},[108,1915,1866],{"class":125},[1511,1917,1919],{"id":1918},"prompt-injection","Prompt Injection",[16,1921,1922],{},"Be aware of prompt injection risks when using user input:",[98,1924,1926],{"className":100,"code":1925,"language":102,"meta":103,"style":103},"// Validate and sanitize user input\nuserInput := sanitize(request.Input)\n\n// Use structured prompts to reduce injection risk\nresult, err := synapse.Fire(ctx, userInput)\n",[105,1927,1928,1933,1955,1959,1964],{"__ignoreMap":103},[108,1929,1930],{"class":110,"line":111},[108,1931,1932],{"class":286},"// Validate and sanitize user input\n",[108,1934,1935,1938,1940,1943,1945,1948,1950,1953],{"class":110,"line":129},[108,1936,1937],{"class":217},"userInput",[108,1939,302],{"class":217},[108,1941,1942],{"class":198}," sanitize",[108,1944,249],{"class":125},[108,1946,1947],{"class":217},"request",[108,1949,221],{"class":125},[108,1951,1952],{"class":217},"Input",[108,1954,255],{"class":125},[108,1956,1957],{"class":110,"line":143},[108,1958,176],{"emptyLinePlaceholder":175},[108,1960,1961],{"class":110,"line":155},[108,1962,1963],{"class":286},"// Use structured prompts to reduce injection risk\n",[108,1965,1966,1969,1971,1974,1976,1979,1981,1983,1985,1987,1989,1992],{"class":110,"line":166},[108,1967,1968],{"class":217},"result",[108,1970,296],{"class":125},[108,1972,1973],{"class":217}," err",[108,1975,302],{"class":217},[108,1977,1978],{"class":217}," synapse",[108,1980,221],{"class":125},[108,1982,377],{"class":198},[108,1984,249],{"class":125},[108,1986,382],{"class":217},[108,1988,296],{"class":125},[108,1990,1991],{"class":217}," userInput",[108,1993,255],{"class":125},[1511,1995,1997],{"id":1996},"rate-limiting","Rate Limiting",[16,1999,2000],{},"Protect your API keys from abuse:",[98,2002,2004],{"className":100,"code":2003,"language":102,"meta":103,"style":103},"synapse := Binary(\"question\", provider,\n    WithRateLimit(10, 100), // 10 requests/sec, burst of 100\n    WithCircuitBreaker(5, 30*time.Second),\n)\n",[105,2005,2006,2027,2047,2070],{"__ignoreMap":103},[108,2007,2008,2011,2013,2016,2018,2021,2023,2025],{"class":110,"line":111},[108,2009,2010],{"class":217},"synapse",[108,2012,302],{"class":217},[108,2014,2015],{"class":198}," Binary",[108,2017,249],{"class":125},[108,2019,2020],{"class":139},"\"question\"",[108,2022,296],{"class":125},[108,2024,326],{"class":217},[108,2026,842],{"class":125},[108,2028,2029,2032,2034,2036,2038,2041,2044],{"class":110,"line":129},[108,2030,2031],{"class":198},"    WithRateLimit",[108,2033,249],{"class":125},[108,2035,915],{"class":897},[108,2037,296],{"class":125},[108,2039,2040],{"class":897}," 100",[108,2042,2043],{"class":125},"),",[108,2045,2046],{"class":286}," // 10 requests/sec, burst of 100\n",[108,2048,2049,2052,2054,2057,2059,2062,2064,2066,2068],{"class":110,"line":143},[108,2050,2051],{"class":198},"    WithCircuitBreaker",[108,2053,249],{"class":125},[108,2055,2056],{"class":897},"5",[108,2058,296],{"class":125},[108,2060,2061],{"class":897}," 30",[108,2063,918],{"class":217},[108,2065,221],{"class":125},[108,2067,923],{"class":217},[108,2069,799],{"class":125},[108,2071,2072],{"class":110,"line":155},[108,2073,255],{"class":125},[90,2075,2077],{"id":2076},"security-updates","Security Updates",[16,2079,2080],{},"Security updates are released as soon as possible after discovery and verification. Update to the latest version promptly.",[90,2082,2084],{"id":2083},"acknowledgments","Acknowledgments",[16,2086,2087],{},"We appreciate responsible disclosure of security vulnerabilities. Contributors who report valid security issues will be acknowledged (unless they prefer to remain anonymous).",[1675,2089,2090],{},"html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}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 pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}",{"title":103,"searchDepth":129,"depth":129,"links":2092},[2093,2094,2095,2101,2102],{"id":1712,"depth":129,"text":1713},{"id":1746,"depth":129,"text":1747},{"id":1786,"depth":129,"text":1787,"children":2096},[2097,2098,2099,2100],{"id":1790,"depth":143,"text":1791},{"id":1808,"depth":143,"text":1809},{"id":1918,"depth":143,"text":1919},{"id":1996,"depth":143,"text":1997},{"id":2076,"depth":129,"text":2077},{"id":2083,"depth":129,"text":2084},"shield",{},"/security",{"title":1703,"description":103},"security","TDd2d2z6nhnVxKqcFAlvTx3sfPqHd58ixexGu3i_x9k",{"id":2110,"title":1652,"body":2111,"description":2119,"extension":1694,"icon":105,"meta":2440,"navigation":175,"path":2441,"seo":2442,"stem":1651,"__hash__":2443},"resources/contributing.md",{"type":9,"value":2112,"toc":2426},[2113,2117,2120,2124,2127,2131,2160,2164,2249,2252,2269,2273,2290,2294,2298,2321,2325,2345,2349,2371,2375,2378,2410,2416,2420,2423],[12,2114,2116],{"id":2115},"contributing-to-zyn","Contributing to zyn",[16,2118,2119],{},"Thank you for your interest in contributing to zyn! This document provides guidelines and instructions for contributing to the project.",[90,2121,2123],{"id":2122},"code-of-conduct","Code of Conduct",[16,2125,2126],{},"Be respectful and inclusive. We're all here to build better software together.",[90,2128,2130],{"id":2129},"getting-started","Getting Started",[1752,2132,2133,2136,2142,2148,2151,2157],{},[1145,2134,2135],{},"Fork the repository",[1145,2137,2138,2139],{},"Clone your fork: ",[105,2140,2141],{},"git clone https://github.com/yourusername/zyn.git",[1145,2143,2144,2145],{},"Create a new branch: ",[105,2146,2147],{},"git checkout -b feature-name",[1145,2149,2150],{},"Make your changes",[1145,2152,2153,2154],{},"Run tests: ",[105,2155,2156],{},"make test",[1145,2158,2159],{},"Submit a pull request",[90,2161,2163],{"id":2162},"development-setup","Development Setup",[98,2165,2167],{"className":622,"code":2166,"language":624,"meta":103,"style":103},"# Install dependencies\ngo mod download\n\n# Install development tools\nmake install-tools\n\n# Run tests\nmake test\n\n# Run linters\nmake lint\n\n# Generate coverage\nmake coverage\n",[105,2168,2169,2174,2184,2188,2193,2201,2205,2210,2217,2221,2226,2233,2237,2242],{"__ignoreMap":103},[108,2170,2171],{"class":110,"line":111},[108,2172,2173],{"class":286},"# Install dependencies\n",[108,2175,2176,2178,2181],{"class":110,"line":129},[108,2177,102],{"class":198},[108,2179,2180],{"class":139}," mod",[108,2182,2183],{"class":139}," download\n",[108,2185,2186],{"class":110,"line":143},[108,2187,176],{"emptyLinePlaceholder":175},[108,2189,2190],{"class":110,"line":155},[108,2191,2192],{"class":286},"# Install development tools\n",[108,2194,2195,2198],{"class":110,"line":166},[108,2196,2197],{"class":198},"make",[108,2199,2200],{"class":139}," install-tools\n",[108,2202,2203],{"class":110,"line":172},[108,2204,176],{"emptyLinePlaceholder":175},[108,2206,2207],{"class":110,"line":179},[108,2208,2209],{"class":286},"# Run tests\n",[108,2211,2212,2214],{"class":110,"line":210},[108,2213,2197],{"class":198},[108,2215,2216],{"class":139}," test\n",[108,2218,2219],{"class":110,"line":235},[108,2220,176],{"emptyLinePlaceholder":175},[108,2222,2223],{"class":110,"line":258},[108,2224,2225],{"class":286},"# Run linters\n",[108,2227,2228,2230],{"class":110,"line":264},[108,2229,2197],{"class":198},[108,2231,2232],{"class":139}," lint\n",[108,2234,2235],{"class":110,"line":273},[108,2236,176],{"emptyLinePlaceholder":175},[108,2238,2239],{"class":110,"line":278},[108,2240,2241],{"class":286},"# Generate coverage\n",[108,2243,2244,2246],{"class":110,"line":283},[108,2245,2197],{"class":198},[108,2247,2248],{"class":139}," coverage\n",[90,2250,1136],{"id":2251},"testing",[1142,2253,2254,2257,2263,2266],{},[1145,2255,2256],{},"All code must have tests",[1145,2258,2259,2260,2262],{},"Run ",[105,2261,2156],{}," before submitting PRs",[1145,2264,2265],{},"Aim for >80% code coverage",[1145,2267,2268],{},"Test both success and error paths",[90,2270,2272],{"id":2271},"code-style","Code Style",[1142,2274,2275,2278,2284,2287],{},[1145,2276,2277],{},"Follow standard Go conventions",[1145,2279,2259,2280,2283],{},[105,2281,2282],{},"make lint"," to check code style",[1145,2285,2286],{},"Use meaningful variable and function names",[1145,2288,2289],{},"Add comments for complex logic",[90,2291,2293],{"id":2292},"adding-new-features","Adding New Features",[1511,2295,2297],{"id":2296},"adding-a-new-synapse-type","Adding a New Synapse Type",[1752,2299,2300,2306,2309,2315,2318],{},[1145,2301,2302,2303,195],{},"Create the synapse file (e.g., ",[105,2304,2305],{},"newtype.go",[1145,2307,2308],{},"Implement the synapse following existing patterns",[1145,2310,2311,2312,195],{},"Add comprehensive tests (",[105,2313,2314],{},"newtype_test.go",[1145,2316,2317],{},"Update documentation",[1145,2319,2320],{},"Add to prompt consistency test",[1511,2322,2324],{"id":2323},"adding-a-new-provider","Adding a New Provider",[1752,2326,2327,2333,2336,2339,2342],{},[1145,2328,2329,2330],{},"Create provider directory: ",[105,2331,2332],{},"providers/newprovider/",[1145,2334,2335],{},"Implement the Provider interface",[1145,2337,2338],{},"Add tests with mock HTTP server",[1145,2340,2341],{},"Document authentication requirements",[1145,2343,2344],{},"Add example usage",[90,2346,2348],{"id":2347},"pull-request-process","Pull Request Process",[1752,2350,2351,2354,2360,2365,2368],{},[1145,2352,2353],{},"Update documentation for any new features",[1145,2355,2356,2357],{},"Ensure all tests pass: ",[105,2358,2359],{},"make test-all",[1145,2361,2362,2363],{},"Ensure linting passes: ",[105,2364,2282],{},[1145,2366,2367],{},"Update CHANGELOG.md with your changes",[1145,2369,2370],{},"Submit PR with clear description",[90,2372,2374],{"id":2373},"commit-messages","Commit Messages",[16,2376,2377],{},"Use clear, descriptive commit messages:",[1142,2379,2380,2386,2392,2398,2404],{},[1145,2381,2382,2385],{},[105,2383,2384],{},"feat:"," for new features",[1145,2387,2388,2391],{},[105,2389,2390],{},"fix:"," for bug fixes",[1145,2393,2394,2397],{},[105,2395,2396],{},"docs:"," for documentation changes",[1145,2399,2400,2403],{},[105,2401,2402],{},"test:"," for test additions/changes",[1145,2405,2406,2409],{},[105,2407,2408],{},"refactor:"," for code refactoring",[16,2411,2412,2413],{},"Example: ",[105,2414,2415],{},"feat: add Transform synapse for text transformations",[90,2417,2419],{"id":2418},"questions","Questions?",[16,2421,2422],{},"Open an issue for questions or discussions about potential changes.",[1675,2424,2425],{},"html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}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);}",{"title":103,"searchDepth":129,"depth":129,"links":2427},[2428,2429,2430,2431,2432,2433,2437,2438,2439],{"id":2122,"depth":129,"text":2123},{"id":2129,"depth":129,"text":2130},{"id":2162,"depth":129,"text":2163},{"id":2251,"depth":129,"text":1136},{"id":2271,"depth":129,"text":2272},{"id":2292,"depth":129,"text":2293,"children":2434},[2435,2436],{"id":2296,"depth":143,"text":2297},{"id":2323,"depth":143,"text":2324},{"id":2347,"depth":129,"text":2348},{"id":2373,"depth":129,"text":2374},{"id":2418,"depth":129,"text":2419},{},"/contributing",{"title":1652,"description":2119},"oFwbpyLDroVh4e1tXrxGKO9UfE-RfOQdgFqUUcpctNA",[2445,2449,2452,2457,2462,2466,2471,2476,2481,2486,2491,2496,2500,2504,2508,2513,2518,2523,2527,2532,2537,2542,2546,2550,2554,2558,2563,2568,2573,2578,2582,2587,2592,2597,2602,2606,2611,2616,2621,2626,2630,2634,2638,2643,2647,2652,2657,2662,2667,2671,2676,2681,2686,2691,2695,2700,2705,2709,2713,2716,2721,2724,2728,2733,2738,2743,2748,2753,2757,2761,2764,2768,2772,2777,2782,2787,2792,2796,2800,2805,2810,2815,2820,2824,2828,2832,2836,2841,2846,2851,2855,2860,2865,2870,2875,2879,2884,2889,2894,2899,2903,2908,2913,2917,2921,2925,2930,2935,2940,2945,2949,2954,2958,2963,2967,2972,2977,2982,2987,2991,2995,2999,3003,3008,3013,3018,3023,3027,3032,3037,3041,3046,3051,3056,3061,3066,3070,3075,3080,3084,3088,3092,3096,3101,3106,3111,3116,3121,3126,3131,3136,3141,3145,3150,3155,3160,3165,3170,3174,3178,3182,3186,3191,3196,3201,3205,3210,3215,3220,3223,3228,3233,3238,3243,3247,3252,3257,3262,3265,3270,3275,3280,3283,3288,3293,3298,3301,3306,3311,3316,3320,3324,3329,3334,3339,3344,3349,3353,3357,3361,3366,3371,3376,3381,3386,3390,3394,3398,3403,3408,3413,3418,3423,3428,3432,3436,3440,3445,3450,3455,3460,3465,3470,3475,3480,3485,3489,3493,3497,3502,3506,3510,3514,3519,3523,3527,3532,3536,3541,3545,3548,3552,3557,3562,3567,3572,3577,3580,3585,3590,3594,3599,3603,3608,3612,3616,3621,3626,3630,3634,3639,3644,3649,3654,3658,3662,3665,3669,3673,3677,3680,3684,3689,3694,3698,3703,3707,3711,3714,3718,3723,3727,3732,3735,3739,3744,3748,3752,3757,3761,3765,3768,3772,3776,3780,3783,3788,3793,3798,3802,3807,3811,3815,3818,3822,3826,3831,3836,3839,3843,3848,3853,3858,3863,3867,3872,3876,3880,3883,3887,3891,3895,3898,3902,3907,3911,3915,3920,3924,3928,3931,3935,3939,3943,3946,3950,3954,3959,3963,3968,3972,3976,3979,3983,3987,3991,3994,3999,4003,4008,4012,4016,4020,4024,4029,4033,4037,4042,4046,4051,4056,4061,4066,4070,4074,4079,4084,4088,4092,4096,4100,4105,4110,4115,4120,4124,4129,4134,4139,4144,4149,4153,4157,4161,4166,4171,4174,4179,4184,4189,4193,4197,4202,4206,4210,4215,4219,4224,4228,4233,4237,4242,4246,4251,4256,4260,4265,4269,4274,4278,4283],{"id":2446,"title":1508,"titles":2447,"content":2448,"level":111},"/v1.0.6/overview",[],"Type-safe LLM orchestration framework with composable reliability patterns",{"id":2450,"title":14,"titles":2451,"content":2448,"level":111},"/v1.0.6/overview#zyn",[],{"id":2453,"title":2454,"titles":2455,"content":2456,"level":129},"/v1.0.6/overview#the-problem","The Problem",[14],"Working with Large Language Models presents unique challenges: Unstructured outputs - LLMs return free-form text, requiring parsing and validationUnreliable responses - Rate limits, timeouts, and malformed JSON are commonPrompt drift - Ad-hoc prompting leads to inconsistent behavior over timeNo type safety - Runtime errors from unexpected response formatsContext management - Multi-turn conversations require careful state handling",{"id":2458,"title":2459,"titles":2460,"content":2461,"level":129},"/v1.0.6/overview#the-solution","The Solution",[14],"zyn provides structured, type-safe LLM interactions through synapses - specialized units that handle specific interaction patterns with compile-time guarantees. // Type-safe extraction with automatic validation\ntype Contact struct {\n    Name  string `json:\"name\"`\n    Email string `json:\"email\"`\n}\n\nfunc (c Contact) Validate() error {\n    if c.Email == \"\" {\n        return fmt.Errorf(\"email required\")\n    }\n    return nil\n}\n\nextractor, _ := zyn.Extract[Contact](\"contact information\", provider)\ncontact, err := extractor.Fire(ctx, session, \"John at john@example.com\")\n// contact is Contact{Name: \"John\", Email: \"john@example.com\"}\n// Validation runs automatically - err if Email is empty",{"id":2463,"title":2464,"titles":2465,"content":103,"level":129},"/v1.0.6/overview#core-philosophy","Core Philosophy",[14],{"id":2467,"title":2468,"titles":2469,"content":2470,"level":143},"/v1.0.6/overview#synapses-over-prompts","Synapses Over Prompts",[14,2464],"Instead of crafting prompts, you declare intent through synapses: PatternSynapseInputOutputYes/No decisionBinarystringboolCategorizationClassificationstringstringData extractionExtract[T]stringTText transformationTransformstringstringStructured analysisAnalyze[T]TstringType conversionConvert[T,U]TUOrderingRankingstringstringEmotional analysisSentimentstringSentimentResult",{"id":2472,"title":2473,"titles":2474,"content":2475,"level":143},"/v1.0.6/overview#sessions-for-context","Sessions for Context",[14,2464],"Sessions manage conversation history across synapse calls: session := zyn.NewSession()\n\n// First call\nclassifier.Fire(ctx, session, \"I love this product!\")\n// Session: [user: \"I love this!\", assistant: {sentiment analysis}]\n\n// Second call sees previous context\nfollowup.Fire(ctx, session, \"What did I say about the product?\")\n// LLM can reference the previous exchange",{"id":2477,"title":2478,"titles":2479,"content":2480,"level":143},"/v1.0.6/overview#reliability-built-in","Reliability Built-In",[14,2464],"Every synapse integrates with pipz for production-grade reliability: synapse, _ := zyn.Binary(\"question\", provider,\n    zyn.WithRetry(3),                              // Retry on failure\n    zyn.WithTimeout(10*time.Second),               // Timeout protection\n    zyn.WithCircuitBreaker(5, 30*time.Second),     // Circuit breaker\n    zyn.WithRateLimit(10, 100),                    // Rate limiting\n)",{"id":2482,"title":2483,"titles":2484,"content":2485,"level":143},"/v1.0.6/overview#observable-by-default","Observable by Default",[14,2464],"All synapses emit capitan hooks for observability: capitan.Hook(zyn.ProviderCallCompleted, func(ctx context.Context, e *capitan.Event) {\n    tokens, _ := zyn.TotalTokensKey.From(e)\n    log.Printf(\"Used %d tokens\", tokens)\n})",{"id":2487,"title":2488,"titles":2489,"content":2490,"level":129},"/v1.0.6/overview#design-priorities","Design Priorities",[14],"Type Safety - Compile-time guarantees over runtime surprisesComposability - Small, focused synapses that combine naturallyReliability - Production patterns built-in, not bolted onObservability - Full visibility into LLM interactionsSimplicity - Minimal API surface, maximum capability",{"id":2492,"title":2493,"titles":2494,"content":2495,"level":129},"/v1.0.6/overview#next-steps","Next Steps",[14],"Quickstart - Build your first synapse in 10 minutesCore Concepts - Deep dive into synapses, sessions, and providersGuides - Practical implementation patternsCookbook - Real-world recipesReference - Complete API documentation html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}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 pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}html pre.shiki code .scyPU, html code.shiki .scyPU{--shiki-default:var(--shiki-placeholder)}",{"id":2497,"title":1522,"titles":2498,"content":2499,"level":111},"/v1.0.6/learn/quickstart",[],"Build your first synapse in 10 minutes",{"id":2501,"title":1522,"titles":2502,"content":2503,"level":111},"/v1.0.6/learn/quickstart#quickstart",[],"Build your first LLM-powered feature in 10 minutes.",{"id":2505,"title":1548,"titles":2506,"content":2507,"level":129},"/v1.0.6/learn/quickstart#installation",[1522],"go get github.com/zoobz-io/zyn",{"id":2509,"title":2510,"titles":2511,"content":2512,"level":129},"/v1.0.6/learn/quickstart#your-first-synapse","Your First Synapse",[1522],"Let's build an email classifier that categorizes incoming messages. package main\n\nimport (\n    \"context\"\n    \"fmt\"\n    \"os\"\n\n    \"github.com/zoobz-io/zyn\"\n    \"github.com/zoobz-io/zyn/openai\"\n)\n\nfunc main() {\n    // 1. Create a provider\n    provider := openai.New(openai.Config{\n        APIKey: os.Getenv(\"OPENAI_API_KEY\"),\n    })\n\n    // 2. Create a classification synapse\n    classifier, err := zyn.Classification(\n        \"What type of email is this?\",\n        []string{\"spam\", \"urgent\", \"newsletter\", \"personal\"},\n        provider,\n    )\n    if err != nil {\n        panic(err)\n    }\n\n    // 3. Create a session for context\n    session := zyn.NewSession()\n\n    // 4. Fire the synapse\n    ctx := context.Background()\n    category, err := classifier.Fire(ctx, session, \"URGENT: Your account will be suspended!\")\n    if err != nil {\n        panic(err)\n    }\n\n    fmt.Println(\"Category:\", category) // \"urgent\"\n}",{"id":2514,"title":2515,"titles":2516,"content":2517,"level":129},"/v1.0.6/learn/quickstart#what-just-happened","What Just Happened?",[1522],"Provider - Connects to OpenAI's APISynapse - Defines the task (classify into categories)Session - Manages conversation contextFire - Executes the LLM call and returns typed results",{"id":2519,"title":2520,"titles":2521,"content":2522,"level":129},"/v1.0.6/learn/quickstart#add-reliability","Add Reliability",[1522],"Real applications need error handling. Add retry and timeout: classifier, err := zyn.Classification(\n    \"What type of email is this?\",\n    []string{\"spam\", \"urgent\", \"newsletter\", \"personal\"},\n    provider,\n    zyn.WithRetry(3),                    // Retry up to 3 times\n    zyn.WithTimeout(10*time.Second),     // 10 second timeout\n)",{"id":2524,"title":2525,"titles":2526,"content":103,"level":129},"/v1.0.6/learn/quickstart#try-different-synapses","Try Different Synapses",[1522],{"id":2528,"title":2529,"titles":2530,"content":2531,"level":143},"/v1.0.6/learn/quickstart#binary-decision","Binary Decision",[1522,2525],"validator, _ := zyn.Binary(\"Is this a valid email address?\", provider)\nisValid, _ := validator.Fire(ctx, session, \"user@example.com\")\n// isValid = true",{"id":2533,"title":2534,"titles":2535,"content":2536,"level":143},"/v1.0.6/learn/quickstart#text-transformation","Text Transformation",[1522,2525],"translator, _ := zyn.Transform(\"Translate to Spanish\", provider)\nspanish, _ := translator.Fire(ctx, session, \"Hello, how are you?\")\n// spanish = \"Hola, ¿cómo estás?\"",{"id":2538,"title":2539,"titles":2540,"content":2541,"level":143},"/v1.0.6/learn/quickstart#data-extraction","Data Extraction",[1522,2525],"type Contact struct {\n    Name  string `json:\"name\"`\n    Email string `json:\"email\"`\n}\n\nfunc (c Contact) Validate() error {\n    if c.Email == \"\" {\n        return fmt.Errorf(\"email required\")\n    }\n    return nil\n}\n\nextractor, _ := zyn.Extract[Contact](\"contact information\", provider)\ncontact, _ := extractor.Fire(ctx, session, \"John Doe at john@example.com\")\n// contact = Contact{Name: \"John Doe\", Email: \"john@example.com\"}",{"id":2543,"title":2493,"titles":2544,"content":2545,"level":129},"/v1.0.6/learn/quickstart#next-steps",[1522],"Core Concepts - Understand synapses, sessions, and providersArchitecture - How zyn works under the hoodProviders Guide - Configure different LLM providers html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}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 pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .soy-K, html code.shiki .soy-K{--shiki-default:#BBBBBB}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .skxcq, html code.shiki .skxcq{--shiki-default:var(--shiki-builtin)}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}",{"id":2547,"title":1528,"titles":2548,"content":2549,"level":111},"/v1.0.6/learn/concepts",[],"Understanding synapses, sessions, and providers",{"id":2551,"title":1528,"titles":2552,"content":2553,"level":111},"/v1.0.6/learn/concepts#core-concepts",[],"zyn is built around three core concepts: Synapses, Sessions, and Providers.",{"id":2555,"title":1068,"titles":2556,"content":2557,"level":129},"/v1.0.6/learn/concepts#synapses",[1528],"A synapse is a typed unit of LLM interaction. Each synapse type handles a specific pattern:",{"id":2559,"title":2560,"titles":2561,"content":2562,"level":143},"/v1.0.6/learn/concepts#decision-synapses","Decision Synapses",[1528,1068],"SynapsePurposeInputOutputBinaryYes/no decisionsstringboolClassificationCategorize into classesstringstringRankingOrder items by criteriastringstringSentimentAnalyze emotional tonestringSentimentResult",{"id":2564,"title":2565,"titles":2566,"content":2567,"level":143},"/v1.0.6/learn/concepts#transformation-synapses","Transformation Synapses",[1528,1068],"SynapsePurposeInputOutputExtract[T]Extract structured datastringTTransformTransform textstringstringAnalyze[T]Analyze structured dataTstringConvert[T,U]Convert between typesTU",{"id":2569,"title":2570,"titles":2571,"content":2572,"level":143},"/v1.0.6/learn/concepts#creating-synapses","Creating Synapses",[1528,1068],"All synapses follow the same pattern: // Constructor: task description + provider + options\nsynapse, err := zyn.Binary(\"Is this valid?\", provider, options...)\n\n// Fire: context + session + input\nresult, err := synapse.Fire(ctx, session, \"input text\")",{"id":2574,"title":2575,"titles":2576,"content":2577,"level":143},"/v1.0.6/learn/concepts#the-validator-interface","The Validator Interface",[1528,1068],"Custom types used with Extract, Analyze, or Convert must implement Validator: type Validator interface {\n    Validate() error\n} This ensures LLM outputs are validated before being returned: type Order struct {\n    ID     string  `json:\"id\"`\n    Amount float64 `json:\"amount\"`\n}\n\nfunc (o Order) Validate() error {\n    if o.ID == \"\" {\n        return fmt.Errorf(\"order ID required\")\n    }\n    if o.Amount \u003C= 0 {\n        return fmt.Errorf(\"amount must be positive\")\n    }\n    return nil\n}",{"id":2579,"title":1073,"titles":2580,"content":2581,"level":129},"/v1.0.6/learn/concepts#sessions",[1528],"Sessions manage conversation context across multiple synapse calls.",{"id":2583,"title":2584,"titles":2585,"content":2586,"level":143},"/v1.0.6/learn/concepts#why-sessions","Why Sessions?",[1528,1073],"LLMs are stateless - each call is independent. Sessions maintain history so later calls can reference earlier context: session := zyn.NewSession()\n\n// First call\nclassifier.Fire(ctx, session, \"I love this product!\")\n// Session now contains: user message + assistant response\n\n// Second call sees the history\nfollowup.Fire(ctx, session, \"Was my previous statement positive?\")\n// LLM can answer \"Yes\" because it sees the previous exchange",{"id":2588,"title":2589,"titles":2590,"content":2591,"level":143},"/v1.0.6/learn/concepts#session-lifecycle","Session Lifecycle",[1528,1073],"┌─────────────────────────────────────────────────────────────┐\n│                        Session                               │\n├─────────────────────────────────────────────────────────────┤\n│  Messages: []Message                                         │\n│  ┌─────────────┐ ┌─────────────┐ ┌─────────────┐           │\n│  │ User: ...   │ │ Assistant:  │ │ User: ...   │  ...      │\n│  │             │ │ ...         │ │             │           │\n│  └─────────────┘ └─────────────┘ └─────────────┘           │\n├─────────────────────────────────────────────────────────────┤\n│  LastUsage: *TokenUsage (from most recent call)             │\n└─────────────────────────────────────────────────────────────┘",{"id":2593,"title":2594,"titles":2595,"content":2596,"level":143},"/v1.0.6/learn/concepts#session-operations","Session Operations",[1528,1073],"session := zyn.NewSession()\n\n// Basic operations\nmessages := session.Messages()  // Get all messages\ncount := session.Len()          // Number of messages\nsession.Clear()                 // Remove all messages\n\n// Message manipulation\nmsg, _ := session.At(0)         // Get message at index\nsession.Remove(0)               // Remove message at index\nsession.Insert(0, msg)          // Insert at index\nsession.Replace(0, msg)         // Replace at index\n\n// Bulk operations\nsession.Prune(5)                // Remove last 5 message pairs (10 messages)\nsession.Truncate(2, 2)          // Keep first 2 and last 2\nsession.SetMessages(msgs)       // Replace entire history\n\n// Token tracking\nusage := session.LastUsage()    // Token usage from last call",{"id":2598,"title":2599,"titles":2600,"content":2601,"level":143},"/v1.0.6/learn/concepts#transactional-updates","Transactional Updates",[1528,1073],"Sessions update atomically - messages are only added after successful calls: session := zyn.NewSession()\nsynapse.Fire(ctx, session, \"input\")  // Fails after retries\n\n// Session is unchanged - no partial state\nassert(session.Len() == 0)",{"id":2603,"title":1555,"titles":2604,"content":2605,"level":129},"/v1.0.6/learn/concepts#providers",[1528],"Providers connect synapses to LLM APIs.",{"id":2607,"title":2608,"titles":2609,"content":2610,"level":143},"/v1.0.6/learn/concepts#provider-interface","Provider Interface",[1528,1555],"type Provider interface {\n    Call(ctx context.Context, messages []Message, temperature float32) (*ProviderResponse, error)\n    Name() string\n}",{"id":2612,"title":2613,"titles":2614,"content":2615,"level":143},"/v1.0.6/learn/concepts#available-providers","Available Providers",[1528,1555],"OpenAI (production): import \"github.com/zoobz-io/zyn/openai\"\n\nprovider := openai.New(openai.Config{\n    APIKey: os.Getenv(\"OPENAI_API_KEY\"),\n    Model:  \"gpt-4o\",  // Optional, defaults to gpt-3.5-turbo\n}) Mock (testing): provider := zyn.NewMockProviderWithResponse(`{\n    \"decision\": true,\n    \"confidence\": 0.95,\n    \"reasoning\": [\"Valid format\"]\n}`)",{"id":2617,"title":2618,"titles":2619,"content":2620,"level":143},"/v1.0.6/learn/concepts#temperature","Temperature",[1528,1555],"Temperature controls response randomness. Each synapse has a default temperature, but you can override it per-request via the input struct: // Set temperature via input struct\ninput := zyn.BinaryInput{\n    Subject:     \"test@example.com\",\n    Temperature: 0.1,  // Override default\n}\nresult, _ := synapse.FireWithInput(ctx, session, input)\n\n// Default temperatures by synapse type:\n// Binary, Extract, Convert: 0.1 (deterministic)\n// Sentiment, Ranking, Analyze: 0.2 (analytical)\n// Classification, Transform: 0.3 (creative)",{"id":2622,"title":2623,"titles":2624,"content":2625,"level":129},"/v1.0.6/learn/concepts#putting-it-together","Putting It Together",[1528],"// Provider connects to LLM\nprovider := openai.New(openai.Config{APIKey: key})\n\n// Synapse defines the task\nclassifier, _ := zyn.Classification(\n    \"Classify support ticket priority\",\n    []string{\"low\", \"medium\", \"high\", \"critical\"},\n    provider,\n    zyn.WithRetry(3),\n)\n\n// Session maintains context\nsession := zyn.NewSession()\n\n// Fire executes the task\npriority, _ := classifier.Fire(ctx, session, \"Server is down!\")\n// priority = \"critical\"\n\n// Session now has context for follow-up calls",{"id":2627,"title":2493,"titles":2628,"content":2629,"level":129},"/v1.0.6/learn/concepts#next-steps",[1528],"Architecture - How zyn works internallyProviders Guide - Provider configurationSessions Guide - Advanced session patterns html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}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 pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}",{"id":2631,"title":1535,"titles":2632,"content":2633,"level":111},"/v1.0.6/learn/architecture",[],"How zyn works under the hood",{"id":2635,"title":1535,"titles":2636,"content":2637,"level":111},"/v1.0.6/learn/architecture#architecture",[],"Understanding how zyn works internally.",{"id":2639,"title":2640,"titles":2641,"content":2642,"level":129},"/v1.0.6/learn/architecture#system-overview","System Overview",[1535],"┌─────────────────────────────────────────────────────────────────────┐\n│                           Application                                │\n│                                                                      │\n│    synapse.Fire(ctx, session, input)                                │\n└─────────────────────┬───────────────────────────────────────────────┘\n                      │\n                      ▼\n┌─────────────────────────────────────────────────────────────────────┐\n│                            Synapse                                   │\n│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐                 │\n│  │   Prompt    │  │   Schema    │  │  Validator  │                 │\n│  │  Generator  │  │  Generator  │  │             │                 │\n│  └─────────────┘  └─────────────┘  └─────────────┘                 │\n└─────────────────────┬───────────────────────────────────────────────┘\n                      │\n                      ▼\n┌─────────────────────────────────────────────────────────────────────┐\n│                         Service Layer                                │\n│  ┌─────────────────────────────────────────────────────────────┐   │\n│  │                      pipz Pipeline                           │   │\n│  │  ┌────────┐ ┌─────────┐ ┌──────────┐ ┌─────────┐           │   │\n│  │  │ Retry  │→│ Timeout │→│ Circuit  │→│  Rate   │→ ...      │   │\n│  │  │        │ │         │ │ Breaker  │ │ Limiter │           │   │\n│  │  └────────┘ └─────────┘ └──────────┘ └─────────┘           │   │\n│  └─────────────────────────────────────────────────────────────┘   │\n└─────────────────────┬───────────────────────────────────────────────┘\n                      │\n                      ▼\n┌─────────────────────────────────────────────────────────────────────┐\n│                           Provider                                   │\n│  ┌─────────────────────────────────────────────────────────────┐   │\n│  │                     HTTP Client                              │   │\n│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │   │\n│  │  │   Request   │  │   Response  │  │    Token    │         │   │\n│  │  │   Builder   │  │   Parser    │  │   Counter   │         │   │\n│  │  └─────────────┘  └─────────────┘  └─────────────┘         │   │\n│  └─────────────────────────────────────────────────────────────┘   │\n└─────────────────────┬───────────────────────────────────────────────┘\n                      │\n                      ▼\n┌─────────────────────────────────────────────────────────────────────┐\n│                          LLM API                                     │\n│                   (OpenAI, Anthropic, etc.)                         │\n└─────────────────────────────────────────────────────────────────────┘",{"id":2644,"title":2645,"titles":2646,"content":103,"level":129},"/v1.0.6/learn/architecture#request-flow","Request Flow",[1535],{"id":2648,"title":2649,"titles":2650,"content":2651,"level":143},"/v1.0.6/learn/architecture#_1-prompt-construction","1. Prompt Construction",[1535,2645],"When Fire() is called, the synapse builds a structured prompt: // User calls\nresult, _ := classifier.Fire(ctx, session, \"URGENT: Server down!\")\n\n// Internally, synapse builds:\n{\n    \"task\": \"What type of email is this?\",\n    \"input\": \"URGENT: Server down!\",\n    \"categories\": [\"spam\", \"urgent\", \"newsletter\", \"personal\"],\n    \"schema\": { /* JSON schema for response */ }\n}",{"id":2653,"title":2654,"titles":2655,"content":2656,"level":143},"/v1.0.6/learn/architecture#_2-message-assembly","2. Message Assembly",[1535,2645],"The prompt is combined with session history: Messages sent to provider:\n1. [system] Task description + schema + instructions\n2. [user]   Previous user message (from session)\n3. [assistant] Previous response (from session)\n4. [user]   Current input",{"id":2658,"title":2659,"titles":2660,"content":2661,"level":143},"/v1.0.6/learn/architecture#_3-pipeline-execution","3. Pipeline Execution",[1535,2645],"The request flows through the pipz pipeline: Request → Retry → Timeout → CircuitBreaker → RateLimit → Provider\n                                                              │\nResponse ← Parse ← Validate ←─────────────────────────────────┘",{"id":2663,"title":2664,"titles":2665,"content":2666,"level":143},"/v1.0.6/learn/architecture#_4-response-processing","4. Response Processing",[1535,2645],"// Provider returns raw JSON\n{\"primary\": \"urgent\", \"confidence\": 0.95, \"reasoning\": [...]}\n\n// Synapse:\n// 1. Parses JSON into typed struct\n// 2. Calls Validate() if applicable\n// 3. Extracts the primary result\n// 4. Updates session with user message + assistant response\n// 5. Returns typed result",{"id":2668,"title":2669,"titles":2670,"content":103,"level":129},"/v1.0.6/learn/architecture#component-details","Component Details",[1535],{"id":2672,"title":2673,"titles":2674,"content":2675,"level":143},"/v1.0.6/learn/architecture#prompt-generation","Prompt Generation",[1535,2669],"Each synapse type generates specific prompts: SynapsePrompt StructureBinaryTask + input + boolean schemaClassificationTask + categories + input + category schemaExtractTTask + input + struct schema from TTransformTask + input + string output schemaAnalyzeTTask + struct input + analysis schemaConvertT,UTask + input schema (T) + output schema (U)",{"id":2677,"title":2678,"titles":2679,"content":2680,"level":143},"/v1.0.6/learn/architecture#schema-generation","Schema Generation",[1535,2669],"Schemas are generated from Go types using reflection: type Contact struct {\n    Name  string `json:\"name\"`\n    Email string `json:\"email\" description:\"Valid email address\"`\n}\n\n// Generates JSON Schema:\n{\n    \"type\": \"object\",\n    \"properties\": {\n        \"name\": {\"type\": \"string\"},\n        \"email\": {\"type\": \"string\", \"description\": \"Valid email address\"}\n    },\n    \"required\": [\"name\", \"email\"]\n}",{"id":2682,"title":2683,"titles":2684,"content":2685,"level":143},"/v1.0.6/learn/architecture#service-layer","Service Layer",[1535,2669],"The Service[T] generic handles: Building the complete requestExecuting through the pipelineParsing and validating responsesManaging session updates type Service[T Validator] struct {\n    provider Provider\n    prompt   PromptBuilder\n    pipeline pipz.Chainable[*SynapseRequest]\n    hooks    HookEmitter\n}",{"id":2687,"title":2688,"titles":2689,"content":2690,"level":143},"/v1.0.6/learn/architecture#observability-hooks","Observability Hooks",[1535,2669],"Hooks fire at key points via capitan: ┌──────────────────┐\n│  RequestStarted  │ → Before pipeline execution\n└────────┬─────────┘\n         │\n┌────────▼─────────┐\n│ ProviderStarted  │ → Before HTTP call\n└────────┬─────────┘\n         │\n┌────────▼─────────┐\n│ProviderCompleted │ → After successful HTTP call (includes tokens)\n└────────┬─────────┘   OR\n┌────────▼─────────┐\n│  ProviderFailed  │ → After HTTP failure\n└────────┬─────────┘\n         │\n┌────────▼─────────┐\n│RequestCompleted  │ → After successful parse/validate\n└──────────────────┘   OR\n┌──────────────────┐\n│  RequestFailed   │ → After pipeline exhaustion\n└──────────────────┘   OR\n┌──────────────────┐\n│ResponseParseFailed│ → After parse/validation error\n└──────────────────┘",{"id":2692,"title":2693,"titles":2694,"content":103,"level":129},"/v1.0.6/learn/architecture#type-safety-guarantees","Type Safety Guarantees",[1535],{"id":2696,"title":2697,"titles":2698,"content":2699,"level":143},"/v1.0.6/learn/architecture#compile-time","Compile-Time",[1535,2693],"Generic synapses enforce input/output typesValidator interface required for custom typesOption functions are type-checked",{"id":2701,"title":2702,"titles":2703,"content":2704,"level":143},"/v1.0.6/learn/architecture#runtime","Runtime",[1535,2693],"JSON schema validation on LLM responsesValidate() called on parsed structsSession operations bounds-checked",{"id":2706,"title":2493,"titles":2707,"content":2708,"level":129},"/v1.0.6/learn/architecture#next-steps",[1535],"Reliability Guide - Configure pipz patternsObservability Guide - Set up hooksTesting Guide - Test strategies html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}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 pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}",{"id":2710,"title":1548,"titles":2711,"content":2712,"level":111},"/v1.0.6/guides/installation",[],"Installing and configuring zyn",{"id":2714,"title":1548,"titles":2715,"content":103,"level":111},"/v1.0.6/guides/installation#installation",[],{"id":2717,"title":2718,"titles":2719,"content":2720,"level":129},"/v1.0.6/guides/installation#requirements","Requirements",[1548],"Go 1.21 or laterAn LLM provider API key (OpenAI, Anthropic, etc.)",{"id":2722,"title":619,"titles":2723,"content":2507,"level":129},"/v1.0.6/guides/installation#install",[1548],{"id":2725,"title":2726,"titles":2727,"content":103,"level":129},"/v1.0.6/guides/installation#provider-setup","Provider Setup",[1548],{"id":2729,"title":2730,"titles":2731,"content":2732,"level":143},"/v1.0.6/guides/installation#openai","OpenAI",[1548,2726],"import \"github.com/zoobz-io/zyn/openai\"\n\nprovider := openai.New(openai.Config{\n    APIKey: os.Getenv(\"OPENAI_API_KEY\"),\n    Model:  \"gpt-4o\",  // Optional, defaults to \"gpt-3.5-turbo\"\n}) Available models: gpt-4o - Most capablegpt-4o-mini - Fast and cost-effectivegpt-3.5-turbo - Default, cost-effective",{"id":2734,"title":2735,"titles":2736,"content":2737,"level":143},"/v1.0.6/guides/installation#anthropic","Anthropic",[1548,2726],"import \"github.com/zoobz-io/zyn/anthropic\"\n\nprovider := anthropic.New(anthropic.Config{\n    APIKey: os.Getenv(\"ANTHROPIC_API_KEY\"),\n    Model:  \"claude-3-5-sonnet-20241022\",  // Optional, defaults to \"claude-sonnet-4-20250514\"\n})",{"id":2739,"title":2740,"titles":2741,"content":2742,"level":143},"/v1.0.6/guides/installation#google-gemini","Google Gemini",[1548,2726],"import \"github.com/zoobz-io/zyn/gemini\"\n\nprovider := gemini.New(gemini.Config{\n    APIKey: os.Getenv(\"GEMINI_API_KEY\"),\n    Model:  \"gemini-1.5-flash\",\n})",{"id":2744,"title":2745,"titles":2746,"content":2747,"level":129},"/v1.0.6/guides/installation#environment-variables","Environment Variables",[1548],"Recommended setup: # .env or shell profile\nexport OPENAI_API_KEY=\"sk-...\"\nexport ANTHROPIC_API_KEY=\"sk-ant-...\"\nexport GEMINI_API_KEY=\"...\"",{"id":2749,"title":2750,"titles":2751,"content":2752,"level":129},"/v1.0.6/guides/installation#verify-installation","Verify Installation",[1548],"package main\n\nimport (\n    \"context\"\n    \"fmt\"\n    \"os\"\n\n    \"github.com/zoobz-io/zyn\"\n    \"github.com/zoobz-io/zyn/openai\"\n)\n\nfunc main() {\n    provider := openai.New(openai.Config{\n        APIKey: os.Getenv(\"OPENAI_API_KEY\"),\n    })\n\n    synapse, err := zyn.Binary(\"Is this a test?\", provider)\n    if err != nil {\n        panic(err)\n    }\n\n    session := zyn.NewSession()\n    result, err := synapse.Fire(context.Background(), session, \"This is a test\")\n    if err != nil {\n        panic(err)\n    }\n\n    fmt.Println(\"Success:\", result)\n}",{"id":2754,"title":2493,"titles":2755,"content":2756,"level":129},"/v1.0.6/guides/installation#next-steps",[1548],"Providers Guide - Advanced provider configurationQuickstart - Build your first synapse html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}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 pre.shiki code .soy-K, html code.shiki .soy-K{--shiki-default:#BBBBBB}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .skxcq, html code.shiki .skxcq{--shiki-default:var(--shiki-builtin)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}",{"id":2758,"title":1555,"titles":2759,"content":2760,"level":111},"/v1.0.6/guides/providers",[],"Configuring and using LLM providers",{"id":2762,"title":1555,"titles":2763,"content":2605,"level":111},"/v1.0.6/guides/providers#providers",[],{"id":2765,"title":2608,"titles":2766,"content":2767,"level":129},"/v1.0.6/guides/providers#provider-interface",[1555],"All providers implement: type Provider interface {\n    Call(ctx context.Context, messages []Message, temperature float32) (*ProviderResponse, error)\n    Name() string  // Returns provider identifier (e.g., \"openai\", \"anthropic\")\n}",{"id":2769,"title":2770,"titles":2771,"content":103,"level":129},"/v1.0.6/guides/providers#openai-provider","OpenAI Provider",[1555],{"id":2773,"title":2774,"titles":2775,"content":2776,"level":143},"/v1.0.6/guides/providers#basic-configuration","Basic Configuration",[1555,2770],"import \"github.com/zoobz-io/zyn/openai\"\n\nprovider := openai.New(openai.Config{\n    APIKey: os.Getenv(\"OPENAI_API_KEY\"),\n})",{"id":2778,"title":2779,"titles":2780,"content":2781,"level":143},"/v1.0.6/guides/providers#full-configuration","Full Configuration",[1555,2770],"provider := openai.New(openai.Config{\n    APIKey:  os.Getenv(\"OPENAI_API_KEY\"),\n    Model:   \"gpt-4o\",           // Model selection\n    BaseURL: \"https://...\",      // Custom endpoint (Azure, proxies)\n    OrgID:   \"org-...\",          // Organization ID\n})",{"id":2783,"title":2784,"titles":2785,"content":2786,"level":143},"/v1.0.6/guides/providers#model-selection","Model Selection",[1555,2770],"ModelSpeedCostBest Forgpt-4oMediumHighComplex reasoninggpt-4o-miniFastLowMost use casesgpt-4-turboMediumMediumLarge context",{"id":2788,"title":2789,"titles":2790,"content":2791,"level":129},"/v1.0.6/guides/providers#anthropic-provider","Anthropic Provider",[1555],"import \"github.com/zoobz-io/zyn/anthropic\"\n\nprovider := anthropic.New(anthropic.Config{\n    APIKey: os.Getenv(\"ANTHROPIC_API_KEY\"),\n    Model:  \"claude-3-5-sonnet-20241022\",\n})",{"id":2793,"title":2784,"titles":2794,"content":2795,"level":143},"/v1.0.6/guides/providers#model-selection-1",[1555,2789],"ModelSpeedCostBest Forclaude-3-5-sonnet-20241022FastMediumBalanced performanceclaude-3-opus-20240229SlowHighComplex analysisclaude-3-haiku-20240307Very FastLowSimple tasks",{"id":2797,"title":2798,"titles":2799,"content":2742,"level":129},"/v1.0.6/guides/providers#gemini-provider","Gemini Provider",[1555],{"id":2801,"title":2802,"titles":2803,"content":2804,"level":129},"/v1.0.6/guides/providers#temperature-control","Temperature Control",[1555],"Temperature affects response randomness. Each synapse type has a default temperature, but you can override it per-request via the input struct: // Set temperature via input struct\ninput := zyn.BinaryInput{\n    Subject:     \"test@example.com\",\n    Temperature: 0.1,  // Override default\n}\nresult, err := synapse.FireWithInput(ctx, session, input)\n\n// Default temperatures by synapse type:\n// Binary, Extraction, Convert:   0.1 (DefaultTemperatureDeterministic)\n// Sentiment, Ranking, Analyze:   0.2 (DefaultTemperatureAnalytical)\n// Classification, Transform:     0.3 (DefaultTemperatureCreative) Guidelines: Precision tasks (extraction, conversion) → 0.1Analytical tasks (sentiment, ranking) → 0.2Creative tasks (transform, classification) → 0.3",{"id":2806,"title":2807,"titles":2808,"content":2809,"level":129},"/v1.0.6/guides/providers#mock-provider","Mock Provider",[1555],"For testing without API calls: // Fixed response\nprovider := zyn.NewMockProviderWithResponse(`{\n    \"decision\": true,\n    \"confidence\": 0.95,\n    \"reasoning\": [\"Valid\"]\n}`)\n\n// Dynamic response\nprovider := zyn.NewMockProviderWithCallback(func(prompt string, temp float32) (string, error) {\n    return `{\"decision\": true, \"confidence\": 0.9, \"reasoning\": [\"ok\"]}`, nil\n})\n\n// Error simulation\nprovider := zyn.NewMockProviderWithError(\"rate limit exceeded\")",{"id":2811,"title":2812,"titles":2813,"content":2814,"level":129},"/v1.0.6/guides/providers#custom-providers","Custom Providers",[1555],"Implement the Provider interface: type CustomProvider struct {\n    client *http.Client\n}\n\nfunc (p *CustomProvider) Call(ctx context.Context, messages []zyn.Message, temperature float32) (*zyn.ProviderResponse, error) {\n    // Build request from messages\n    // Call your LLM API\n    // Return response with content and usage\n\n    return &zyn.ProviderResponse{\n        Content: responseJSON,\n        Usage: zyn.TokenUsage{\n            Prompt:     promptTokens,\n            Completion: completionTokens,\n            Total:      totalTokens,\n        },\n    }, nil\n}\n\nfunc (p *CustomProvider) Name() string {\n    return \"custom\"\n}",{"id":2816,"title":2817,"titles":2818,"content":2819,"level":129},"/v1.0.6/guides/providers#provider-selection-strategy","Provider Selection Strategy",[1555],"// Primary + fallback pattern\nprimaryProvider := openai.New(openai.Config{APIKey: key1})\nfallbackProvider := anthropic.New(anthropic.Config{APIKey: key2})\n\nsynapse, _ := zyn.Binary(\"question\", primaryProvider,\n    zyn.WithFallback(fallbackSynapse),\n)",{"id":2821,"title":2493,"titles":2822,"content":2823,"level":129},"/v1.0.6/guides/providers#next-steps",[1555],"Sessions Guide - Managing conversation contextReliability Guide - Retry, timeout, circuit breaker html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}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 pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}",{"id":2825,"title":1073,"titles":2826,"content":2827,"level":111},"/v1.0.6/guides/sessions",[],"Managing conversation context with sessions",{"id":2829,"title":1073,"titles":2830,"content":2831,"level":111},"/v1.0.6/guides/sessions#sessions",[],"Sessions manage conversation context across synapse calls.",{"id":2833,"title":2584,"titles":2834,"content":2835,"level":129},"/v1.0.6/guides/sessions#why-sessions",[1073],"LLMs are stateless. Sessions maintain history so synapses can reference previous interactions: session := zyn.NewSession()\n\n// First call\nclassifier.Fire(ctx, session, \"I love this product!\")\n// Session: [{user: \"I love...\"}, {assistant: {positive...}}]\n\n// Second call sees history\nfollowup.Fire(ctx, session, \"Was that positive or negative?\")\n// LLM can answer correctly from context",{"id":2837,"title":2838,"titles":2839,"content":2840,"level":129},"/v1.0.6/guides/sessions#basic-operations","Basic Operations",[1073],"session := zyn.NewSession()\n\n// Check state\nmessages := session.Messages()  // []Message\ncount := session.Len()          // int\nisEmpty := session.Len() == 0   // bool\n\n// Clear all\nsession.Clear()",{"id":2842,"title":2843,"titles":2844,"content":2845,"level":129},"/v1.0.6/guides/sessions#message-access","Message Access",[1073],"// Get message at index\nmsg, err := session.At(0)\n\n// Message structure\ntype Message struct {\n    Role    Role    // RoleUser, RoleAssistant, RoleSystem\n    Content string\n}",{"id":2847,"title":2848,"titles":2849,"content":2850,"level":129},"/v1.0.6/guides/sessions#message-manipulation","Message Manipulation",[1073],"// Remove at index\nerr := session.Remove(2)\n\n// Replace at index\nerr := session.Replace(1, zyn.Message{\n    Role:    zyn.RoleAssistant,\n    Content: \"Updated response\",\n})\n\n// Insert at index\nerr := session.Insert(0, zyn.Message{\n    Role:    zyn.RoleSystem,\n    Content: \"You are a helpful assistant\",\n})\n\n// Append (used internally by synapses)\nsession.Append(zyn.RoleUser, \"Hello\")",{"id":2852,"title":2853,"titles":2854,"content":103,"level":129},"/v1.0.6/guides/sessions#bulk-operations","Bulk Operations",[1073],{"id":2856,"title":2857,"titles":2858,"content":2859,"level":143},"/v1.0.6/guides/sessions#prune","Prune",[1073,2853],"Remove the last N messages: session.Prune(4)  // Remove last 4 messages Useful for context window management when sessions grow large.",{"id":2861,"title":2862,"titles":2863,"content":2864,"level":143},"/v1.0.6/guides/sessions#truncate","Truncate",[1073,2853],"Keep first N and last M messages: session.Truncate(2, 2)  // Keep first 2, last 2, remove middle Useful for preserving initial context while keeping recent history.",{"id":2866,"title":2867,"titles":2868,"content":2869,"level":143},"/v1.0.6/guides/sessions#replace-all","Replace All",[1073,2853],"session.SetMessages([]zyn.Message{\n    {Role: zyn.RoleUser, Content: \"Summarized context\"},\n    {Role: zyn.RoleAssistant, Content: \"Acknowledged\"},\n})",{"id":2871,"title":2872,"titles":2873,"content":2874,"level":129},"/v1.0.6/guides/sessions#token-tracking","Token Tracking",[1073],"Sessions track token usage from the last call: synapse.Fire(ctx, session, \"input\")\n\nif usage := session.LastUsage(); usage != nil {\n    fmt.Printf(\"Tokens: prompt=%d completion=%d total=%d\\n\",\n        usage.Prompt, usage.Completion, usage.Total)\n}",{"id":2876,"title":2877,"titles":2878,"content":103,"level":129},"/v1.0.6/guides/sessions#context-strategies","Context Strategies",[1073],{"id":2880,"title":2881,"titles":2882,"content":2883,"level":143},"/v1.0.6/guides/sessions#sliding-window","Sliding Window",[1073,2877],"Keep only the last N exchanges: func slidingWindow(session *zyn.Session, maxMessages int) {\n    if session.Len() > maxMessages {\n        excess := session.Len() - maxMessages\n        session.Prune(excess)\n    }\n}\n\n// Usage\nsynapse.Fire(ctx, session, input)\nslidingWindow(session, 20)  // Keep last 20 messages",{"id":2885,"title":2886,"titles":2887,"content":2888,"level":143},"/v1.0.6/guides/sessions#summarization","Summarization",[1073,2877],"Replace old messages with a summary: func summarizeOldContext(ctx context.Context, session *zyn.Session, summarizer *zyn.TransformSynapse) {\n    if session.Len() \u003C 20 {\n        return\n    }\n\n    // Get old messages\n    old := session.Messages()[:10]\n    oldText := formatMessages(old)\n\n    // Summarize\n    summary, _ := summarizer.Fire(ctx, zyn.NewSession(), oldText)\n\n    // Replace with summary\n    session.Truncate(0, 10)  // Keep last 10\n    session.Insert(0, zyn.Message{\n        Role:    zyn.RoleSystem,\n        Content: \"Previous context summary: \" + summary,\n    })\n}",{"id":2890,"title":2891,"titles":2892,"content":2893,"level":143},"/v1.0.6/guides/sessions#selective-pruning","Selective Pruning",[1073,2877],"Remove low-value exchanges: func pruneByRelevance(session *zyn.Session, topic string) {\n    messages := session.Messages()\n    relevant := []zyn.Message{}\n\n    for _, msg := range messages {\n        if isRelevant(msg.Content, topic) {\n            relevant = append(relevant, msg)\n        }\n    }\n\n    session.SetMessages(relevant)\n}",{"id":2895,"title":2896,"titles":2897,"content":2898,"level":129},"/v1.0.6/guides/sessions#multi-synapse-workflows","Multi-Synapse Workflows",[1073],"Sessions enable complex workflows where context flows between different synapses: session := zyn.NewSession()\n\n// Step 1: Extract data\nextractor, _ := zyn.Extract[Customer](\"customer info\", provider)\ncustomer, _ := extractor.Fire(ctx, session, rawEmail)\n\n// Step 2: Classify (sees extraction context)\nclassifier, _ := zyn.Classification(\"urgency\", []string{\"low\", \"high\"}, provider)\nurgency, _ := classifier.Fire(ctx, session, customer.Issue)\n\n// Step 3: Generate response (sees both previous steps)\nresponder, _ := zyn.Transform(\"write response\", provider)\nresponse, _ := responder.Fire(ctx, session, \"Respond appropriately\")",{"id":2900,"title":2599,"titles":2901,"content":2902,"level":129},"/v1.0.6/guides/sessions#transactional-updates",[1073],"Sessions only update after successful calls: session := zyn.NewSession()\ninitialLen := session.Len()  // 0\n\n_, err := synapse.Fire(ctx, session, \"input\")\nif err != nil {\n    // Session unchanged\n    assert(session.Len() == initialLen)\n} This prevents retry attempts from corrupting session state.",{"id":2904,"title":2905,"titles":2906,"content":2907,"level":129},"/v1.0.6/guides/sessions#prompt-caching","Prompt Caching",[1073],"Sessions leverage provider-side caching automatically: Full history sent with each callProviders cache repeated prefixes (5min-1hr TTL)Subsequent calls reuse cache, reducing costs 60-90%No configuration needed",{"id":2909,"title":2910,"titles":2911,"content":2912,"level":129},"/v1.0.6/guides/sessions#independent-sessions","Independent Sessions",[1073],"Different conversations need separate sessions: // Each user gets their own session\nuserSessions := make(map[string]*zyn.Session)\n\nfunc handleRequest(userID string, input string) {\n    session, ok := userSessions[userID]\n    if !ok {\n        session = zyn.NewSession()\n        userSessions[userID] = session\n    }\n\n    synapse.Fire(ctx, session, input)\n}",{"id":2914,"title":2493,"titles":2915,"content":2916,"level":129},"/v1.0.6/guides/sessions#next-steps",[1073],"Reliability Guide - Retry, timeout, circuit breakerMulti-Turn Cookbook - Advanced patterns html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}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 pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .scyPU, html code.shiki .scyPU{--shiki-default:var(--shiki-placeholder)}html pre.shiki code .suWN2, html code.shiki .suWN2{--shiki-default:var(--shiki-tag)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .skxcq, html code.shiki .skxcq{--shiki-default:var(--shiki-builtin)}",{"id":2918,"title":1109,"titles":2919,"content":2920,"level":111},"/v1.0.6/guides/reliability",[],"Retry, timeout, circuit breaker, and rate limiting",{"id":2922,"title":1109,"titles":2923,"content":2924,"level":111},"/v1.0.6/guides/reliability#reliability",[],"zyn integrates with pipz for production-grade reliability patterns.",{"id":2926,"title":2927,"titles":2928,"content":2929,"level":129},"/v1.0.6/guides/reliability#available-options","Available Options",[1109],"synapse, _ := zyn.Binary(\"question\", provider,\n    zyn.WithRetry(3),                              // Retry on failure\n    zyn.WithBackoff(3, 100*time.Millisecond),      // Retry with backoff\n    zyn.WithTimeout(10*time.Second),               // Timeout protection\n    zyn.WithCircuitBreaker(5, 30*time.Second),     // Circuit breaker\n    zyn.WithRateLimit(10, 100),                    // Rate limiting\n    zyn.WithFallback(backupSynapse),               // Fallback synapse\n    zyn.WithErrorHandler(errorPipeline),           // Custom error handling\n)",{"id":2931,"title":2932,"titles":2933,"content":2934,"level":129},"/v1.0.6/guides/reliability#retry","Retry",[1109],"Automatically retry failed calls: // Simple retry (up to 3 attempts)\nzyn.WithRetry(3)\n\n// With exponential backoff\n// Attempts with delays: 100ms, 200ms, 400ms, ...\nzyn.WithBackoff(3, 100*time.Millisecond) When to use: Transient failures (network blips)Rate limit errors (429)Provider temporary errors (503) Best practices: Keep attempts low (2-3) to avoid cost explosionUse backoff for rate limitsCombine with timeout to bound total duration",{"id":2936,"title":2937,"titles":2938,"content":2939,"level":129},"/v1.0.6/guides/reliability#timeout","Timeout",[1109],"Bound maximum execution time: zyn.WithTimeout(10 * time.Second) When to use: Always. LLM calls can hang indefinitelyUser-facing requests with latency requirementsBackground jobs with resource constraints Guidelines: Simple queries: 5-10 secondsComplex reasoning: 30-60 secondsBatch processing: longer, but always bounded",{"id":2941,"title":2942,"titles":2943,"content":2944,"level":129},"/v1.0.6/guides/reliability#circuit-breaker","Circuit Breaker",[1109],"Stop calling a failing provider: // Open after 5 failures, try again after 30 seconds\nzyn.WithCircuitBreaker(5, 30*time.Second) States: Closed - Normal operation, failures countedOpen - Fails immediately, no provider callsHalf-Open - After recovery time, tries one request When to use: Provider outagesProtecting downstream systemsCost control during failures",{"id":2946,"title":1997,"titles":2947,"content":2948,"level":129},"/v1.0.6/guides/reliability#rate-limiting",[1109],"Control request throughput: // 10 requests per second, burst of 100\nzyn.WithRateLimit(10, 100) When to use: Respecting provider rate limitsControlling costsFair resource sharing Note: Rate limiters are per-synapse. For global limits, share a rate limiter instance.",{"id":2950,"title":2951,"titles":2952,"content":2953,"level":129},"/v1.0.6/guides/reliability#fallback","Fallback",[1109],"Use a backup synapse on failure: // Create backup synapse (different provider)\nbackupSynapse, _ := zyn.Binary(\"question\", backupProvider)\n\n// Primary with fallback\nsynapse, _ := zyn.Binary(\"question\", primaryProvider,\n    zyn.WithFallback(backupSynapse),\n) Use cases: Multi-provider redundancyGraceful degradation (fall back to simpler model)A/B testing with fallback",{"id":2955,"title":1616,"titles":2956,"content":2957,"level":129},"/v1.0.6/guides/reliability#error-handling",[1109],"Custom error processing: import \"github.com/zoobz-io/pipz\"\n\n// Define identity for the error handler\nvar logErrorsID = pipz.NewIdentity(\"log-errors\", \"Logs synapse errors\")\n\nerrorHandler := pipz.Apply(logErrorsID,\n    func(ctx context.Context, e *pipz.Error[*zyn.SynapseRequest]) (*pipz.Error[*zyn.SynapseRequest], error) {\n        log.Printf(\"Synapse error: %v\", e.Err)\n        metrics.Increment(\"synapse_errors\")\n        return e, nil\n    },\n)\n\nsynapse, _ := zyn.Binary(\"question\", provider,\n    zyn.WithErrorHandler(errorHandler),\n)",{"id":2959,"title":2960,"titles":2961,"content":2962,"level":129},"/v1.0.6/guides/reliability#combining-options","Combining Options",[1109],"Options compose naturally: synapse, _ := zyn.Classification(\"classify\", categories, provider,\n    // Retry with backoff for transient failures\n    zyn.WithBackoff(3, 100*time.Millisecond),\n\n    // Timeout to bound total duration\n    zyn.WithTimeout(30*time.Second),\n\n    // Circuit breaker for provider outages\n    zyn.WithCircuitBreaker(5, 60*time.Second),\n\n    // Rate limit to stay within quotas\n    zyn.WithRateLimit(10, 50),\n\n    // Fallback to backup provider\n    zyn.WithFallback(backupSynapse),\n) Execution order: Request → RateLimit → CircuitBreaker → Timeout → Retry → Provider",{"id":2964,"title":2965,"titles":2966,"content":103,"level":129},"/v1.0.6/guides/reliability#recommended-configurations","Recommended Configurations",[1109],{"id":2968,"title":2969,"titles":2970,"content":2971,"level":143},"/v1.0.6/guides/reliability#user-facing-api","User-Facing API",[1109,2965],"zyn.WithRetry(2),\nzyn.WithTimeout(10*time.Second),\nzyn.WithCircuitBreaker(3, 30*time.Second),",{"id":2973,"title":2974,"titles":2975,"content":2976,"level":143},"/v1.0.6/guides/reliability#background-processing","Background Processing",[1109,2965],"zyn.WithBackoff(5, 500*time.Millisecond),\nzyn.WithTimeout(60*time.Second),\nzyn.WithRateLimit(5, 20),",{"id":2978,"title":2979,"titles":2980,"content":2981,"level":143},"/v1.0.6/guides/reliability#high-availability","High-Availability",[1109,2965],"zyn.WithRetry(2),\nzyn.WithTimeout(15*time.Second),\nzyn.WithCircuitBreaker(5, 30*time.Second),\nzyn.WithFallback(backupSynapse),",{"id":2983,"title":2984,"titles":2985,"content":2986,"level":129},"/v1.0.6/guides/reliability#session-behavior","Session Behavior",[1109],"Sessions are transactional with reliability options: session := zyn.NewSession()\n\n// Even with 3 retries, session only updates once on success\nsynapse, _ := zyn.Binary(\"q\", provider, zyn.WithRetry(3))\nsynapse.Fire(ctx, session, \"input\")\n\n// If all retries fail, session is unchanged\n// If any retry succeeds, session has exactly 2 messages",{"id":2988,"title":2493,"titles":2989,"content":2990,"level":129},"/v1.0.6/guides/reliability#next-steps",[1109],"Observability Guide - Monitor reliability behaviorTesting Guide - Test reliability patternspipz Documentation - Full pipeline reference html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}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 pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .scyPU, html code.shiki .scyPU{--shiki-default:var(--shiki-placeholder)}",{"id":2992,"title":1114,"titles":2993,"content":2994,"level":111},"/v1.0.6/guides/observability",[],"Monitoring LLM interactions with hooks",{"id":2996,"title":1114,"titles":2997,"content":2998,"level":111},"/v1.0.6/guides/observability#observability",[],"zyn emits capitan hooks for full visibility into LLM interactions.",{"id":3000,"title":3001,"titles":3002,"content":103,"level":129},"/v1.0.6/guides/observability#available-signals","Available Signals",[1114],{"id":3004,"title":3005,"titles":3006,"content":3007,"level":143},"/v1.0.6/guides/observability#request-lifecycle","Request Lifecycle",[1114,3001],"SignalWhenKey FieldsRequestStartedBefore pipelinerequest.id, synapse.type, inputRequestCompletedAfter successrequest.id, output, responseRequestFailedAfter pipeline failurerequest.id, errorResponseParseFailedAfter parse/validation errorrequest.id, response, error.type",{"id":3009,"title":3010,"titles":3011,"content":3012,"level":143},"/v1.0.6/guides/observability#provider-lifecycle","Provider Lifecycle",[1114,3001],"SignalWhenKey FieldsProviderCallStartedBefore HTTP callprovider, modelProviderCallCompletedAfter HTTP successprovider, tokens, duration.msProviderCallFailedAfter HTTP failureprovider, http.status.code, error",{"id":3014,"title":3015,"titles":3016,"content":3017,"level":129},"/v1.0.6/guides/observability#basic-usage","Basic Usage",[1114],"import (\n    \"github.com/zoobz-io/capitan\"\n    \"github.com/zoobz-io/zyn\"\n)\n\n// Hook into specific signals\ncapitan.Hook(zyn.RequestCompleted, func(ctx context.Context, e *capitan.Event) {\n    requestID, _ := zyn.RequestIDKey.From(e)\n    synapseType, _ := zyn.SynapseTypeKey.From(e)\n    log.Printf(\"Request %s (%s) completed\", requestID, synapseType)\n})",{"id":3019,"title":3020,"titles":3021,"content":3022,"level":129},"/v1.0.6/guides/observability#field-access","Field Access",[1114],"Use typed keys for type-safe field access: capitan.Hook(zyn.ProviderCallCompleted, func(ctx context.Context, e *capitan.Event) {\n    // Typed accessors\n    model, _ := zyn.ModelKey.From(e)\n    tokens, _ := zyn.TotalTokensKey.From(e)\n    duration, _ := zyn.DurationMsKey.From(e)\n    provider, _ := zyn.ProviderKey.From(e)\n\n    log.Printf(\"[%s] %s: %d tokens in %dms\", provider, model, tokens, duration)\n})",{"id":3024,"title":3025,"titles":3026,"content":103,"level":129},"/v1.0.6/guides/observability#available-keys","Available Keys",[1114],{"id":3028,"title":3029,"titles":3030,"content":3031,"level":143},"/v1.0.6/guides/observability#request-fields","Request Fields",[1114,3025],"zyn.RequestIDKey      // string - Unique request identifier\nzyn.SynapseTypeKey    // string - \"binary\", \"classification\", etc.\nzyn.PromptTaskKey     // string - Task description\nzyn.TemperatureKey    // float64 - Temperature setting used\nzyn.InputKey          // string - Input text\nzyn.OutputKey         // string - Parsed result (JSON)\nzyn.ResponseKey       // string - Raw LLM response\nzyn.ErrorKey          // string - Error message\nzyn.ErrorTypeKey      // string - \"parse_error\", \"validation_error\"",{"id":3033,"title":3034,"titles":3035,"content":3036,"level":143},"/v1.0.6/guides/observability#provider-fields","Provider Fields",[1114,3025],"zyn.ProviderKey              // string - \"openai\", \"anthropic\", etc.\nzyn.ModelKey                 // string - Model used\nzyn.PromptTokensKey          // int - Prompt token count\nzyn.CompletionTokensKey      // int - Completion token count\nzyn.TotalTokensKey           // int - Total token count\nzyn.DurationMsKey            // int - Call duration in ms\nzyn.HTTPStatusCodeKey        // int - HTTP status code\nzyn.ResponseIDKey            // string - Provider's response ID\nzyn.ResponseFinishReasonKey  // string - \"stop\", \"length\", etc.\nzyn.ResponseCreatedKey       // int - Response creation timestamp\nzyn.APIErrorTypeKey          // string - API error type\nzyn.APIErrorCodeKey          // string - API error code",{"id":3038,"title":3039,"titles":3040,"content":103,"level":129},"/v1.0.6/guides/observability#common-patterns","Common Patterns",[1114],{"id":3042,"title":3043,"titles":3044,"content":3045,"level":143},"/v1.0.6/guides/observability#token-usage-tracking","Token Usage Tracking",[1114,3039],"var totalTokens int64\n\ncapitan.Hook(zyn.ProviderCallCompleted, func(ctx context.Context, e *capitan.Event) {\n    tokens, _ := zyn.TotalTokensKey.From(e)\n    atomic.AddInt64(&totalTokens, int64(tokens))\n})",{"id":3047,"title":3048,"titles":3049,"content":3050,"level":143},"/v1.0.6/guides/observability#error-monitoring","Error Monitoring",[1114,3039],"capitan.Hook(zyn.RequestFailed, func(ctx context.Context, e *capitan.Event) {\n    requestID, _ := zyn.RequestIDKey.From(e)\n    err, _ := zyn.ErrorKey.From(e)\n    synapseType, _ := zyn.SynapseTypeKey.From(e)\n\n    log.Printf(\"FAILED [%s] %s: %s\", synapseType, requestID, err)\n    metrics.Increment(\"synapse_failures\", \"type\", synapseType)\n})\n\ncapitan.Hook(zyn.ResponseParseFailed, func(ctx context.Context, e *capitan.Event) {\n    errorType, _ := zyn.ErrorTypeKey.From(e)\n    response, _ := zyn.ResponseKey.From(e)\n\n    if errorType == \"parse_error\" {\n        log.Printf(\"Parse error on response: %s\", response[:100])\n    }\n})",{"id":3052,"title":3053,"titles":3054,"content":3055,"level":143},"/v1.0.6/guides/observability#latency-tracking","Latency Tracking",[1114,3039],"capitan.Hook(zyn.ProviderCallCompleted, func(ctx context.Context, e *capitan.Event) {\n    duration, _ := zyn.DurationMsKey.From(e)\n    model, _ := zyn.ModelKey.From(e)\n\n    metrics.Histogram(\"llm_latency_ms\", float64(duration), \"model\", model)\n})",{"id":3057,"title":3058,"titles":3059,"content":3060,"level":143},"/v1.0.6/guides/observability#request-correlation","Request Correlation",[1114,3039],"All signals include request.id for tracing: capitan.Hook(zyn.RequestStarted, func(ctx context.Context, e *capitan.Event) {\n    requestID, _ := zyn.RequestIDKey.From(e)\n    log.Printf(\"Starting request %s\", requestID)\n})\n\ncapitan.Hook(zyn.ProviderCallCompleted, func(ctx context.Context, e *capitan.Event) {\n    // Same request ID available\n    requestID, _ := zyn.RequestIDKey.From(e)\n    log.Printf(\"Provider call for request %s completed\", requestID)\n})\n\ncapitan.Hook(zyn.RequestCompleted, func(ctx context.Context, e *capitan.Event) {\n    requestID, _ := zyn.RequestIDKey.From(e)\n    log.Printf(\"Request %s completed\", requestID)\n})",{"id":3062,"title":3063,"titles":3064,"content":3065,"level":129},"/v1.0.6/guides/observability#global-observer","Global Observer",[1114],"Observe all events for debugging: observer := capitan.Observe(func(ctx context.Context, e *capitan.Event) {\n    log.Printf(\"Event: %s\", e.Signal())\n})\ndefer observer.Close()",{"id":3067,"title":3068,"titles":3069,"content":103,"level":129},"/v1.0.6/guides/observability#integration-examples","Integration Examples",[1114],{"id":3071,"title":3072,"titles":3073,"content":3074,"level":143},"/v1.0.6/guides/observability#prometheus-metrics","Prometheus Metrics",[1114,3068],"var (\n    tokenCounter = prometheus.NewCounterVec(\n        prometheus.CounterOpts{Name: \"llm_tokens_total\"},\n        []string{\"model\", \"type\"},\n    )\n    latencyHistogram = prometheus.NewHistogramVec(\n        prometheus.HistogramOpts{Name: \"llm_latency_seconds\"},\n        []string{\"model\"},\n    )\n)\n\ncapitan.Hook(zyn.ProviderCallCompleted, func(ctx context.Context, e *capitan.Event) {\n    model, _ := zyn.ModelKey.From(e)\n    prompt, _ := zyn.PromptTokensKey.From(e)\n    completion, _ := zyn.CompletionTokensKey.From(e)\n    duration, _ := zyn.DurationMsKey.From(e)\n\n    tokenCounter.WithLabelValues(model, \"prompt\").Add(float64(prompt))\n    tokenCounter.WithLabelValues(model, \"completion\").Add(float64(completion))\n    latencyHistogram.WithLabelValues(model).Observe(float64(duration) / 1000)\n})",{"id":3076,"title":3077,"titles":3078,"content":3079,"level":143},"/v1.0.6/guides/observability#structured-logging","Structured Logging",[1114,3068],"capitan.Hook(zyn.RequestCompleted, func(ctx context.Context, e *capitan.Event) {\n    requestID, _ := zyn.RequestIDKey.From(e)\n    synapseType, _ := zyn.SynapseTypeKey.From(e)\n    input, _ := zyn.InputKey.From(e)\n    output, _ := zyn.OutputKey.From(e)\n\n    slog.Info(\"synapse_completed\",\n        \"request_id\", requestID,\n        \"type\", synapseType,\n        \"input_len\", len(input),\n        \"output\", output,\n    )\n})",{"id":3081,"title":2493,"titles":3082,"content":3083,"level":129},"/v1.0.6/guides/observability#next-steps",[1114],"Testing Guide - Test with hookscapitan Documentation - Full hooks reference html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .soy-K, html code.shiki .soy-K{--shiki-default:#BBBBBB}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .scyPU, html code.shiki .scyPU{--shiki-default:var(--shiki-placeholder)}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 pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .skxcq, html code.shiki .skxcq{--shiki-default:var(--shiki-builtin)}",{"id":3085,"title":1136,"titles":3086,"content":3087,"level":111},"/v1.0.6/guides/testing",[],"Testing strategies for LLM-powered applications",{"id":3089,"title":1136,"titles":3090,"content":3091,"level":111},"/v1.0.6/guides/testing#testing",[],"Strategies for testing LLM-powered applications with zyn.",{"id":3093,"title":3094,"titles":3095,"content":103,"level":129},"/v1.0.6/guides/testing#mock-providers","Mock Providers",[1136],{"id":3097,"title":3098,"titles":3099,"content":3100,"level":143},"/v1.0.6/guides/testing#fixed-response","Fixed Response",[1136,3094],"func TestClassification(t *testing.T) {\n    provider := zyn.NewMockProviderWithResponse(`{\n        \"primary\": \"spam\",\n        \"secondary\": \"\",\n        \"confidence\": 0.95,\n        \"reasoning\": [\"Contains promotional language\"]\n    }`)\n\n    classifier, _ := zyn.Classification(\n        \"Classify email type\",\n        []string{\"spam\", \"urgent\", \"personal\"},\n        provider,\n    )\n\n    session := zyn.NewSession()\n    result, err := classifier.Fire(context.Background(), session, \"Buy now!\")\n\n    assert.NoError(t, err)\n    assert.Equal(t, \"spam\", result)\n}",{"id":3102,"title":3103,"titles":3104,"content":3105,"level":143},"/v1.0.6/guides/testing#dynamic-response","Dynamic Response",[1136,3094],"func TestDynamicResponse(t *testing.T) {\n    provider := zyn.NewMockProviderWithCallback(func(prompt string, temp float32) (string, error) {\n        if strings.Contains(prompt, \"valid\") {\n            return `{\"decision\": true, \"confidence\": 0.9, \"reasoning\": [\"ok\"]}`, nil\n        }\n        return `{\"decision\": false, \"confidence\": 0.9, \"reasoning\": [\"invalid\"]}`, nil\n    })\n\n    validator, _ := zyn.Binary(\"Is this valid?\", provider)\n    session := zyn.NewSession()\n\n    result, _ := validator.Fire(context.Background(), session, \"valid input\")\n    assert.True(t, result)\n}",{"id":3107,"title":3108,"titles":3109,"content":3110,"level":143},"/v1.0.6/guides/testing#error-simulation","Error Simulation",[1136,3094],"func TestErrorHandling(t *testing.T) {\n    provider := zyn.NewMockProviderWithError(\"rate limit exceeded\")\n\n    synapse, _ := zyn.Binary(\"question\", provider)\n    session := zyn.NewSession()\n\n    _, err := synapse.Fire(context.Background(), session, \"input\")\n    assert.Error(t, err)\n    assert.Contains(t, err.Error(), \"rate limit\")\n}",{"id":3112,"title":3113,"titles":3114,"content":3115,"level":129},"/v1.0.6/guides/testing#testing-package","Testing Package",[1136],"The testing package provides advanced test utilities: import zynt \"github.com/zoobz-io/zyn/testing\"",{"id":3117,"title":3118,"titles":3119,"content":3120,"level":143},"/v1.0.6/guides/testing#response-builder","Response Builder",[1136,3113],"Build valid responses easily: // Binary response\nresponse := zynt.NewResponseBuilder().\n    WithDecision(true).\n    WithConfidence(0.95).\n    WithReasoning(\"Valid format\", \"Contains required fields\").\n    Build()\n\n// Classification response\nresponse := zynt.NewResponseBuilder().\n    WithPrimary(\"urgent\").\n    WithSecondary(\"\").\n    WithConfidence(0.87).\n    WithReasoning(\"Time-sensitive language detected\").\n    Build()\n\n// Ranking response\nresponse := zynt.NewResponseBuilder().\n    WithRanked(\"first\", \"second\", \"third\").\n    WithConfidence(0.9).\n    WithReasoning(\"Ordered by relevance\").\n    Build()",{"id":3122,"title":3123,"titles":3124,"content":3125,"level":143},"/v1.0.6/guides/testing#sequenced-provider","Sequenced Provider",[1136,3113],"Return different responses in sequence: provider := zynt.NewSequencedProvider(\n    zynt.NewResponseBuilder().WithDecision(true).WithConfidence(0.9).WithReasoning(\"first\").Build(),\n    zynt.NewResponseBuilder().WithDecision(false).WithConfidence(0.8).WithReasoning(\"second\").Build(),\n)\n\nsynapse, _ := zyn.Binary(\"question\", provider)\nsession := zyn.NewSession()\n\nresult1, _ := synapse.Fire(ctx, session, \"input1\")  // true\nresult2, _ := synapse.Fire(ctx, session, \"input2\")  // false",{"id":3127,"title":3128,"titles":3129,"content":3130,"level":143},"/v1.0.6/guides/testing#failing-provider","Failing Provider",[1136,3113],"Test retry behavior: // Fails twice, then succeeds\nprovider := zynt.NewFailingProvider(2).\n    WithSuccessResponse(zynt.NewResponseBuilder().\n        WithDecision(true).\n        WithConfidence(0.9).\n        WithReasoning(\"recovered\").\n        Build())\n\nsynapse, _ := zyn.Binary(\"question\", provider, zyn.WithRetry(3))\nsession := zyn.NewSession()\n\nresult, err := synapse.Fire(ctx, session, \"input\")\nassert.NoError(t, err)  // Succeeds on third attempt\nassert.True(t, result)\nassert.Equal(t, 3, provider.CallCount())",{"id":3132,"title":3133,"titles":3134,"content":3135,"level":143},"/v1.0.6/guides/testing#call-recorder","Call Recorder",[1136,3113],"Inspect provider calls: inner := zynt.NewSequencedProvider(`{\"decision\": true, \"confidence\": 0.9, \"reasoning\": [\"ok\"]}`)\nrecorder := zynt.NewCallRecorder(inner)\n\nsynapse, _ := zyn.Binary(\"question\", recorder)\nsynapse.Fire(ctx, session, \"test input\")\n\ncalls := recorder.Calls()\nassert.Len(t, calls, 1)\nassert.Equal(t, \"test input\", calls[0].Messages[0].Content)\n\nlastCall := recorder.LastCall()\nassert.NotNil(t, lastCall)",{"id":3137,"title":3138,"titles":3139,"content":3140,"level":143},"/v1.0.6/guides/testing#latency-provider","Latency Provider",[1136,3113],"Test timeout behavior: inner := zynt.NewSequencedProvider(`{\"decision\": true, \"confidence\": 0.9, \"reasoning\": [\"ok\"]}`)\nslowProvider := zynt.NewLatencyProvider(inner, 500*time.Millisecond)\n\nsynapse, _ := zyn.Binary(\"question\", slowProvider, zyn.WithTimeout(100*time.Millisecond))\nsession := zyn.NewSession()\n\n_, err := synapse.Fire(ctx, session, \"input\")\nassert.Error(t, err)  // Timeout before provider responds",{"id":3142,"title":3143,"titles":3144,"content":103,"level":129},"/v1.0.6/guides/testing#testing-patterns","Testing Patterns",[1136],{"id":3146,"title":3147,"titles":3148,"content":3149,"level":143},"/v1.0.6/guides/testing#session-state","Session State",[1136,3143],"func TestSessionUpdates(t *testing.T) {\n    provider := zyn.NewMockProviderWithResponse(`{...}`)\n    synapse, _ := zyn.Binary(\"question\", provider)\n\n    session := zyn.NewSession()\n    assert.Equal(t, 0, session.Len())\n\n    synapse.Fire(ctx, session, \"input\")\n\n    assert.Equal(t, 2, session.Len())  // user + assistant\n    assert.Equal(t, zyn.RoleUser, session.Messages()[0].Role)\n    assert.Equal(t, zyn.RoleAssistant, session.Messages()[1].Role)\n}",{"id":3151,"title":3152,"titles":3153,"content":3154,"level":143},"/v1.0.6/guides/testing#transactional-behavior","Transactional Behavior",[1136,3143],"func TestSessionUnchangedOnError(t *testing.T) {\n    provider := zyn.NewMockProviderWithError(\"failure\")\n    synapse, _ := zyn.Binary(\"question\", provider, zyn.WithRetry(2))\n\n    session := zyn.NewSession()\n    initialLen := session.Len()\n\n    _, err := synapse.Fire(ctx, session, \"input\")\n\n    assert.Error(t, err)\n    assert.Equal(t, initialLen, session.Len())  // Unchanged\n}",{"id":3156,"title":3157,"titles":3158,"content":3159,"level":143},"/v1.0.6/guides/testing#custom-type-validation","Custom Type Validation",[1136,3143],"type Order struct {\n    ID     string  `json:\"id\"`\n    Amount float64 `json:\"amount\"`\n}\n\nfunc (o Order) Validate() error {\n    if o.ID == \"\" {\n        return fmt.Errorf(\"ID required\")\n    }\n    return nil\n}\n\nfunc TestValidationError(t *testing.T) {\n    // Response missing required ID\n    provider := zyn.NewMockProviderWithResponse(`{\n        \"id\": \"\",\n        \"amount\": 100,\n        \"confidence\": 0.9,\n        \"reasoning\": [\"extracted\"]\n    }`)\n\n    extractor, _ := zyn.Extract[Order](\"extract order\", provider)\n    session := zyn.NewSession()\n\n    _, err := extractor.Fire(ctx, session, \"Order for $100\")\n    assert.Error(t, err)\n    assert.Contains(t, err.Error(), \"ID required\")\n}",{"id":3161,"title":3162,"titles":3163,"content":3164,"level":129},"/v1.0.6/guides/testing#integration-tests","Integration Tests",[1136],"For tests against real providers: func TestRealProvider(t *testing.T) {\n    if os.Getenv(\"OPENAI_API_KEY\") == \"\" {\n        t.Skip(\"OPENAI_API_KEY not set\")\n    }\n\n    provider := openai.New(openai.Config{\n        APIKey: os.Getenv(\"OPENAI_API_KEY\"),\n        Model:  \"gpt-4o-mini\",\n    })\n\n    synapse, _ := zyn.Binary(\"Is this a valid email?\", provider,\n        zyn.WithTimeout(30*time.Second),\n    )\n\n    session := zyn.NewSession()\n    result, err := synapse.Fire(context.Background(), session, \"test@example.com\")\n\n    assert.NoError(t, err)\n    assert.True(t, result)\n}",{"id":3166,"title":3167,"titles":3168,"content":3169,"level":129},"/v1.0.6/guides/testing#benchmarks","Benchmarks",[1136],"func BenchmarkSynapseFire(b *testing.B) {\n    provider := zynt.NewSequencedProvider(\n        zynt.NewResponseBuilder().\n            WithDecision(true).\n            WithConfidence(0.9).\n            WithReasoning(\"ok\").\n            Build(),\n    )\n\n    synapse, _ := zyn.Binary(\"question\", provider)\n\n    b.ResetTimer()\n    for i := 0; i \u003C b.N; i++ {\n        session := zyn.NewSession()\n        synapse.Fire(context.Background(), session, \"input\")\n    }\n}",{"id":3171,"title":2493,"titles":3172,"content":3173,"level":129},"/v1.0.6/guides/testing#next-steps",[1136],"Best Practices - Production guidelinesTesting Package Reference - Full API html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}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 pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}",{"id":3175,"title":1582,"titles":3176,"content":3177,"level":111},"/v1.0.6/guides/best-practices",[],"Production guidelines for LLM applications",{"id":3179,"title":1582,"titles":3180,"content":3181,"level":111},"/v1.0.6/guides/best-practices#best-practices",[],"Guidelines for building production LLM applications with zyn.",{"id":3183,"title":3184,"titles":3185,"content":103,"level":129},"/v1.0.6/guides/best-practices#synapse-design","Synapse Design",[1582],{"id":3187,"title":3188,"titles":3189,"content":3190,"level":143},"/v1.0.6/guides/best-practices#keep-tasks-focused","Keep Tasks Focused",[1582,3184],"Each synapse should do one thing well: // ✅ Good: Single, clear task\nclassifier, _ := zyn.Classification(\"email type\", categories, provider)\nextractor, _ := zyn.Extract[Contact](\"contact info\", provider)\n\n// ❌ Bad: Multiple tasks in one\nsynapse, _ := zyn.Transform(\"classify, extract contacts, and summarize\", provider)",{"id":3192,"title":3193,"titles":3194,"content":3195,"level":143},"/v1.0.6/guides/best-practices#use-appropriate-synapse-types","Use Appropriate Synapse Types",[1582,3184],"Choose the right synapse for the task: TaskSynapseWhyYes/no questionBinaryType-safe booleanPick from optionsClassificationConstrained outputFree-form textTransformString outputStructured dataExtract[T]Type-safe struct",{"id":3197,"title":3198,"titles":3199,"content":3200,"level":143},"/v1.0.6/guides/best-practices#validate-custom-types","Validate Custom Types",[1582,3184],"Always implement meaningful validation: type Order struct {\n    ID     string  `json:\"id\"`\n    Amount float64 `json:\"amount\"`\n}\n\nfunc (o Order) Validate() error {\n    if o.ID == \"\" {\n        return fmt.Errorf(\"order ID required\")\n    }\n    if o.Amount \u003C= 0 {\n        return fmt.Errorf(\"amount must be positive\")\n    }\n    if o.Amount > 1000000 {\n        return fmt.Errorf(\"amount exceeds maximum\")\n    }\n    return nil\n}",{"id":3202,"title":3203,"titles":3204,"content":103,"level":129},"/v1.0.6/guides/best-practices#session-management","Session Management",[1582],{"id":3206,"title":3207,"titles":3208,"content":3209,"level":143},"/v1.0.6/guides/best-practices#one-session-per-conversation","One Session Per Conversation",[1582,3203],"// ✅ Good: Dedicated session per user/conversation\nuserSessions := make(map[string]*zyn.Session)\n\nfunc handleRequest(userID, input string) {\n    session := userSessions[userID]\n    if session == nil {\n        session = zyn.NewSession()\n        userSessions[userID] = session\n    }\n    synapse.Fire(ctx, session, input)\n}",{"id":3211,"title":3212,"titles":3213,"content":3214,"level":143},"/v1.0.6/guides/best-practices#manage-session-size","Manage Session Size",[1582,3203],"Sessions grow unbounded. Implement pruning: const maxMessages = 50\n\nfunc processWithPruning(ctx context.Context, session *zyn.Session, input string) {\n    result, _ := synapse.Fire(ctx, session, input)\n\n    // Prune if too large\n    if session.Len() > maxMessages {\n        session.Prune(session.Len() - maxMessages)\n    }\n\n    return result\n}",{"id":3216,"title":3217,"titles":3218,"content":3219,"level":143},"/v1.0.6/guides/best-practices#dont-share-sessions-across-users","Don't Share Sessions Across Users",[1582,3203],"// ❌ Bad: Shared session leaks context between users\nvar globalSession = zyn.NewSession()\n\n// ✅ Good: Isolated sessions\nfunc newUserSession() *zyn.Session {\n    return zyn.NewSession()\n}",{"id":3221,"title":1109,"titles":3222,"content":103,"level":129},"/v1.0.6/guides/best-practices#reliability",[1582],{"id":3224,"title":3225,"titles":3226,"content":3227,"level":143},"/v1.0.6/guides/best-practices#always-use-timeout","Always Use Timeout",[1582,1109],"LLM calls can hang indefinitely: // ✅ Good: Bounded execution time\nsynapse, _ := zyn.Binary(\"q\", provider, zyn.WithTimeout(30*time.Second))\n\n// ❌ Bad: Unbounded\nsynapse, _ := zyn.Binary(\"q\", provider)",{"id":3229,"title":3230,"titles":3231,"content":3232,"level":143},"/v1.0.6/guides/best-practices#retry-with-backoff","Retry with Backoff",[1582,1109],"For production, use backoff to handle rate limits: synapse, _ := zyn.Binary(\"q\", provider,\n    zyn.WithBackoff(3, 100*time.Millisecond),  // 100ms, 200ms, 400ms\n    zyn.WithTimeout(30*time.Second),\n)",{"id":3234,"title":3235,"titles":3236,"content":3237,"level":143},"/v1.0.6/guides/best-practices#circuit-breaker-for-outages","Circuit Breaker for Outages",[1582,1109],"Protect against cascading failures: synapse, _ := zyn.Binary(\"q\", provider,\n    zyn.WithCircuitBreaker(5, 60*time.Second),\n)",{"id":3239,"title":3240,"titles":3241,"content":3242,"level":143},"/v1.0.6/guides/best-practices#have-a-fallback","Have a Fallback",[1582,1109],"For critical paths: backupSynapse, _ := zyn.Binary(\"q\", backupProvider)\nsynapse, _ := zyn.Binary(\"q\", primaryProvider,\n    zyn.WithFallback(backupSynapse),\n)",{"id":3244,"title":3245,"titles":3246,"content":103,"level":129},"/v1.0.6/guides/best-practices#performance","Performance",[1582],{"id":3248,"title":3249,"titles":3250,"content":3251,"level":143},"/v1.0.6/guides/best-practices#reuse-synapses","Reuse Synapses",[1582,3245],"Create synapses once, reuse them: // ✅ Good: Create once\nvar classifier *zyn.ClassificationSynapse\n\nfunc init() {\n    classifier, _ = zyn.Classification(\"type\", categories, provider)\n}\n\nfunc handleRequest(input string) {\n    session := zyn.NewSession()\n    return classifier.Fire(ctx, session, input)\n}\n\n// ❌ Bad: Create per request\nfunc handleRequest(input string) {\n    classifier, _ := zyn.Classification(\"type\", categories, provider)\n    return classifier.Fire(ctx, zyn.NewSession(), input)\n}",{"id":3253,"title":3254,"titles":3255,"content":3256,"level":143},"/v1.0.6/guides/best-practices#use-appropriate-models","Use Appropriate Models",[1582,3245],"Match model capability to task complexity: // Simple classification → fast, cheap model\nclassifier, _ := zyn.Classification(\"type\", cats, openai.New(openai.Config{\n    Model: \"gpt-4o-mini\",\n}))\n\n// Complex reasoning → capable model\nanalyzer, _ := zyn.Analyze[Report](\"deep analysis\", openai.New(openai.Config{\n    Model: \"gpt-4o\",\n}))",{"id":3258,"title":3259,"titles":3260,"content":3261,"level":143},"/v1.0.6/guides/best-practices#temperature-for-determinism","Temperature for Determinism",[1582,3245],"Use low temperature for repeatable results. Classification already defaults to 0.3, but you can override per-request: // Override temperature via input struct\ninput := zyn.ClassificationInput{\n    Subject:     \"some content\",\n    Temperature: zyn.DefaultTemperatureDeterministic, // 0.1\n}\nresult, _ := classifier.FireWithInput(ctx, session, input)",{"id":3263,"title":1114,"titles":3264,"content":103,"level":129},"/v1.0.6/guides/best-practices#observability",[1582],{"id":3266,"title":3267,"titles":3268,"content":3269,"level":143},"/v1.0.6/guides/best-practices#track-token-usage","Track Token Usage",[1582,1114],"Monitor costs: capitan.Hook(zyn.ProviderCallCompleted, func(ctx context.Context, e *capitan.Event) {\n    tokens, _ := zyn.TotalTokensKey.From(e)\n    model, _ := zyn.ModelKey.From(e)\n    metrics.Add(\"llm_tokens\", float64(tokens), \"model\", model)\n})",{"id":3271,"title":3272,"titles":3273,"content":3274,"level":143},"/v1.0.6/guides/best-practices#log-failures","Log Failures",[1582,1114],"capitan.Hook(zyn.RequestFailed, func(ctx context.Context, e *capitan.Event) {\n    requestID, _ := zyn.RequestIDKey.From(e)\n    err, _ := zyn.ErrorKey.From(e)\n    log.Printf(\"Request %s failed: %s\", requestID, err)\n})",{"id":3276,"title":3277,"titles":3278,"content":3279,"level":143},"/v1.0.6/guides/best-practices#monitor-latency","Monitor Latency",[1582,1114],"capitan.Hook(zyn.ProviderCallCompleted, func(ctx context.Context, e *capitan.Event) {\n    duration, _ := zyn.DurationMsKey.From(e)\n    metrics.Histogram(\"llm_latency_ms\", float64(duration))\n})",{"id":3281,"title":1703,"titles":3282,"content":103,"level":129},"/v1.0.6/guides/best-practices#security",[1582],{"id":3284,"title":3285,"titles":3286,"content":3287,"level":143},"/v1.0.6/guides/best-practices#validate-all-inputs","Validate All Inputs",[1582,1703],"Don't pass user input directly without validation: func handleUserInput(input string) {\n    // Validate/sanitize\n    if len(input) > 10000 {\n        return errors.New(\"input too long\")\n    }\n\n    synapse.Fire(ctx, session, input)\n}",{"id":3289,"title":3290,"titles":3291,"content":3292,"level":143},"/v1.0.6/guides/best-practices#dont-log-sensitive-data","Don't Log Sensitive Data",[1582,1703],"capitan.Hook(zyn.RequestCompleted, func(ctx context.Context, e *capitan.Event) {\n    // ❌ Bad: May contain PII\n    input, _ := zyn.InputKey.From(e)\n    log.Printf(\"Input: %s\", input)\n\n    // ✅ Good: Log metadata only\n    requestID, _ := zyn.RequestIDKey.From(e)\n    log.Printf(\"Request %s completed\", requestID)\n})",{"id":3294,"title":3295,"titles":3296,"content":3297,"level":143},"/v1.0.6/guides/best-practices#protect-api-keys","Protect API Keys",[1582,1703],"// ✅ Good: Environment variable\nprovider := openai.New(openai.Config{\n    APIKey: os.Getenv(\"OPENAI_API_KEY\"),\n})\n\n// ❌ Bad: Hardcoded\nprovider := openai.New(openai.Config{\n    APIKey: \"sk-...\",\n})",{"id":3299,"title":1136,"titles":3300,"content":103,"level":129},"/v1.0.6/guides/best-practices#testing",[1582],{"id":3302,"title":3303,"titles":3304,"content":3305,"level":143},"/v1.0.6/guides/best-practices#use-mocks-in-unit-tests","Use Mocks in Unit Tests",[1582,1136],"func TestBusiness Logic(t *testing.T) {\n    provider := zyn.NewMockProviderWithResponse(`{...}`)\n    // Test with deterministic responses\n}",{"id":3307,"title":3308,"titles":3309,"content":3310,"level":143},"/v1.0.6/guides/best-practices#integration-tests-with-skip","Integration Tests with Skip",[1582,1136],"func TestRealProvider(t *testing.T) {\n    if os.Getenv(\"OPENAI_API_KEY\") == \"\" {\n        t.Skip(\"OPENAI_API_KEY not set\")\n    }\n    // Test against real provider\n}",{"id":3312,"title":3313,"titles":3314,"content":3315,"level":129},"/v1.0.6/guides/best-practices#summary","Summary",[1582],"AreaRecommendationSynapsesOne task per synapse, validate custom typesSessionsOne per conversation, manage size, don't shareReliabilityAlways timeout, retry with backoff, have fallbackPerformanceReuse synapses, match model to taskObservabilityTrack tokens, log failures, monitor latencySecurityValidate inputs, protect keys, don't log PIITestingMock in unit tests, skip integration without keys html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}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 pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}html pre.shiki code .skxcq, html code.shiki .skxcq{--shiki-default:var(--shiki-builtin)}html pre.shiki code .sfm-E, html code.shiki .sfm-E{--shiki-default:var(--shiki-variable)}html pre.shiki code .scyPU, html code.shiki .scyPU{--shiki-default:var(--shiki-placeholder)}",{"id":3317,"title":1595,"titles":3318,"content":3319,"level":111},"/v1.0.6/cookbook/classification-workflows",[],"Real-world classification patterns with zyn",{"id":3321,"title":1595,"titles":3322,"content":3323,"level":111},"/v1.0.6/cookbook/classification-workflows#classification-workflows",[],"Real-world patterns for classification tasks.",{"id":3325,"title":3326,"titles":3327,"content":3328,"level":129},"/v1.0.6/cookbook/classification-workflows#email-triage-system","Email Triage System",[1595],"Automatically route incoming emails: package main\n\nimport (\n    \"context\"\n    \"fmt\"\n\n    \"github.com/zoobz-io/zyn\"\n    \"github.com/zoobz-io/zyn/openai\"\n)\n\ntype EmailRouter struct {\n    classifier *zyn.ClassificationSynapse\n    urgency    *zyn.ClassificationSynapse\n}\n\nfunc NewEmailRouter(provider zyn.Provider) (*EmailRouter, error) {\n    classifier, err := zyn.Classification(\n        \"Classify email type based on content and subject\",\n        []string{\"support\", \"sales\", \"billing\", \"spam\", \"personal\"},\n        provider,\n        zyn.WithRetry(2),\n    )\n    if err != nil {\n        return nil, err\n    }\n\n    urgency, err := zyn.Classification(\n        \"Determine urgency level\",\n        []string{\"low\", \"medium\", \"high\", \"critical\"},\n        provider,\n        zyn.WithRetry(2),\n    )\n    if err != nil {\n        return nil, err\n    }\n\n    return &EmailRouter{classifier: classifier, urgency: urgency}, nil\n}\n\ntype RoutingDecision struct {\n    Category string\n    Urgency  string\n    Queue    string\n}\n\nfunc (r *EmailRouter) Route(ctx context.Context, subject, body string) (*RoutingDecision, error) {\n    session := zyn.NewSession()\n    input := fmt.Sprintf(\"Subject: %s\\n\\nBody: %s\", subject, body)\n\n    // Classify type\n    category, err := r.classifier.Fire(ctx, session, input)\n    if err != nil {\n        return nil, fmt.Errorf(\"classification failed: %w\", err)\n    }\n\n    // Determine urgency (with classification context)\n    urgency, err := r.urgency.Fire(ctx, session, \"What is the urgency of this email?\")\n    if err != nil {\n        return nil, fmt.Errorf(\"urgency assessment failed: %w\", err)\n    }\n\n    return &RoutingDecision{\n        Category: category,\n        Urgency:  urgency,\n        Queue:    determineQueue(category, urgency),\n    }, nil\n}\n\nfunc determineQueue(category, urgency string) string {\n    if urgency == \"critical\" {\n        return \"escalation\"\n    }\n    return category + \"-queue\"\n}",{"id":3330,"title":3331,"titles":3332,"content":3333,"level":129},"/v1.0.6/cookbook/classification-workflows#multi-level-classification","Multi-Level Classification",[1595],"Hierarchical classification with primary and secondary categories: type ContentClassifier struct {\n    primary   *zyn.ClassificationSynapse\n    secondary map[string]*zyn.ClassificationSynapse\n}\n\nfunc NewContentClassifier(provider zyn.Provider) (*ContentClassifier, error) {\n    primary, _ := zyn.Classification(\n        \"Primary content category\",\n        []string{\"technology\", \"business\", \"entertainment\", \"sports\"},\n        provider,\n    )\n\n    // Secondary classifiers per primary category\n    secondary := map[string]*zyn.ClassificationSynapse{}\n\n    secondary[\"technology\"], _ = zyn.Classification(\n        \"Technology subcategory\",\n        []string{\"ai\", \"cloud\", \"security\", \"hardware\", \"software\"},\n        provider,\n    )\n\n    secondary[\"business\"], _ = zyn.Classification(\n        \"Business subcategory\",\n        []string{\"finance\", \"startup\", \"management\", \"marketing\"},\n        provider,\n    )\n\n    return &ContentClassifier{primary: primary, secondary: secondary}, nil\n}\n\ntype Classification struct {\n    Primary   string\n    Secondary string\n}\n\nfunc (c *ContentClassifier) Classify(ctx context.Context, content string) (*Classification, error) {\n    session := zyn.NewSession()\n\n    // Primary classification\n    primary, err := c.primary.Fire(ctx, session, content)\n    if err != nil {\n        return nil, err\n    }\n\n    // Secondary classification if available\n    var secondary string\n    if secondaryClassifier, ok := c.secondary[primary]; ok {\n        secondary, err = secondaryClassifier.Fire(ctx, session, \"Classify subcategory\")\n        if err != nil {\n            return nil, err\n        }\n    }\n\n    return &Classification{Primary: primary, Secondary: secondary}, nil\n}",{"id":3335,"title":3336,"titles":3337,"content":3338,"level":129},"/v1.0.6/cookbook/classification-workflows#classification-with-examples","Classification with Examples",[1595],"Improve accuracy with few-shot examples: func classifyWithExamples(ctx context.Context, provider zyn.Provider, text string) (string, error) {\n    classifier, _ := zyn.Classification(\n        \"Classify customer feedback sentiment\",\n        []string{\"positive\", \"negative\", \"neutral\", \"mixed\"},\n        provider,\n    )\n\n    session := zyn.NewSession()\n\n    // Provide examples through classification input\n    input := zyn.ClassificationInput{\n        Subject: text,\n        Examples: map[string][]string{\n            \"positive\": {\n                \"Absolutely love this product!\",\n                \"Best purchase I've made all year\",\n                \"Exceeded all my expectations\",\n            },\n            \"negative\": {\n                \"Complete waste of money\",\n                \"Terrible experience, would not recommend\",\n                \"Product broke after one day\",\n            },\n            \"neutral\": {\n                \"It works as described\",\n                \"Average product, nothing special\",\n                \"Does what it says\",\n            },\n            \"mixed\": {\n                \"Good product but expensive\",\n                \"Love the features, hate the interface\",\n                \"Fast shipping but item was damaged\",\n            },\n        },\n    }\n\n    return classifier.FireWithInput(ctx, session, input)\n}",{"id":3340,"title":3341,"titles":3342,"content":3343,"level":129},"/v1.0.6/cookbook/classification-workflows#batch-classification","Batch Classification",[1595],"Classify multiple items efficiently: type BatchClassifier struct {\n    synapse *zyn.ClassificationSynapse\n}\n\ntype ClassificationResult struct {\n    Input    string\n    Category string\n    Error    error\n}\n\nfunc (b *BatchClassifier) ClassifyBatch(ctx context.Context, items []string) []ClassificationResult {\n    results := make([]ClassificationResult, len(items))\n\n    // Process in parallel with bounded concurrency\n    sem := make(chan struct{}, 5)  // Max 5 concurrent\n    var wg sync.WaitGroup\n\n    for i, item := range items {\n        wg.Add(1)\n        go func(idx int, input string) {\n            defer wg.Done()\n            sem \u003C- struct{}{}\n            defer func() { \u003C-sem }()\n\n            session := zyn.NewSession()\n            category, err := b.synapse.Fire(ctx, session, input)\n\n            results[idx] = ClassificationResult{\n                Input:    input,\n                Category: category,\n                Error:    err,\n            }\n        }(i, item)\n    }\n\n    wg.Wait()\n    return results\n}",{"id":3345,"title":3346,"titles":3347,"content":3348,"level":129},"/v1.0.6/cookbook/classification-workflows#classification-with-confidence-threshold","Classification with Confidence Threshold",[1595],"Only accept high-confidence classifications: func classifyWithThreshold(ctx context.Context, synapse *zyn.ClassificationSynapse, input string, threshold float64) (string, error) {\n    session := zyn.NewSession()\n\n    result, err := synapse.FireWithDetails(ctx, session, input)\n    if err != nil {\n        return \"\", err\n    }\n\n    if result.Confidence \u003C threshold {\n        return \"\", fmt.Errorf(\"confidence %.2f below threshold %.2f\", result.Confidence, threshold)\n    }\n\n    return result.Primary, nil\n}\n\n// Usage\ncategory, err := classifyWithThreshold(ctx, classifier, email, 0.8)\nif err != nil {\n    // Route to human review\n    return routeToHuman(email)\n}",{"id":3350,"title":2493,"titles":3351,"content":3352,"level":129},"/v1.0.6/cookbook/classification-workflows#next-steps",[1595],"Extraction Pipelines - Extract structured dataMulti-Turn Conversations - Complex workflows html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .soy-K, html code.shiki .soy-K{--shiki-default:#BBBBBB}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}html pre.shiki code .scyPU, html code.shiki .scyPU{--shiki-default:var(--shiki-placeholder)}html pre.shiki code .suWN2, html code.shiki .suWN2{--shiki-default:var(--shiki-tag)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}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 pre.shiki code .skxcq, html code.shiki .skxcq{--shiki-default:var(--shiki-builtin)}",{"id":3354,"title":1602,"titles":3355,"content":3356,"level":111},"/v1.0.6/cookbook/extraction-pipelines",[],"Extracting structured data from unstructured text",{"id":3358,"title":1602,"titles":3359,"content":3360,"level":111},"/v1.0.6/cookbook/extraction-pipelines#extraction-pipelines",[],"Patterns for extracting structured data from unstructured text.",{"id":3362,"title":3363,"titles":3364,"content":3365,"level":129},"/v1.0.6/cookbook/extraction-pipelines#contact-information-extractor","Contact Information Extractor",[1602],"Extract contact details from emails or documents: package main\n\nimport (\n    \"context\"\n    \"fmt\"\n    \"regexp\"\n\n    \"github.com/zoobz-io/zyn\"\n)\n\ntype Contact struct {\n    Name    string `json:\"name\"`\n    Email   string `json:\"email\"`\n    Phone   string `json:\"phone,omitempty\"`\n    Company string `json:\"company,omitempty\"`\n    Title   string `json:\"title,omitempty\"`\n}\n\nfunc (c Contact) Validate() error {\n    if c.Name == \"\" {\n        return fmt.Errorf(\"name is required\")\n    }\n    if c.Email != \"\" && !isValidEmail(c.Email) {\n        return fmt.Errorf(\"invalid email format: %s\", c.Email)\n    }\n    return nil\n}\n\nfunc isValidEmail(email string) bool {\n    pattern := `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$`\n    matched, _ := regexp.MatchString(pattern, email)\n    return matched\n}\n\ntype ContactExtractor struct {\n    synapse *zyn.ExtractionSynapse[Contact]\n}\n\nfunc NewContactExtractor(provider zyn.Provider) (*ContactExtractor, error) {\n    synapse, err := zyn.Extract[Contact](\n        \"Extract contact information including name, email, phone, company, and job title\",\n        provider,\n        zyn.WithRetry(2),\n    )\n    if err != nil {\n        return nil, err\n    }\n    return &ContactExtractor{synapse: synapse}, nil\n}\n\nfunc (e *ContactExtractor) Extract(ctx context.Context, text string) (Contact, error) {\n    session := zyn.NewSession()\n    return e.synapse.Fire(ctx, session, text)\n}\n\n// Usage\nfunc main() {\n    extractor, _ := NewContactExtractor(provider)\n\n    text := `\n        Hi, I'm John Smith from Acme Corp. I'm the VP of Engineering.\n        You can reach me at john.smith@acme.com or call (555) 123-4567.\n    `\n\n    contact, err := extractor.Extract(context.Background(), text)\n    // contact = {Name: \"John Smith\", Email: \"john.smith@acme.com\", Phone: \"(555) 123-4567\", Company: \"Acme Corp\", Title: \"VP of Engineering\"}\n}",{"id":3367,"title":3368,"titles":3369,"content":3370,"level":129},"/v1.0.6/cookbook/extraction-pipelines#invoice-data-extraction","Invoice Data Extraction",[1602],"Extract structured invoice data: type LineItem struct {\n    Description string  `json:\"description\"`\n    Quantity    int     `json:\"quantity\"`\n    UnitPrice   float64 `json:\"unit_price\"`\n    Total       float64 `json:\"total\"`\n}\n\ntype Invoice struct {\n    InvoiceNumber string     `json:\"invoice_number\"`\n    Date          string     `json:\"date\"`\n    Vendor        string     `json:\"vendor\"`\n    Items         []LineItem `json:\"items\"`\n    Subtotal      float64    `json:\"subtotal\"`\n    Tax           float64    `json:\"tax\"`\n    Total         float64    `json:\"total\"`\n}\n\nfunc (i Invoice) Validate() error {\n    if i.InvoiceNumber == \"\" {\n        return fmt.Errorf(\"invoice number required\")\n    }\n    if len(i.Items) == 0 {\n        return fmt.Errorf(\"at least one line item required\")\n    }\n    if i.Total \u003C= 0 {\n        return fmt.Errorf(\"total must be positive\")\n    }\n\n    // Validate line items sum\n    var itemsTotal float64\n    for _, item := range i.Items {\n        itemsTotal += item.Total\n    }\n    if abs(itemsTotal-i.Subtotal) > 0.01 {\n        return fmt.Errorf(\"line items don't sum to subtotal\")\n    }\n\n    return nil\n}\n\nfunc extractInvoice(ctx context.Context, provider zyn.Provider, invoiceText string) (Invoice, error) {\n    extractor, _ := zyn.Extract[Invoice](\n        \"Extract invoice details including number, date, vendor, line items, and totals\",\n        provider,\n    )\n\n    session := zyn.NewSession()\n    return extractor.Fire(ctx, session, invoiceText)\n}",{"id":3372,"title":3373,"titles":3374,"content":3375,"level":129},"/v1.0.6/cookbook/extraction-pipelines#multi-step-extraction-pipeline","Multi-Step Extraction Pipeline",[1602],"Extract complex data in stages: type RawEvent struct {\n    Title       string `json:\"title\"`\n    Description string `json:\"description\"`\n    RawDate     string `json:\"raw_date\"`\n    RawLocation string `json:\"raw_location\"`\n}\n\nfunc (r RawEvent) Validate() error {\n    if r.Title == \"\" {\n        return fmt.Errorf(\"title required\")\n    }\n    return nil\n}\n\ntype ParsedDate struct {\n    Year   int    `json:\"year\"`\n    Month  int    `json:\"month\"`\n    Day    int    `json:\"day\"`\n    Hour   int    `json:\"hour\"`\n    Minute int    `json:\"minute\"`\n    TZ     string `json:\"timezone\"`\n}\n\nfunc (p ParsedDate) Validate() error {\n    if p.Year \u003C 2000 || p.Year > 2100 {\n        return fmt.Errorf(\"invalid year: %d\", p.Year)\n    }\n    return nil\n}\n\ntype Location struct {\n    Venue   string  `json:\"venue\"`\n    Address string  `json:\"address\"`\n    City    string  `json:\"city\"`\n    State   string  `json:\"state\"`\n    Lat     float64 `json:\"latitude,omitempty\"`\n    Lng     float64 `json:\"longitude,omitempty\"`\n}\n\nfunc (l Location) Validate() error {\n    if l.City == \"\" {\n        return fmt.Errorf(\"city required\")\n    }\n    return nil\n}\n\ntype Event struct {\n    Title       string\n    Description string\n    Date        ParsedDate\n    Location    Location\n}\n\nfunc extractEvent(ctx context.Context, provider zyn.Provider, text string) (*Event, error) {\n    session := zyn.NewSession()\n\n    // Step 1: Extract raw event data\n    rawExtractor, _ := zyn.Extract[RawEvent](\"Extract event title, description, date text, and location text\", provider)\n    raw, err := rawExtractor.Fire(ctx, session, text)\n    if err != nil {\n        return nil, fmt.Errorf(\"raw extraction failed: %w\", err)\n    }\n\n    // Step 2: Parse date (with context from step 1)\n    dateExtractor, _ := zyn.Extract[ParsedDate](\"Parse date into structured components\", provider)\n    date, err := dateExtractor.Fire(ctx, session, raw.RawDate)\n    if err != nil {\n        return nil, fmt.Errorf(\"date parsing failed: %w\", err)\n    }\n\n    // Step 3: Parse location (with full context)\n    locationExtractor, _ := zyn.Extract[Location](\"Parse location into structured components\", provider)\n    location, err := locationExtractor.Fire(ctx, session, raw.RawLocation)\n    if err != nil {\n        return nil, fmt.Errorf(\"location parsing failed: %w\", err)\n    }\n\n    return &Event{\n        Title:       raw.Title,\n        Description: raw.Description,\n        Date:        date,\n        Location:    location,\n    }, nil\n}",{"id":3377,"title":3378,"titles":3379,"content":3380,"level":129},"/v1.0.6/cookbook/extraction-pipelines#extraction-with-fallback","Extraction with Fallback",[1602],"Handle extraction failures gracefully: type ProductInfo struct {\n    Name     string   `json:\"name\"`\n    Price    float64  `json:\"price\"`\n    Currency string   `json:\"currency\"`\n    Features []string `json:\"features\"`\n}\n\nfunc (p ProductInfo) Validate() error {\n    if p.Name == \"\" {\n        return fmt.Errorf(\"product name required\")\n    }\n    if p.Price \u003C 0 {\n        return fmt.Errorf(\"price cannot be negative\")\n    }\n    return nil\n}\n\ntype BasicProductInfo struct {\n    Name        string `json:\"name\"`\n    Description string `json:\"description\"`\n}\n\nfunc (b BasicProductInfo) Validate() error {\n    if b.Name == \"\" {\n        return fmt.Errorf(\"name required\")\n    }\n    return nil\n}\n\nfunc extractProduct(ctx context.Context, provider zyn.Provider, text string) (any, error) {\n    session := zyn.NewSession()\n\n    // Try detailed extraction first\n    detailed, _ := zyn.Extract[ProductInfo](\"Extract detailed product information\", provider)\n    product, err := detailed.Fire(ctx, session, text)\n    if err == nil {\n        return product, nil\n    }\n\n    // Fall back to basic extraction\n    basic, _ := zyn.Extract[BasicProductInfo](\"Extract basic product name and description\", provider)\n    return basic.Fire(ctx, zyn.NewSession(), text)\n}",{"id":3382,"title":3383,"titles":3384,"content":3385,"level":129},"/v1.0.6/cookbook/extraction-pipelines#batch-extraction-with-progress","Batch Extraction with Progress",[1602],"Extract from multiple documents with progress tracking: type ExtractionProgress struct {\n    Total     int\n    Completed int\n    Errors    int\n}\n\nfunc extractBatch[T zyn.Validator](\n    ctx context.Context,\n    synapse *zyn.ExtractionSynapse[T],\n    documents []string,\n    progressCh chan\u003C- ExtractionProgress,\n) ([]T, []error) {\n    results := make([]T, len(documents))\n    errors := make([]error, len(documents))\n\n    progress := ExtractionProgress{Total: len(documents)}\n\n    for i, doc := range documents {\n        session := zyn.NewSession()\n        result, err := synapse.Fire(ctx, session, doc)\n\n        if err != nil {\n            errors[i] = err\n            progress.Errors++\n        } else {\n            results[i] = result\n        }\n\n        progress.Completed++\n        if progressCh != nil {\n            progressCh \u003C- progress\n        }\n    }\n\n    return results, errors\n}",{"id":3387,"title":2493,"titles":3388,"content":3389,"level":129},"/v1.0.6/cookbook/extraction-pipelines#next-steps",[1602],"Multi-Turn Conversations - Complex workflowsError Handling - Robust error management html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .soy-K, html code.shiki .soy-K{--shiki-default:#BBBBBB}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .scyPU, html code.shiki .scyPU{--shiki-default:var(--shiki-placeholder)}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}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 pre.shiki code .skxcq, html code.shiki .skxcq{--shiki-default:var(--shiki-builtin)}",{"id":3391,"title":1609,"titles":3392,"content":3393,"level":111},"/v1.0.6/cookbook/multi-turn-conversations",[],"Building complex workflows with session context",{"id":3395,"title":1609,"titles":3396,"content":3397,"level":111},"/v1.0.6/cookbook/multi-turn-conversations#multi-turn-conversations",[],"Patterns for building complex workflows using session context.",{"id":3399,"title":3400,"titles":3401,"content":3402,"level":129},"/v1.0.6/cookbook/multi-turn-conversations#customer-support-agent","Customer Support Agent",[1609],"Multi-step support workflow with context: package main\n\nimport (\n    \"context\"\n    \"fmt\"\n\n    \"github.com/zoobz-io/zyn\"\n)\n\ntype SupportAgent struct {\n    extractor  *zyn.ExtractionSynapse[CustomerIssue]\n    classifier *zyn.ClassificationSynapse\n    responder  *zyn.TransformSynapse\n    resolver   *zyn.BinarySynapse\n}\n\ntype CustomerIssue struct {\n    Name        string `json:\"name\"`\n    Issue       string `json:\"issue\"`\n    ProductArea string `json:\"product_area\"`\n}\n\nfunc (c CustomerIssue) Validate() error {\n    if c.Issue == \"\" {\n        return fmt.Errorf(\"issue description required\")\n    }\n    return nil\n}\n\nfunc NewSupportAgent(provider zyn.Provider) (*SupportAgent, error) {\n    extractor, _ := zyn.Extract[CustomerIssue](\"Extract customer name, issue, and product area\", provider)\n    classifier, _ := zyn.Classification(\"Issue severity\", []string{\"low\", \"medium\", \"high\", \"critical\"}, provider)\n    responder, _ := zyn.Transform(\"Generate empathetic customer service response\", provider)\n    resolver, _ := zyn.Binary(\"Can this issue be resolved with available information?\", provider)\n\n    return &SupportAgent{\n        extractor:  extractor,\n        classifier: classifier,\n        responder:  responder,\n        resolver:   resolver,\n    }, nil\n}\n\ntype SupportResponse struct {\n    CustomerName string\n    Severity     string\n    Response     string\n    NeedsHuman   bool\n}\n\nfunc (a *SupportAgent) HandleTicket(ctx context.Context, customerMessage string) (*SupportResponse, error) {\n    // Shared session for full context\n    session := zyn.NewSession()\n\n    // Step 1: Extract issue details\n    issue, err := a.extractor.Fire(ctx, session, customerMessage)\n    if err != nil {\n        return nil, fmt.Errorf(\"extraction failed: %w\", err)\n    }\n\n    // Step 2: Classify severity (sees extraction context)\n    severity, err := a.classifier.Fire(ctx, session, issue.Issue)\n    if err != nil {\n        return nil, fmt.Errorf(\"classification failed: %w\", err)\n    }\n\n    // Step 3: Check if resolvable (sees full context)\n    resolvable, err := a.resolver.Fire(ctx, session, \"Based on the issue and severity, can this be resolved automatically?\")\n    if err != nil {\n        return nil, fmt.Errorf(\"resolution check failed: %w\", err)\n    }\n\n    // Step 4: Generate response (sees all previous context)\n    prompt := fmt.Sprintf(\"Respond to %s about their %s severity issue regarding %s\",\n        issue.Name, severity, issue.ProductArea)\n    response, err := a.responder.Fire(ctx, session, prompt)\n    if err != nil {\n        return nil, fmt.Errorf(\"response generation failed: %w\", err)\n    }\n\n    return &SupportResponse{\n        CustomerName: issue.Name,\n        Severity:     severity,\n        Response:     response,\n        NeedsHuman:   !resolvable || severity == \"critical\",\n    }, nil\n}",{"id":3404,"title":3405,"titles":3406,"content":3407,"level":129},"/v1.0.6/cookbook/multi-turn-conversations#interview-assistant","Interview Assistant",[1609],"Conduct a multi-question interview: type InterviewAssistant struct {\n    questioner *zyn.TransformSynapse\n    evaluator  *zyn.ClassificationSynapse\n    summarizer *zyn.TransformSynapse\n}\n\ntype InterviewResult struct {\n    Questions   []string\n    Answers     []string\n    Evaluations []string\n    Summary     string\n}\n\nfunc (a *InterviewAssistant) Conduct(ctx context.Context, topic string, numQuestions int) (*InterviewResult, error) {\n    session := zyn.NewSession()\n    result := &InterviewResult{}\n\n    // Initialize context\n    initPrompt := fmt.Sprintf(\"You are conducting an interview about %s. Ask probing questions.\", topic)\n    session.Append(zyn.RoleSystem, initPrompt)\n\n    for i := 0; i \u003C numQuestions; i++ {\n        // Generate question based on previous context\n        question, err := a.questioner.Fire(ctx, session, fmt.Sprintf(\"Ask question %d of %d\", i+1, numQuestions))\n        if err != nil {\n            return nil, err\n        }\n        result.Questions = append(result.Questions, question)\n\n        // Simulate getting answer (in real app, this comes from user)\n        answer := getAnswer(question)  // placeholder\n        result.Answers = append(result.Answers, answer)\n\n        // Add answer to session for context\n        session.Append(zyn.RoleUser, answer)\n\n        // Evaluate answer\n        evaluation, _ := a.evaluator.Fire(ctx, session, \"Evaluate the quality of the last answer\")\n        result.Evaluations = append(result.Evaluations, evaluation)\n    }\n\n    // Final summary with full context\n    result.Summary, _ = a.summarizer.Fire(ctx, session, \"Summarize the interview and key findings\")\n\n    return result, nil\n}",{"id":3409,"title":3410,"titles":3411,"content":3412,"level":129},"/v1.0.6/cookbook/multi-turn-conversations#iterative-refinement","Iterative Refinement",[1609],"Refine output through multiple iterations: type RefiningWriter struct {\n    writer   *zyn.TransformSynapse\n    critic   *zyn.TransformSynapse\n    improver *zyn.TransformSynapse\n}\n\nfunc (r *RefiningWriter) Write(ctx context.Context, prompt string, iterations int) (string, error) {\n    session := zyn.NewSession()\n\n    // Initial draft\n    draft, err := r.writer.Fire(ctx, session, prompt)\n    if err != nil {\n        return \"\", err\n    }\n\n    for i := 0; i \u003C iterations; i++ {\n        // Get critique (sees previous drafts)\n        critique, err := r.critic.Fire(ctx, session, fmt.Sprintf(\"Critique this draft: %s\", draft))\n        if err != nil {\n            return draft, nil  // Return current draft on error\n        }\n\n        // Improve based on critique (sees draft and critique)\n        improved, err := r.improver.Fire(ctx, session, fmt.Sprintf(\"Improve the draft based on this feedback: %s\", critique))\n        if err != nil {\n            return draft, nil\n        }\n\n        draft = improved\n    }\n\n    return draft, nil\n}",{"id":3414,"title":3415,"titles":3416,"content":3417,"level":129},"/v1.0.6/cookbook/multi-turn-conversations#branching-conversations","Branching Conversations",[1609],"Handle different paths based on responses: type DecisionTree struct {\n    decider   *zyn.ClassificationSynapse\n    handlers  map[string]*zyn.TransformSynapse\n}\n\nfunc (d *DecisionTree) Process(ctx context.Context, input string) (string, error) {\n    session := zyn.NewSession()\n\n    // Decide which branch to take\n    decision, err := d.decider.Fire(ctx, session, input)\n    if err != nil {\n        return \"\", err\n    }\n\n    // Get appropriate handler\n    handler, ok := d.handlers[decision]\n    if !ok {\n        return \"\", fmt.Errorf(\"no handler for decision: %s\", decision)\n    }\n\n    // Process with context from decision\n    return handler.Fire(ctx, session, \"Process based on the decision\")\n}",{"id":3419,"title":3420,"titles":3421,"content":3422,"level":129},"/v1.0.6/cookbook/multi-turn-conversations#context-window-management","Context Window Management",[1609],"Handle long conversations: type ConversationManager struct {\n    synapse    *zyn.TransformSynapse\n    summarizer *zyn.TransformSynapse\n    maxMessages int\n}\n\nfunc (m *ConversationManager) Chat(ctx context.Context, session *zyn.Session, userMessage string) (string, error) {\n    // Check if we need to compress history\n    if session.Len() > m.maxMessages {\n        if err := m.compressHistory(ctx, session); err != nil {\n            return \"\", err\n        }\n    }\n\n    return m.synapse.Fire(ctx, session, userMessage)\n}\n\nfunc (m *ConversationManager) compressHistory(ctx context.Context, session *zyn.Session) error {\n    // Get messages to summarize (keep last few)\n    messages := session.Messages()\n    toSummarize := messages[:len(messages)-4]  // Keep last 4\n\n    // Create summary\n    summarySession := zyn.NewSession()\n    summarySession.SetMessages(toSummarize)\n    summary, err := m.summarizer.Fire(ctx, summarySession, \"Summarize this conversation\")\n    if err != nil {\n        return err\n    }\n\n    // Replace with summary + recent messages\n    session.SetMessages(append(\n        []zyn.Message{{Role: zyn.RoleSystem, Content: \"Previous context: \" + summary}},\n        messages[len(messages)-4:]...,\n    ))\n\n    return nil\n}",{"id":3424,"title":3425,"titles":3426,"content":3427,"level":129},"/v1.0.6/cookbook/multi-turn-conversations#parallel-processing-with-shared-context","Parallel Processing with Shared Context",[1609],"Process multiple aspects in parallel, then combine: type ParallelAnalyzer struct {\n    sentiment  *zyn.SentimentSynapse\n    topics     *zyn.ExtractionSynapse[Topics]\n    entities   *zyn.ExtractionSynapse[Entities]\n    summarizer *zyn.TransformSynapse\n}\n\ntype AnalysisResult struct {\n    Sentiment string\n    Topics    []string\n    Entities  []string\n    Summary   string\n}\n\nfunc (a *ParallelAnalyzer) Analyze(ctx context.Context, text string) (*AnalysisResult, error) {\n    var wg sync.WaitGroup\n    var sentiment zyn.SentimentResponse\n    var topics Topics\n    var entities Entities\n    var errs []error\n    var mu sync.Mutex\n\n    // Parallel analysis with independent sessions\n    wg.Add(3)\n\n    go func() {\n        defer wg.Done()\n        s := zyn.NewSession()\n        result, err := a.sentiment.FireWithDetails(ctx, s, text)\n        mu.Lock()\n        if err != nil {\n            errs = append(errs, err)\n        } else {\n            sentiment = result\n        }\n        mu.Unlock()\n    }()\n\n    go func() {\n        defer wg.Done()\n        s := zyn.NewSession()\n        result, err := a.topics.Fire(ctx, s, text)\n        mu.Lock()\n        if err != nil {\n            errs = append(errs, err)\n        } else {\n            topics = result\n        }\n        mu.Unlock()\n    }()\n\n    go func() {\n        defer wg.Done()\n        s := zyn.NewSession()\n        result, err := a.entities.Fire(ctx, s, text)\n        mu.Lock()\n        if err != nil {\n            errs = append(errs, err)\n        } else {\n            entities = result\n        }\n        mu.Unlock()\n    }()\n\n    wg.Wait()\n\n    if len(errs) > 0 {\n        return nil, fmt.Errorf(\"analysis errors: %v\", errs)\n    }\n\n    // Combine results with summarizer (new session with combined context)\n    combineSession := zyn.NewSession()\n    combinedContext := fmt.Sprintf(\"Sentiment: %s\\nTopics: %v\\nEntities: %v\",\n        sentiment.Overall, topics.Items, entities.Items)\n\n    summary, _ := a.summarizer.Fire(ctx, combineSession, \"Summarize these analysis results: \"+combinedContext)\n\n    return &AnalysisResult{\n        Sentiment: sentiment.Overall,\n        Topics:    topics.Items,\n        Entities:  entities.Items,\n        Summary:   summary,\n    }, nil\n}",{"id":3429,"title":2493,"titles":3430,"content":3431,"level":129},"/v1.0.6/cookbook/multi-turn-conversations#next-steps",[1609],"Error Handling - Robust error managementSessions Guide - Session fundamentals html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .soy-K, html code.shiki .soy-K{--shiki-default:#BBBBBB}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .scyPU, html code.shiki .scyPU{--shiki-default:var(--shiki-placeholder)}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 pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}html pre.shiki code .skxcq, html code.shiki .skxcq{--shiki-default:var(--shiki-builtin)}html pre.shiki code .suWN2, html code.shiki .suWN2{--shiki-default:var(--shiki-tag)}",{"id":3433,"title":1616,"titles":3434,"content":3435,"level":111},"/v1.0.6/cookbook/error-handling",[],"Robust error handling patterns for LLM applications",{"id":3437,"title":1616,"titles":3438,"content":3439,"level":111},"/v1.0.6/cookbook/error-handling#error-handling",[],"Patterns for robust error handling in LLM applications.",{"id":3441,"title":3442,"titles":3443,"content":3444,"level":129},"/v1.0.6/cookbook/error-handling#error-types","Error Types",[1616],"zyn errors fall into categories: TypeCauseRecoveryProvider errorsNetwork, rate limits, API failuresRetry, fallbackParse errorsInvalid JSON from LLMRetry, log for analysisValidation errorsLLM output fails validationRetry, adjust promptTimeout errorsLLM took too longRetry, increase timeoutContext errorsContext canceledDon't retry",{"id":3446,"title":3447,"titles":3448,"content":3449,"level":129},"/v1.0.6/cookbook/error-handling#basic-error-handling","Basic Error Handling",[1616],"result, err := synapse.Fire(ctx, session, input)\nif err != nil {\n    switch {\n    case errors.Is(err, context.Canceled):\n        // Context was canceled - don't retry\n        return fmt.Errorf(\"operation canceled\")\n\n    case errors.Is(err, context.DeadlineExceeded):\n        // Timeout - may retry with longer timeout\n        return fmt.Errorf(\"operation timed out\")\n\n    case strings.Contains(err.Error(), \"rate limit\"):\n        // Rate limited - backoff and retry\n        return fmt.Errorf(\"rate limited, please retry later\")\n\n    case strings.Contains(err.Error(), \"validation\"):\n        // LLM output invalid - log for analysis\n        log.Printf(\"Validation error: %v\", err)\n        return fmt.Errorf(\"unable to process request\")\n\n    default:\n        // Unknown error\n        return fmt.Errorf(\"unexpected error: %w\", err)\n    }\n}",{"id":3451,"title":3452,"titles":3453,"content":3454,"level":129},"/v1.0.6/cookbook/error-handling#custom-error-handler-pipeline","Custom Error Handler Pipeline",[1616],"Use pipz for structured error handling: import \"github.com/zoobz-io/pipz\"\n\n// Define identity for the error handler\nvar handleErrorsID = pipz.NewIdentity(\"handle-errors\", \"Handles and categorizes errors\")\n\n// Create error handler\nerrorHandler := pipz.Apply(handleErrorsID,\n    func(ctx context.Context, e *pipz.Error[*zyn.SynapseRequest]) (*pipz.Error[*zyn.SynapseRequest], error) {\n        // Log all errors\n        log.Printf(\"Synapse error: %v (input: %s)\", e.Err, e.Data.Input)\n\n        // Track metrics by error type\n        switch {\n        case strings.Contains(e.Err.Error(), \"rate limit\"):\n            metrics.Increment(\"llm_rate_limit_errors\")\n        case strings.Contains(e.Err.Error(), \"timeout\"):\n            metrics.Increment(\"llm_timeout_errors\")\n        case strings.Contains(e.Err.Error(), \"parse\"):\n            metrics.Increment(\"llm_parse_errors\")\n        default:\n            metrics.Increment(\"llm_other_errors\")\n        }\n\n        // Pass through (don't swallow)\n        return e, nil\n    },\n)\n\n// Apply to synapse\nsynapse, _ := zyn.Binary(\"question\", provider,\n    zyn.WithErrorHandler(errorHandler),\n    zyn.WithRetry(3),\n)",{"id":3456,"title":3457,"titles":3458,"content":3459,"level":129},"/v1.0.6/cookbook/error-handling#graceful-degradation","Graceful Degradation",[1616],"Provide fallback behavior: type DegradingClassifier struct {\n    primary  *zyn.ClassificationSynapse\n    fallback *zyn.ClassificationSynapse\n    default_ string\n}\n\nfunc (c *DegradingClassifier) Classify(ctx context.Context, input string) (string, error) {\n    session := zyn.NewSession()\n\n    // Try primary (complex model)\n    result, err := c.primary.Fire(ctx, session, input)\n    if err == nil {\n        return result, nil\n    }\n    log.Printf(\"Primary failed: %v, trying fallback\", err)\n\n    // Try fallback (simpler model)\n    result, err = c.fallback.Fire(ctx, zyn.NewSession(), input)\n    if err == nil {\n        return result, nil\n    }\n    log.Printf(\"Fallback failed: %v, using default\", err)\n\n    // Return safe default\n    return c.default_, nil\n}",{"id":3461,"title":3462,"titles":3463,"content":3464,"level":129},"/v1.0.6/cookbook/error-handling#retry-with-validation-feedback","Retry with Validation Feedback",[1616],"Retry with context about previous failures: func extractWithRetry[T zyn.Validator](\n    ctx context.Context,\n    synapse *zyn.ExtractionSynapse[T],\n    input string,\n    maxAttempts int,\n) (T, error) {\n    var zero T\n    session := zyn.NewSession()\n\n    for attempt := 1; attempt \u003C= maxAttempts; attempt++ {\n        result, err := synapse.Fire(ctx, session, input)\n\n        if err == nil {\n            return result, nil\n        }\n\n        if attempt \u003C maxAttempts {\n            // Add error context for next attempt\n            session.Append(zyn.RoleUser, fmt.Sprintf(\n                \"Previous attempt failed: %v. Please try again with valid output.\",\n                err,\n            ))\n        }\n    }\n\n    return zero, fmt.Errorf(\"failed after %d attempts\", maxAttempts)\n}",{"id":3466,"title":3467,"titles":3468,"content":3469,"level":129},"/v1.0.6/cookbook/error-handling#circuit-breaker-with-monitoring","Circuit Breaker with Monitoring",[1616],"Track circuit breaker state: type MonitoredSynapse struct {\n    synapse      *zyn.BinarySynapse\n    circuitOpen  atomic.Bool\n    lastFailure  atomic.Value  // time.Time\n}\n\nfunc NewMonitoredSynapse(provider zyn.Provider) (*MonitoredSynapse, error) {\n    ms := &MonitoredSynapse{}\n\n    synapse, err := zyn.Binary(\"question\", provider,\n        zyn.WithCircuitBreaker(5, 30*time.Second),\n        zyn.WithErrorHandler(ms.trackErrors()),\n    )\n    if err != nil {\n        return nil, err\n    }\n\n    ms.synapse = synapse\n    return ms, nil\n}\n\n// Identity for tracking errors\nvar trackErrorsID = pipz.NewIdentity(\"track-errors\", \"Tracks circuit breaker state\")\n\nfunc (ms *MonitoredSynapse) trackErrors() pipz.Chainable[*pipz.Error[*zyn.SynapseRequest]] {\n    return pipz.Apply(trackErrorsID,\n        func(ctx context.Context, e *pipz.Error[*zyn.SynapseRequest]) (*pipz.Error[*zyn.SynapseRequest], error) {\n            if strings.Contains(e.Err.Error(), \"circuit open\") {\n                ms.circuitOpen.Store(true)\n                metrics.Set(\"circuit_breaker_open\", 1)\n            } else {\n                ms.circuitOpen.Store(false)\n                metrics.Set(\"circuit_breaker_open\", 0)\n            }\n            ms.lastFailure.Store(time.Now())\n            return e, nil\n        },\n    )\n}\n\nfunc (ms *MonitoredSynapse) IsHealthy() bool {\n    return !ms.circuitOpen.Load()\n}",{"id":3471,"title":3472,"titles":3473,"content":3474,"level":129},"/v1.0.6/cookbook/error-handling#timeout-escalation","Timeout Escalation",[1616],"Increase timeout on retry: func fireWithEscalatingTimeout(\n    ctx context.Context,\n    provider zyn.Provider,\n    input string,\n    initialTimeout time.Duration,\n    maxAttempts int,\n) (bool, error) {\n    timeout := initialTimeout\n\n    for attempt := 1; attempt \u003C= maxAttempts; attempt++ {\n        // Create synapse with current timeout\n        synapse, _ := zyn.Binary(\"question\", provider,\n            zyn.WithTimeout(timeout),\n        )\n\n        session := zyn.NewSession()\n        result, err := synapse.Fire(ctx, session, input)\n\n        if err == nil {\n            return result, nil\n        }\n\n        if !errors.Is(err, context.DeadlineExceeded) {\n            // Not a timeout - don't escalate\n            return false, err\n        }\n\n        // Escalate timeout for next attempt\n        timeout = timeout * 2\n        log.Printf(\"Attempt %d timed out, escalating to %v\", attempt, timeout)\n    }\n\n    return false, fmt.Errorf(\"exceeded max attempts with timeout escalation\")\n}",{"id":3476,"title":3477,"titles":3478,"content":3479,"level":129},"/v1.0.6/cookbook/error-handling#error-aggregation","Error Aggregation",[1616],"Collect and report errors from batch operations: type BatchErrors struct {\n    Total    int\n    Failed   int\n    ByType   map[string]int\n    Samples  []error\n}\n\nfunc processBatch(ctx context.Context, synapse *zyn.BinarySynapse, inputs []string) (*BatchErrors, []bool) {\n    errors := &BatchErrors{\n        Total:   len(inputs),\n        ByType:  make(map[string]int),\n        Samples: make([]error, 0, 5),\n    }\n    results := make([]bool, len(inputs))\n\n    for i, input := range inputs {\n        session := zyn.NewSession()\n        result, err := synapse.Fire(ctx, session, input)\n\n        if err != nil {\n            errors.Failed++\n            errors.ByType[categorizeError(err)]++\n            if len(errors.Samples) \u003C 5 {\n                errors.Samples = append(errors.Samples, err)\n            }\n        } else {\n            results[i] = result\n        }\n    }\n\n    return errors, results\n}\n\nfunc categorizeError(err error) string {\n    switch {\n    case strings.Contains(err.Error(), \"rate limit\"):\n        return \"rate_limit\"\n    case strings.Contains(err.Error(), \"timeout\"):\n        return \"timeout\"\n    case strings.Contains(err.Error(), \"parse\"):\n        return \"parse\"\n    case strings.Contains(err.Error(), \"validation\"):\n        return \"validation\"\n    default:\n        return \"other\"\n    }\n}",{"id":3481,"title":3482,"titles":3483,"content":3484,"level":129},"/v1.0.6/cookbook/error-handling#observability-integration","Observability Integration",[1616],"Log errors with full context: import \"github.com/zoobz-io/capitan\"\n\n// Track all failures\ncapitan.Hook(zyn.RequestFailed, func(ctx context.Context, e *capitan.Event) {\n    requestID, _ := zyn.RequestIDKey.From(e)\n    synapseType, _ := zyn.SynapseTypeKey.From(e)\n    task, _ := zyn.PromptTaskKey.From(e)\n    err, _ := zyn.ErrorKey.From(e)\n\n    log.Printf(\"REQUEST_FAILED request_id=%s type=%s task=%q error=%s\",\n        requestID, synapseType, task, err)\n\n    metrics.Increment(\"synapse_failures\",\n        \"type\", synapseType,\n        \"error_category\", categorizeError(fmt.Errorf(err)),\n    )\n})\n\n// Track parse/validation failures separately\ncapitan.Hook(zyn.ResponseParseFailed, func(ctx context.Context, e *capitan.Event) {\n    requestID, _ := zyn.RequestIDKey.From(e)\n    errorType, _ := zyn.ErrorTypeKey.From(e)\n    response, _ := zyn.ResponseKey.From(e)\n\n    log.Printf(\"RESPONSE_PARSE_FAILED request_id=%s error_type=%s response=%s\",\n        requestID, errorType, truncate(response, 200))\n\n    // These warrant investigation - LLM producing invalid output\n    if errorType == \"parse_error\" {\n        alerting.Warn(\"LLM parse error\", map[string]string{\n            \"request_id\": requestID,\n            \"response\":   truncate(response, 500),\n        })\n    }\n})",{"id":3486,"title":2493,"titles":3487,"content":3488,"level":129},"/v1.0.6/cookbook/error-handling#next-steps",[1616],"Reliability Guide - Built-in reliability patternsObservability Guide - Monitoring setup html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .scyPU, html code.shiki .scyPU{--shiki-default:var(--shiki-placeholder)}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 pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .skxcq, html code.shiki .skxcq{--shiki-default:var(--shiki-builtin)}",{"id":3490,"title":1628,"titles":3491,"content":3492,"level":111},"/v1.0.6/reference/cheatsheet",[],"Quick reference for zyn API",{"id":3494,"title":1628,"titles":3495,"content":3496,"level":111},"/v1.0.6/reference/cheatsheet#cheatsheet",[],"Quick reference for zyn.",{"id":3498,"title":3499,"titles":3500,"content":3501,"level":129},"/v1.0.6/reference/cheatsheet#synapse-types","Synapse Types",[1628],"SynapseInputOutputConstructorBinarystringboolzyn.Binary(task, provider, opts...)Classificationstringstringzyn.Classification(task, categories, provider, opts...)Rankingstringstringzyn.Ranking(criteria, provider, opts...)SentimentstringSentimentResultzyn.Sentiment(task, provider, opts...)ExtractTstringTzyn.Extract[T](task, provider, opts...)Transformstringstringzyn.Transform(task, provider, opts...)AnalyzeTTstringzyn.Analyze[T](task, provider, opts...)ConvertT,UTUzyn.Convert[T,U](task, provider, opts...)",{"id":3503,"title":3504,"titles":3505,"content":103,"level":129},"/v1.0.6/reference/cheatsheet#quick-start-patterns","Quick Start Patterns",[1628],{"id":3507,"title":2529,"titles":3508,"content":3509,"level":143},"/v1.0.6/reference/cheatsheet#binary-decision",[1628,3504],"synapse, _ := zyn.Binary(\"Is this valid?\", provider)\nsession := zyn.NewSession()\nresult, _ := synapse.Fire(ctx, session, \"input\")\n// result: bool",{"id":3511,"title":443,"titles":3512,"content":3513,"level":143},"/v1.0.6/reference/cheatsheet#classification",[1628,3504],"synapse, _ := zyn.Classification(\"Classify type\", []string{\"a\", \"b\", \"c\"}, provider)\nsession := zyn.NewSession()\nresult, _ := synapse.Fire(ctx, session, \"input\")\n// result: string (one of categories)",{"id":3515,"title":3516,"titles":3517,"content":3518,"level":143},"/v1.0.6/reference/cheatsheet#extraction","Extraction",[1628,3504],"type Data struct {\n    Field string `json:\"field\"`\n}\nfunc (d Data) Validate() error { return nil }\n\nsynapse, _ := zyn.Extract[Data](\"Extract data\", provider)\nsession := zyn.NewSession()\nresult, _ := synapse.Fire(ctx, session, \"input\")\n// result: Data",{"id":3520,"title":545,"titles":3521,"content":3522,"level":143},"/v1.0.6/reference/cheatsheet#transform",[1628,3504],"synapse, _ := zyn.Transform(\"Translate to Spanish\", provider)\nsession := zyn.NewSession()\nresult, _ := synapse.Fire(ctx, session, \"Hello\")\n// result: string",{"id":3524,"title":1640,"titles":3525,"content":3526,"level":129},"/v1.0.6/reference/cheatsheet#options",[1628],"// Reliability\nzyn.WithRetry(3)                              // Retry up to 3 times\nzyn.WithBackoff(3, 100*time.Millisecond)      // Exponential backoff\nzyn.WithTimeout(10*time.Second)               // Timeout\nzyn.WithCircuitBreaker(5, 30*time.Second)     // Circuit breaker\nzyn.WithRateLimit(10, 100)                    // Rate limiting\nzyn.WithFallback(backupSynapse)               // Fallback synapse\n\n// Behavior\nzyn.WithErrorHandler(errorPipeline)           // Custom error handling",{"id":3528,"title":3529,"titles":3530,"content":3531,"level":129},"/v1.0.6/reference/cheatsheet#temperature-constants","Temperature Constants",[1628],"// Set via input struct, not synapse option\nzyn.DefaultTemperatureDeterministic = 0.1  // Binary, Extract, Convert\nzyn.DefaultTemperatureAnalytical    = 0.2  // Sentiment, Ranking, Analyze\nzyn.DefaultTemperatureCreative      = 0.3  // Classification, Transform\nzyn.TemperatureUnset                = -1   // Use synapse default\nzyn.TemperatureZero                 = 0.0001 // Near-zero (0.0 = unset)",{"id":3533,"title":2594,"titles":3534,"content":3535,"level":129},"/v1.0.6/reference/cheatsheet#session-operations",[1628],"session := zyn.NewSession()\n\n// Read\nmessages := session.Messages()    // []Message\ncount := session.Len()            // int\nmsg, _ := session.At(0)           // Message at index\nusage := session.LastUsage()      // *TokenUsage\n\n// Write\nsession.Append(role, content)     // Add message\nsession.Clear()                   // Remove all\nsession.Remove(index)             // Remove at index\nsession.Replace(index, msg)       // Replace at index\nsession.Insert(index, msg)        // Insert at index\n\n// Bulk\nsession.Prune(n)                  // Remove last n message pairs (n*2 messages)\nsession.Truncate(first, last)     // Keep first n and last m\nsession.SetMessages(msgs)         // Replace all\nsession.SetUsage(usage)           // Set token usage",{"id":3537,"title":3538,"titles":3539,"content":3540,"level":129},"/v1.0.6/reference/cheatsheet#message-types","Message Types",[1628],"type Message struct {\n    Role    string\n    Content string\n}\n\n// Roles\nzyn.RoleUser\nzyn.RoleAssistant\nzyn.RoleSystem",{"id":3542,"title":2608,"titles":3543,"content":3544,"level":129},"/v1.0.6/reference/cheatsheet#provider-interface",[1628],"type Provider interface {\n    Call(ctx context.Context, messages []Message, temperature float32) (*ProviderResponse, error)\n    Name() string\n}\n\ntype ProviderResponse struct {\n    Content string\n    Usage   TokenUsage\n}\n\ntype TokenUsage struct {\n    Prompt     int\n    Completion int\n    Total      int\n}",{"id":3546,"title":1555,"titles":3547,"content":103,"level":129},"/v1.0.6/reference/cheatsheet#providers",[1628],{"id":3549,"title":2730,"titles":3550,"content":3551,"level":143},"/v1.0.6/reference/cheatsheet#openai",[1628,1555],"import \"github.com/zoobz-io/zyn/openai\"\n\nprovider := openai.New(openai.Config{\n    APIKey: os.Getenv(\"OPENAI_API_KEY\"),\n    Model:  \"gpt-4o\",  // defaults to \"gpt-3.5-turbo\"\n})",{"id":3553,"title":3554,"titles":3555,"content":3556,"level":143},"/v1.0.6/reference/cheatsheet#mock-testing","Mock (Testing)",[1628,1555],"// Fixed response\nprovider := zyn.NewMockProviderWithResponse(`{\"decision\": true, ...}`)\n\n// Dynamic\nprovider := zyn.NewMockProviderWithCallback(func(p string, t float32) (string, error) {\n    return `{\"decision\": true, ...}`, nil\n})\n\n// Error\nprovider := zyn.NewMockProviderWithError(\"rate limit exceeded\")",{"id":3558,"title":3559,"titles":3560,"content":3561,"level":129},"/v1.0.6/reference/cheatsheet#validator-interface","Validator Interface",[1628],"type Validator interface {\n    Validate() error\n} All custom types used with Extract, Analyze, or Convert must implement this.",{"id":3563,"title":3564,"titles":3565,"content":3566,"level":129},"/v1.0.6/reference/cheatsheet#observability-signals","Observability Signals",[1628],"zyn.RequestStarted         // Before pipeline\nzyn.RequestCompleted       // After success\nzyn.RequestFailed          // After pipeline failure\nzyn.ResponseParseFailed    // After parse/validation error\nzyn.ProviderCallStarted    // Before HTTP call\nzyn.ProviderCallCompleted  // After HTTP success\nzyn.ProviderCallFailed     // After HTTP failure",{"id":3568,"title":3569,"titles":3570,"content":3571,"level":129},"/v1.0.6/reference/cheatsheet#hook-keys","Hook Keys",[1628],"// Request fields\nzyn.RequestIDKey      // string\nzyn.SynapseTypeKey    // string\nzyn.InputKey          // string\nzyn.OutputKey         // string\nzyn.ErrorKey          // string\n\n// Provider fields\nzyn.ProviderKey       // string\nzyn.ModelKey          // string\nzyn.TotalTokensKey    // int\nzyn.DurationMsKey     // int\nzyn.HTTPStatusCodeKey // int",{"id":3573,"title":3574,"titles":3575,"content":3576,"level":129},"/v1.0.6/reference/cheatsheet#decision-tree-which-synapse","Decision Tree: Which Synapse?",[1628],"Need yes/no answer?\n├─ Yes → Binary\n└─ No\n   └─ Pick from fixed options?\n      ├─ Yes → Classification\n      └─ No\n         └─ Order items?\n            ├─ Yes → Ranking\n            └─ No\n               └─ Analyze sentiment?\n                  ├─ Yes → Sentiment\n                  └─ No\n                     └─ Extract structured data?\n                        ├─ Yes → Extract[T]\n                        └─ No\n                           └─ Transform text?\n                              ├─ Yes → Transform\n                              └─ No\n                                 └─ Analyze struct → text?\n                                    ├─ Yes → Analyze[T]\n                                    └─ No → Convert[T,U]",{"id":3578,"title":3039,"titles":3579,"content":103,"level":129},"/v1.0.6/reference/cheatsheet#common-patterns",[1628],{"id":3581,"title":3582,"titles":3583,"content":3584,"level":143},"/v1.0.6/reference/cheatsheet#synapse-with-reliability","Synapse with Reliability",[1628,3039],"synapse, _ := zyn.Binary(\"question\", provider,\n    zyn.WithRetry(3),\n    zyn.WithTimeout(10*time.Second),\n    zyn.WithCircuitBreaker(5, 30*time.Second),\n)",{"id":3586,"title":3587,"titles":3588,"content":3589,"level":143},"/v1.0.6/reference/cheatsheet#multi-step-workflow","Multi-Step Workflow",[1628,3039],"session := zyn.NewSession()\nstep1.Fire(ctx, session, input)\nstep2.Fire(ctx, session, \"continue\")  // sees step1 context\nstep3.Fire(ctx, session, \"finish\")    // sees all context",{"id":3591,"title":3267,"titles":3592,"content":3593,"level":143},"/v1.0.6/reference/cheatsheet#track-token-usage",[1628,3039],"capitan.Hook(zyn.ProviderCallCompleted, func(ctx context.Context, e *capitan.Event) {\n    tokens, _ := zyn.TotalTokensKey.From(e)\n    log.Printf(\"Used %d tokens\", tokens)\n}) html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}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 pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}html pre.shiki code .scyPU, html code.shiki .scyPU{--shiki-default:var(--shiki-placeholder)}",{"id":3595,"title":3596,"titles":3597,"content":3598,"level":111},"/v1.0.6/reference/synapses/analyze","Analyze Synapse",[],"Analyze structured data and produce text analysis",{"id":3600,"title":3596,"titles":3601,"content":3602,"level":111},"/v1.0.6/reference/synapses/analyze#analyze-synapse",[],"Analyze structured data and produce text analysis.",{"id":3604,"title":3605,"titles":3606,"content":3607,"level":129},"/v1.0.6/reference/synapses/analyze#constructor","Constructor",[3596],"func Analyze[T any](task string, provider Provider, opts ...Option) (*AnalyzeSynapse[T], error) Type Parameter: T - Struct type to analyze (no Validator required for input) Parameters: task - Description of the analysisprovider - LLM provideropts - Optional configuration Returns: *AnalyzeSynapse[T] - The configured synapseerror - Configuration error",{"id":3609,"title":3610,"titles":3611,"content":103,"level":129},"/v1.0.6/reference/synapses/analyze#methods","Methods",[3596],{"id":3613,"title":377,"titles":3614,"content":3615,"level":143},"/v1.0.6/reference/synapses/analyze#fire",[3596,3610],"func (s *AnalyzeSynapse[T]) Fire(ctx context.Context, session *Session, input T) (string, error) Execute and return analysis text. Returns: string - Analysis texterror - Execution error",{"id":3617,"title":3618,"titles":3619,"content":3620,"level":143},"/v1.0.6/reference/synapses/analyze#firewithdetails","FireWithDetails",[3596,3610],"func (s *AnalyzeSynapse[T]) FireWithDetails(ctx context.Context, session *Session, input T) (*AnalyzeResponse, error) Execute and return full response.",{"id":3622,"title":3623,"titles":3624,"content":3625,"level":129},"/v1.0.6/reference/synapses/analyze#response-type","Response Type",[3596],"type AnalyzeResponse struct {\n    Analysis   string   `json:\"analysis\"`\n    Confidence float64  `json:\"confidence\"`\n    Reasoning  []string `json:\"reasoning\"`\n}",{"id":3627,"title":3628,"titles":3629,"content":103,"level":129},"/v1.0.6/reference/synapses/analyze#examples","Examples",[3596],{"id":3631,"title":3015,"titles":3632,"content":3633,"level":143},"/v1.0.6/reference/synapses/analyze#basic-usage",[3596,3628],"type ServerMetrics struct {\n    CPU      float64 `json:\"cpu_usage\"`\n    Memory   float64 `json:\"memory_usage\"`\n    DiskIO   float64 `json:\"disk_io\"`\n    Requests int     `json:\"requests_per_second\"`\n}\n\nanalyzer, _ := zyn.Analyze[ServerMetrics](\"system performance analysis\", provider)\nsession := zyn.NewSession()\n\nmetrics := ServerMetrics{\n    CPU:      85.5,\n    Memory:   72.3,\n    DiskIO:   45.0,\n    Requests: 1200,\n}\n\nanalysis, err := analyzer.Fire(ctx, session, metrics)\n// analysis: \"CPU usage is high at 85.5%, which may indicate a processing bottleneck.\n//            Memory usage at 72.3% is within acceptable range but should be monitored.\n//            Consider scaling horizontally to handle the 1200 req/s load.\"",{"id":3635,"title":3636,"titles":3637,"content":3638,"level":143},"/v1.0.6/reference/synapses/analyze#financial-analysis","Financial Analysis",[3596,3628],"type QuarterlyReport struct {\n    Revenue    float64 `json:\"revenue\"`\n    Expenses   float64 `json:\"expenses\"`\n    Growth     float64 `json:\"growth_percent\"`\n    NewClients int     `json:\"new_clients\"`\n}\n\nanalyzer, _ := zyn.Analyze[QuarterlyReport](\"business performance summary\", provider)\n\nreport := QuarterlyReport{\n    Revenue:    1500000,\n    Expenses:   1200000,\n    Growth:     12.5,\n    NewClients: 45,\n}\n\nanalysis, err := analyzer.Fire(ctx, session, report)",{"id":3640,"title":3641,"titles":3642,"content":3643,"level":143},"/v1.0.6/reference/synapses/analyze#with-context","With Context",[3596,3628],"// Add historical context\nsession := zyn.NewSession()\nsession.Append(zyn.RoleUser, \"Previous quarter had 8% growth and 30 new clients\")\n\n// Analysis will consider historical context\nanalysis, err := analyzer.Fire(ctx, session, currentReport)\n// analysis references improvement from previous quarter",{"id":3645,"title":3646,"titles":3647,"content":3648,"level":129},"/v1.0.6/reference/synapses/analyze#use-cases","Use Cases",[3596],"System monitoring summariesFinancial report analysisPerformance reviewsAudit summariesData interpretation html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}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 pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .scyPU, html code.shiki .scyPU{--shiki-default:var(--shiki-placeholder)}",{"id":3650,"title":3651,"titles":3652,"content":3653,"level":111},"/v1.0.6/reference/synapses/binary","Binary Synapse",[],"Yes/no decisions with confidence scores",{"id":3655,"title":3651,"titles":3656,"content":3657,"level":111},"/v1.0.6/reference/synapses/binary#binary-synapse",[],"Yes/no decisions with confidence scores.",{"id":3659,"title":3605,"titles":3660,"content":3661,"level":129},"/v1.0.6/reference/synapses/binary#constructor",[3651],"func Binary(task string, provider Provider, opts ...Option) (*BinarySynapse, error) Parameters: task - Description of the decision to makeprovider - LLM provideropts - Optional configuration Returns: *BinarySynapse - The configured synapseerror - Configuration error",{"id":3663,"title":3610,"titles":3664,"content":103,"level":129},"/v1.0.6/reference/synapses/binary#methods",[3651],{"id":3666,"title":377,"titles":3667,"content":3668,"level":143},"/v1.0.6/reference/synapses/binary#fire",[3651,3610],"func (s *BinarySynapse) Fire(ctx context.Context, session *Session, input string) (bool, error) Execute the synapse and return the boolean decision. Parameters: ctx - Context for cancellation/timeoutsession - Session for conversation contextinput - Text to evaluate Returns: bool - The decision (true/false)error - Execution error",{"id":3670,"title":3618,"titles":3671,"content":3672,"level":143},"/v1.0.6/reference/synapses/binary#firewithdetails",[3651,3610],"func (s *BinarySynapse) FireWithDetails(ctx context.Context, session *Session, input string) (*BinaryResponse, error) Execute and return full response including confidence and reasoning. Returns: *BinaryResponse - Full responseerror - Execution error",{"id":3674,"title":3623,"titles":3675,"content":3676,"level":129},"/v1.0.6/reference/synapses/binary#response-type",[3651],"type BinaryResponse struct {\n    Decision   bool     `json:\"decision\"`\n    Confidence float64  `json:\"confidence\"`\n    Reasoning  []string `json:\"reasoning\"`\n}",{"id":3678,"title":3628,"titles":3679,"content":103,"level":129},"/v1.0.6/reference/synapses/binary#examples",[3651],{"id":3681,"title":3015,"titles":3682,"content":3683,"level":143},"/v1.0.6/reference/synapses/binary#basic-usage",[3651,3628],"validator, _ := zyn.Binary(\"Is this a valid email address?\", provider)\nsession := zyn.NewSession()\n\nresult, err := validator.Fire(ctx, session, \"user@example.com\")\n// result: true",{"id":3685,"title":3686,"titles":3687,"content":3688,"level":143},"/v1.0.6/reference/synapses/binary#with-details","With Details",[3651,3628],"validator, _ := zyn.Binary(\"Is this a valid email address?\", provider)\nsession := zyn.NewSession()\n\nresponse, err := validator.FireWithDetails(ctx, session, \"not-an-email\")\n// response.Decision: false\n// response.Confidence: 0.95\n// response.Reasoning: [\"Missing @ symbol\", \"No domain present\"]",{"id":3690,"title":3691,"titles":3692,"content":3693,"level":143},"/v1.0.6/reference/synapses/binary#with-options","With Options",[3651,3628],"validator, _ := zyn.Binary(\"Is this appropriate content?\", provider,\n    zyn.WithRetry(3),\n    zyn.WithBackoff(3, 100*time.Millisecond),\n)",{"id":3695,"title":3646,"titles":3696,"content":3697,"level":129},"/v1.0.6/reference/synapses/binary#use-cases",[3651],"Email validationContent moderationFeature flag decisionsApproval workflowsData quality checks html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}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 pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}",{"id":3699,"title":3700,"titles":3701,"content":3702,"level":111},"/v1.0.6/reference/synapses/classification","Classification Synapse",[],"Categorize text into predefined classes",{"id":3704,"title":3700,"titles":3705,"content":3706,"level":111},"/v1.0.6/reference/synapses/classification#classification-synapse",[],"Categorize text into predefined classes.",{"id":3708,"title":3605,"titles":3709,"content":3710,"level":129},"/v1.0.6/reference/synapses/classification#constructor",[3700],"func Classification(task string, categories []string, provider Provider, opts ...Option) (*ClassificationSynapse, error) Parameters: task - Description of what to classifycategories - Valid category optionsprovider - LLM provideropts - Optional configuration Returns: *ClassificationSynapse - The configured synapseerror - Configuration error",{"id":3712,"title":3610,"titles":3713,"content":103,"level":129},"/v1.0.6/reference/synapses/classification#methods",[3700],{"id":3715,"title":377,"titles":3716,"content":3717,"level":143},"/v1.0.6/reference/synapses/classification#fire",[3700,3610],"func (s *ClassificationSynapse) Fire(ctx context.Context, session *Session, input string) (string, error) Execute and return the primary category. Returns: string - Primary category (one of the provided categories)error - Execution error",{"id":3719,"title":3720,"titles":3721,"content":3722,"level":143},"/v1.0.6/reference/synapses/classification#firewithinput","FireWithInput",[3700,3610],"func (s *ClassificationSynapse) FireWithInput(ctx context.Context, session *Session, input ClassificationInput) (string, error) Execute with structured input including examples.",{"id":3724,"title":3618,"titles":3725,"content":3726,"level":143},"/v1.0.6/reference/synapses/classification#firewithdetails",[3700,3610],"func (s *ClassificationSynapse) FireWithDetails(ctx context.Context, session *Session, input string) (*ClassificationResponse, error) Execute and return full response.",{"id":3728,"title":3729,"titles":3730,"content":3731,"level":129},"/v1.0.6/reference/synapses/classification#types","Types",[3700],"type ClassificationInput struct {\n    Subject  string              // Text to classify\n    Examples map[string][]string // Optional examples per category\n}\n\ntype ClassificationResponse struct {\n    Primary    string   `json:\"primary\"`\n    Secondary  string   `json:\"secondary,omitempty\"`\n    Confidence float64  `json:\"confidence\"`\n    Reasoning  []string `json:\"reasoning\"`\n}",{"id":3733,"title":3628,"titles":3734,"content":103,"level":129},"/v1.0.6/reference/synapses/classification#examples",[3700],{"id":3736,"title":3015,"titles":3737,"content":3738,"level":143},"/v1.0.6/reference/synapses/classification#basic-usage",[3700,3628],"classifier, _ := zyn.Classification(\n    \"What type of email is this?\",\n    []string{\"spam\", \"urgent\", \"newsletter\", \"personal\"},\n    provider,\n)\nsession := zyn.NewSession()\n\nresult, err := classifier.Fire(ctx, session, \"URGENT: Your account will be suspended!\")\n// result: \"urgent\"",{"id":3740,"title":3741,"titles":3742,"content":3743,"level":143},"/v1.0.6/reference/synapses/classification#with-examples","With Examples",[3700,3628],"input := zyn.ClassificationInput{\n    Subject: \"Great product, fast shipping!\",\n    Examples: map[string][]string{\n        \"positive\": {\"Love it!\", \"Excellent quality\"},\n        \"negative\": {\"Terrible\", \"Waste of money\"},\n        \"neutral\":  {\"It's okay\", \"As expected\"},\n    },\n}\n\nresult, err := classifier.FireWithInput(ctx, session, input)\n// result: \"positive\"",{"id":3745,"title":3686,"titles":3746,"content":3747,"level":143},"/v1.0.6/reference/synapses/classification#with-details",[3700,3628],"response, err := classifier.FireWithDetails(ctx, session, \"Check out this amazing deal!\")\n// response.Primary: \"spam\"\n// response.Secondary: \"promotional\"\n// response.Confidence: 0.87\n// response.Reasoning: [\"Contains promotional language\", \"Urgency tactics\"]",{"id":3749,"title":3646,"titles":3750,"content":3751,"level":129},"/v1.0.6/reference/synapses/classification#use-cases",[3700],"Email routingSupport ticket triageContent categorizationSentiment analysis (simple)Intent detection html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}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 pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}",{"id":3753,"title":3754,"titles":3755,"content":3756,"level":111},"/v1.0.6/reference/synapses/convert","Convert Synapse",[],"Convert between struct types",{"id":3758,"title":3754,"titles":3759,"content":3760,"level":111},"/v1.0.6/reference/synapses/convert#convert-synapse",[],"Convert between struct types with LLM intelligence.",{"id":3762,"title":3605,"titles":3763,"content":3764,"level":129},"/v1.0.6/reference/synapses/convert#constructor",[3754],"func Convert[TIn any, TOut Validator](task string, provider Provider, opts ...Option) (*ConvertSynapse[TIn, TOut], error) Type Parameters: TIn - Input struct typeTOut - Output struct type (must implement Validator) Parameters: task - Description of the conversionprovider - LLM provideropts - Optional configuration Returns: *ConvertSynapse[TIn, TOut] - The configured synapseerror - Configuration error",{"id":3766,"title":3610,"titles":3767,"content":103,"level":129},"/v1.0.6/reference/synapses/convert#methods",[3754],{"id":3769,"title":377,"titles":3770,"content":3771,"level":143},"/v1.0.6/reference/synapses/convert#fire",[3754,3610],"func (s *ConvertSynapse[TIn, TOut]) Fire(ctx context.Context, session *Session, input TIn) (*TOut, error) Execute and return converted struct. Returns: *TOut - Converted and validated structerror - Execution or validation error",{"id":3773,"title":3618,"titles":3774,"content":3775,"level":143},"/v1.0.6/reference/synapses/convert#firewithdetails",[3754,3610],"func (s *ConvertSynapse[TIn, TOut]) FireWithDetails(ctx context.Context, session *Session, input TIn) (*ConvertResponse[TOut], error) Execute and return full response.",{"id":3777,"title":3623,"titles":3778,"content":3779,"level":129},"/v1.0.6/reference/synapses/convert#response-type",[3754],"type ConvertResponse[T any] struct {\n    Data       T        `json:\"data\"`\n    Confidence float64  `json:\"confidence\"`\n    Reasoning  []string `json:\"reasoning\"`\n}",{"id":3781,"title":3628,"titles":3782,"content":103,"level":129},"/v1.0.6/reference/synapses/convert#examples",[3754],{"id":3784,"title":3785,"titles":3786,"content":3787,"level":143},"/v1.0.6/reference/synapses/convert#schema-migration","Schema Migration",[3754,3628],"type UserV1 struct {\n    Name      string `json:\"name\"`\n    Email     string `json:\"email\"`\n    BirthDate string `json:\"birth_date\"` // \"1990-05-15\"\n}\n\ntype UserV2 struct {\n    FullName string `json:\"full_name\"`\n    Contact  struct {\n        Email string `json:\"email\"`\n    } `json:\"contact\"`\n    Age int `json:\"age\"`\n}\n\nfunc (u UserV2) Validate() error {\n    if u.FullName == \"\" {\n        return fmt.Errorf(\"full name required\")\n    }\n    return nil\n}\n\nconverter, _ := zyn.Convert[UserV1, UserV2](\"migrate to v2 schema\", provider)\nsession := zyn.NewSession()\n\nv1User := UserV1{\n    Name:      \"John Doe\",\n    Email:     \"john@example.com\",\n    BirthDate: \"1990-05-15\",\n}\n\nv2User, err := converter.Fire(ctx, session, v1User)\n// v2User: &UserV2{\n//     FullName: \"John Doe\",\n//     Contact:  {Email: \"john@example.com\"},\n//     Age:      34,  // Calculated from BirthDate\n// }",{"id":3789,"title":3790,"titles":3791,"content":3792,"level":143},"/v1.0.6/reference/synapses/convert#format-conversion","Format Conversion",[3754,3628],"type CSVRow struct {\n    Col1 string `json:\"col1\"`\n    Col2 string `json:\"col2\"`\n    Col3 string `json:\"col3\"`\n}\n\ntype StructuredData struct {\n    Name     string  `json:\"name\"`\n    Quantity int     `json:\"quantity\"`\n    Price    float64 `json:\"price\"`\n}\n\nfunc (s StructuredData) Validate() error {\n    if s.Name == \"\" {\n        return fmt.Errorf(\"name required\")\n    }\n    return nil\n}\n\nconverter, _ := zyn.Convert[CSVRow, StructuredData](\"parse CSV columns\", provider)\n\nrow := CSVRow{Col1: \"Widget\", Col2: \"100\", Col3: \"$19.99\"}\ndata, err := converter.Fire(ctx, session, row)\n// data: &StructuredData{Name: \"Widget\", Quantity: 100, Price: 19.99}",{"id":3794,"title":3795,"titles":3796,"content":3797,"level":143},"/v1.0.6/reference/synapses/convert#api-response-normalization","API Response Normalization",[3754,3628],"type ExternalAPIResponse struct {\n    StatusCode int               `json:\"status_code\"`\n    Payload    map[string]any    `json:\"payload\"`\n    Metadata   map[string]string `json:\"metadata\"`\n}\n\ntype NormalizedResponse struct {\n    Success bool   `json:\"success\"`\n    Data    string `json:\"data\"`\n    Error   string `json:\"error,omitempty\"`\n}\n\nfunc (n NormalizedResponse) Validate() error { return nil }\n\nconverter, _ := zyn.Convert[ExternalAPIResponse, NormalizedResponse](\n    \"normalize API response to standard format\",\n    provider,\n)",{"id":3799,"title":3646,"titles":3800,"content":3801,"level":129},"/v1.0.6/reference/synapses/convert#use-cases",[3754],"Schema migrationsAPI response normalizationData format conversionLegacy system integrationData enrichment/transformation html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}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 pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}",{"id":3803,"title":3804,"titles":3805,"content":3806,"level":111},"/v1.0.6/reference/synapses/extraction","Extraction Synapse",[],"Extract structured data from text",{"id":3808,"title":3804,"titles":3809,"content":3810,"level":111},"/v1.0.6/reference/synapses/extraction#extraction-synapse",[],"Extract structured data from unstructured text.",{"id":3812,"title":3605,"titles":3813,"content":3814,"level":129},"/v1.0.6/reference/synapses/extraction#constructor",[3804],"func Extract[T Validator](task string, provider Provider, opts ...Option) (*ExtractionSynapse[T], error) Type Parameter: T - Struct type to extract (must implement Validator) Parameters: task - Description of what to extractprovider - LLM provideropts - Optional configuration Returns: *ExtractionSynapse[T] - The configured synapseerror - Configuration error",{"id":3816,"title":3610,"titles":3817,"content":103,"level":129},"/v1.0.6/reference/synapses/extraction#methods",[3804],{"id":3819,"title":377,"titles":3820,"content":3821,"level":143},"/v1.0.6/reference/synapses/extraction#fire",[3804,3610],"func (s *ExtractionSynapse[T]) Fire(ctx context.Context, session *Session, text string) (T, error) Execute and return extracted struct. Returns: T - Extracted and validated structerror - Execution or validation error",{"id":3823,"title":3720,"titles":3824,"content":3825,"level":143},"/v1.0.6/reference/synapses/extraction#firewithinput",[3804,3610],"func (s *ExtractionSynapse[T]) FireWithInput(ctx context.Context, session *Session, input ExtractionInput) (T, error) Execute with rich input structure.",{"id":3827,"title":3828,"titles":3829,"content":3830,"level":143},"/v1.0.6/reference/synapses/extraction#withdefaults","WithDefaults",[3804,3610],"func (s *ExtractionSynapse[T]) WithDefaults(defaults ExtractionInput) *ExtractionSynapse[T] Set default input values that are merged with user input at execution time.",{"id":3832,"title":3833,"titles":3834,"content":3835,"level":129},"/v1.0.6/reference/synapses/extraction#input-type","Input Type",[3804],"type ExtractionInput struct {\n    Text        string  // The text to extract from\n    Context     string  // Additional context\n    Examples    string  // Example extractions (newline-separated)\n    Temperature float32 // LLM temperature setting\n}",{"id":3837,"title":3628,"titles":3838,"content":103,"level":129},"/v1.0.6/reference/synapses/extraction#examples",[3804],{"id":3840,"title":3015,"titles":3841,"content":3842,"level":143},"/v1.0.6/reference/synapses/extraction#basic-usage",[3804,3628],"type Contact struct {\n    Name  string `json:\"name\"`\n    Email string `json:\"email\"`\n    Phone string `json:\"phone,omitempty\"`\n}\n\nfunc (c Contact) Validate() error {\n    if c.Name == \"\" {\n        return fmt.Errorf(\"name required\")\n    }\n    if c.Email == \"\" {\n        return fmt.Errorf(\"email required\")\n    }\n    return nil\n}\n\nextractor, _ := zyn.Extract[Contact](\"contact information\", provider)\nsession := zyn.NewSession()\n\ncontact, err := extractor.Fire(ctx, session, \"John Doe at john@example.com, call (555) 123-4567\")\n// contact: Contact{Name: \"John Doe\", Email: \"john@example.com\", Phone: \"(555) 123-4567\"}",{"id":3844,"title":3845,"titles":3846,"content":3847,"level":143},"/v1.0.6/reference/synapses/extraction#with-nested-structs","With Nested Structs",[3804,3628],"type Address struct {\n    Street  string `json:\"street\"`\n    City    string `json:\"city\"`\n    Country string `json:\"country\"`\n}\n\ntype Company struct {\n    Name    string  `json:\"name\"`\n    Address Address `json:\"address\"`\n}\n\nfunc (c Company) Validate() error {\n    if c.Name == \"\" {\n        return fmt.Errorf(\"company name required\")\n    }\n    return nil\n}\n\nextractor, _ := zyn.Extract[Company](\"company information\", provider)",{"id":3849,"title":3850,"titles":3851,"content":3852,"level":143},"/v1.0.6/reference/synapses/extraction#with-json-tags","With JSON Tags",[3804,3628],"Use json tags to control field names and optionality: type Order struct {\n    ID          string  `json:\"order_id\"`           // Maps to \"order_id\" in JSON\n    Amount      float64 `json:\"amount\"`\n    Description string  `json:\"description,omitempty\"` // Optional\n}",{"id":3854,"title":3855,"titles":3856,"content":3857,"level":143},"/v1.0.6/reference/synapses/extraction#with-description-tags","With Description Tags",[3804,3628],"Use description tags for LLM guidance: type Product struct {\n    Name  string  `json:\"name\" description:\"Product name without brand\"`\n    Price float64 `json:\"price\" description:\"Price in USD\"`\n    SKU   string  `json:\"sku\" description:\"Stock keeping unit code\"`\n}",{"id":3859,"title":3860,"titles":3861,"content":3862,"level":129},"/v1.0.6/reference/synapses/extraction#validation","Validation",[3804],"The Validate() method is called automatically after parsing: func (o Order) Validate() error {\n    if o.ID == \"\" {\n        return fmt.Errorf(\"order ID required\")\n    }\n    if o.Amount \u003C= 0 {\n        return fmt.Errorf(\"amount must be positive\")\n    }\n    if o.Amount > 1000000 {\n        return fmt.Errorf(\"amount exceeds maximum\")\n    }\n    return nil\n} If validation fails, Fire() returns an error and the session is not updated.",{"id":3864,"title":3646,"titles":3865,"content":3866,"level":129},"/v1.0.6/reference/synapses/extraction#use-cases",[3804],"Contact extractionInvoice parsingResume/CV parsingProduct information extractionEvent details extraction html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}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 pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}",{"id":3868,"title":3869,"titles":3870,"content":3871,"level":111},"/v1.0.6/reference/synapses/ranking","Ranking Synapse",[],"Order items by specified criteria",{"id":3873,"title":3869,"titles":3874,"content":3875,"level":111},"/v1.0.6/reference/synapses/ranking#ranking-synapse",[],"Order items by specified criteria.",{"id":3877,"title":3605,"titles":3878,"content":3879,"level":129},"/v1.0.6/reference/synapses/ranking#constructor",[3869],"func Ranking(criteria string, provider Provider, opts ...Option) (*RankingSynapse, error) Parameters: criteria - How to rank items (e.g., \"most relevant to least relevant\")provider - LLM provideropts - Optional configuration Returns: *RankingSynapse - The configured synapseerror - Configuration error",{"id":3881,"title":3610,"titles":3882,"content":103,"level":129},"/v1.0.6/reference/synapses/ranking#methods",[3869],{"id":3884,"title":377,"titles":3885,"content":3886,"level":143},"/v1.0.6/reference/synapses/ranking#fire",[3869,3610],"func (s *RankingSynapse) Fire(ctx context.Context, session *Session, items []string) ([]string, error) Execute and return ranked items. Parameters: items - Slice of items to rank Returns: []string - Items in ranked ordererror - Execution error",{"id":3888,"title":3618,"titles":3889,"content":3890,"level":143},"/v1.0.6/reference/synapses/ranking#firewithdetails",[3869,3610],"func (s *RankingSynapse) FireWithDetails(ctx context.Context, session *Session, items []string) (*RankingResponse, error) Execute and return full response.",{"id":3892,"title":3623,"titles":3893,"content":3894,"level":129},"/v1.0.6/reference/synapses/ranking#response-type",[3869],"type RankingResponse struct {\n    Ranked     []string `json:\"ranked\"`\n    Confidence float64  `json:\"confidence\"`\n    Reasoning  []string `json:\"reasoning\"`\n}",{"id":3896,"title":3628,"titles":3897,"content":103,"level":129},"/v1.0.6/reference/synapses/ranking#examples",[3869],{"id":3899,"title":3015,"titles":3900,"content":3901,"level":143},"/v1.0.6/reference/synapses/ranking#basic-usage",[3869,3628],"ranker, _ := zyn.Ranking(\"most healthy to least healthy\", provider)\nsession := zyn.NewSession()\n\nitems := []string{\"apple\", \"candy bar\", \"salad\", \"soda\"}\nresult, err := ranker.Fire(ctx, session, items)\n// result: [\"salad\", \"apple\", \"candy bar\", \"soda\"]",{"id":3903,"title":3904,"titles":3905,"content":3906,"level":143},"/v1.0.6/reference/synapses/ranking#relevance-ranking","Relevance Ranking",[3869,3628],"ranker, _ := zyn.Ranking(\"most relevant to the query\", provider)\n\n// Add context first\nsession := zyn.NewSession()\nsession.Append(zyn.RoleUser, \"I'm looking for a family car\")\n\nitems := []string{\"sports car\", \"minivan\", \"SUV\", \"motorcycle\"}\nresult, err := ranker.Fire(ctx, session, items)\n// result: [\"minivan\", \"SUV\", \"sports car\", \"motorcycle\"]",{"id":3908,"title":3686,"titles":3909,"content":3910,"level":143},"/v1.0.6/reference/synapses/ranking#with-details",[3869,3628],"response, err := ranker.FireWithDetails(ctx, session, items)\n// response.Ranked: [\"salad\", \"apple\", \"candy bar\", \"soda\"]\n// response.Confidence: 0.92\n// response.Reasoning: [\n//     \"Salad is most nutritious with vegetables and fiber\",\n//     \"Apple is a natural fruit with vitamins\",\n//     \"Candy bar has high sugar but some energy\",\n//     \"Soda has no nutritional value and high sugar\"\n// ]",{"id":3912,"title":3646,"titles":3913,"content":3914,"level":129},"/v1.0.6/reference/synapses/ranking#use-cases",[3869],"Search result orderingTask prioritizationRecommendation rankingDocument relevanceOption comparison html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}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 pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}",{"id":3916,"title":3917,"titles":3918,"content":3919,"level":111},"/v1.0.6/reference/synapses/sentiment","Sentiment Synapse",[],"Analyze emotional tone with detailed breakdown",{"id":3921,"title":3917,"titles":3922,"content":3923,"level":111},"/v1.0.6/reference/synapses/sentiment#sentiment-synapse",[],"Analyze emotional tone with detailed breakdown.",{"id":3925,"title":3605,"titles":3926,"content":3927,"level":129},"/v1.0.6/reference/synapses/sentiment#constructor",[3917],"func Sentiment(task string, provider Provider, opts ...Option) (*SentimentSynapse, error) Parameters: task - Description of sentiment analysis focusprovider - LLM provideropts - Optional configuration Returns: *SentimentSynapse - The configured synapseerror - Configuration error",{"id":3929,"title":3610,"titles":3930,"content":103,"level":129},"/v1.0.6/reference/synapses/sentiment#methods",[3917],{"id":3932,"title":377,"titles":3933,"content":3934,"level":143},"/v1.0.6/reference/synapses/sentiment#fire",[3917,3610],"func (s *SentimentSynapse) Fire(ctx context.Context, session *Session, input string) (string, error) Execute and return overall sentiment. Returns: string - Overall sentiment (\"positive\", \"negative\", \"neutral\", \"mixed\")error - Execution error",{"id":3936,"title":3618,"titles":3937,"content":3938,"level":143},"/v1.0.6/reference/synapses/sentiment#firewithdetails",[3917,3610],"func (s *SentimentSynapse) FireWithDetails(ctx context.Context, session *Session, input string) (*SentimentResponse, error) Execute and return full response with scores and aspects.",{"id":3940,"title":3623,"titles":3941,"content":3942,"level":129},"/v1.0.6/reference/synapses/sentiment#response-type",[3917],"type SentimentResponse struct {\n    Overall    string             `json:\"overall\"`\n    Confidence float64            `json:\"confidence\"`\n    Scores     SentimentScores    `json:\"scores\"`\n    Emotions   []string           `json:\"emotions,omitempty\"`\n    Aspects    map[string]string  `json:\"aspects,omitempty\"`\n    Reasoning  []string           `json:\"reasoning\"`\n}\n\ntype SentimentScores struct {\n    Positive float64 `json:\"positive\"`\n    Negative float64 `json:\"negative\"`\n    Neutral  float64 `json:\"neutral\"`\n}",{"id":3944,"title":3628,"titles":3945,"content":103,"level":129},"/v1.0.6/reference/synapses/sentiment#examples",[3917],{"id":3947,"title":3015,"titles":3948,"content":3949,"level":143},"/v1.0.6/reference/synapses/sentiment#basic-usage",[3917,3628],"analyzer, _ := zyn.Sentiment(\"Analyze customer feedback\", provider)\nsession := zyn.NewSession()\n\nresult, err := analyzer.Fire(ctx, session, \"I love this product! Best purchase ever!\")\n// result: \"positive\"",{"id":3951,"title":3686,"titles":3952,"content":3953,"level":143},"/v1.0.6/reference/synapses/sentiment#with-details",[3917,3628],"response, err := analyzer.FireWithDetails(ctx, session, \"The product is great but shipping was slow\")\n// response.Overall: \"mixed\"\n// response.Confidence: 0.85\n// response.Scores: {Positive: 0.6, Negative: 0.3, Neutral: 0.1}\n// response.Emotions: [\"satisfaction\", \"frustration\"]\n// response.Aspects: {\"product\": \"positive\", \"shipping\": \"negative\"}\n// response.Reasoning: [\"Positive about product quality\", \"Negative about delivery time\"]",{"id":3955,"title":3956,"titles":3957,"content":3958,"level":143},"/v1.0.6/reference/synapses/sentiment#aspect-based-analysis","Aspect-Based Analysis",[3917,3628],"analyzer, _ := zyn.Sentiment(\"Analyze sentiment by aspect: product, service, price\", provider)\n\nresponse, err := analyzer.FireWithDetails(ctx, session,\n    \"Great product, terrible customer service, but the price was fair\")\n// response.Aspects: {\n//     \"product\": \"positive\",\n//     \"service\": \"negative\",\n//     \"price\": \"neutral\"\n// }",{"id":3960,"title":3646,"titles":3961,"content":3962,"level":129},"/v1.0.6/reference/synapses/sentiment#use-cases",[3917],"Customer feedback analysisSocial media monitoringProduct review analysisBrand sentiment trackingSupport ticket prioritization html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}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 pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}",{"id":3964,"title":3965,"titles":3966,"content":3967,"level":111},"/v1.0.6/reference/synapses/transform","Transform Synapse",[],"Transform text to text",{"id":3969,"title":3965,"titles":3970,"content":3971,"level":111},"/v1.0.6/reference/synapses/transform#transform-synapse",[],"Transform text to text (translation, summarization, rewriting, etc.).",{"id":3973,"title":3605,"titles":3974,"content":3975,"level":129},"/v1.0.6/reference/synapses/transform#constructor",[3965],"func Transform(task string, provider Provider, opts ...Option) (*TransformSynapse, error) Parameters: task - Description of the transformationprovider - LLM provideropts - Optional configuration Returns: *TransformSynapse - The configured synapseerror - Configuration error",{"id":3977,"title":3610,"titles":3978,"content":103,"level":129},"/v1.0.6/reference/synapses/transform#methods",[3965],{"id":3980,"title":377,"titles":3981,"content":3982,"level":143},"/v1.0.6/reference/synapses/transform#fire",[3965,3610],"func (s *TransformSynapse) Fire(ctx context.Context, session *Session, input string) (string, error) Execute and return transformed text. Returns: string - Transformed texterror - Execution error",{"id":3984,"title":3618,"titles":3985,"content":3986,"level":143},"/v1.0.6/reference/synapses/transform#firewithdetails",[3965,3610],"func (s *TransformSynapse) FireWithDetails(ctx context.Context, session *Session, input string) (*TransformResponse, error) Execute and return full response.",{"id":3988,"title":3623,"titles":3989,"content":3990,"level":129},"/v1.0.6/reference/synapses/transform#response-type",[3965],"type TransformResponse struct {\n    Output     string   `json:\"output\"`\n    Confidence float64  `json:\"confidence\"`\n    Changes    []string `json:\"changes,omitempty\"`\n    Reasoning  []string `json:\"reasoning\"`\n}",{"id":3992,"title":3628,"titles":3993,"content":103,"level":129},"/v1.0.6/reference/synapses/transform#examples",[3965],{"id":3995,"title":3996,"titles":3997,"content":3998,"level":143},"/v1.0.6/reference/synapses/transform#translation","Translation",[3965,3628],"translator, _ := zyn.Transform(\"Translate to Spanish\", provider)\nsession := zyn.NewSession()\n\nresult, err := translator.Fire(ctx, session, \"Hello, how are you?\")\n// result: \"Hola, ¿cómo estás?\"",{"id":4000,"title":2886,"titles":4001,"content":4002,"level":143},"/v1.0.6/reference/synapses/transform#summarization",[3965,3628],"summarizer, _ := zyn.Transform(\"Summarize into 3 bullet points\", provider)\nsession := zyn.NewSession()\n\nresult, err := summarizer.Fire(ctx, session, longArticle)\n// result: \"• Point 1\\n• Point 2\\n• Point 3\"",{"id":4004,"title":4005,"titles":4006,"content":4007,"level":143},"/v1.0.6/reference/synapses/transform#rewriting","Rewriting",[3965,3628],"rewriter, _ := zyn.Transform(\"Rewrite in formal business English\", provider)\nsession := zyn.NewSession()\n\nresult, err := rewriter.Fire(ctx, session, \"hey can u check this out asap?\")\n// result: \"Could you please review this at your earliest convenience?\"",{"id":4009,"title":3686,"titles":4010,"content":4011,"level":143},"/v1.0.6/reference/synapses/transform#with-details",[3965,3628],"response, err := transformer.FireWithDetails(ctx, session, input)\n// response.Output: \"transformed text\"\n// response.Confidence: 0.92\n// response.Changes: [\"Corrected grammar\", \"Improved clarity\"]\n// response.Reasoning: [\"Applied formal tone\", \"Fixed punctuation\"]",{"id":4013,"title":3646,"titles":4014,"content":4015,"level":129},"/v1.0.6/reference/synapses/transform#use-cases",[3965],"TranslationSummarizationTone adjustmentGrammar correctionFormat conversion (prose to bullets, etc.)Content expansion html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}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 pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}",{"id":4017,"title":1640,"titles":4018,"content":4019,"level":111},"/v1.0.6/reference/options",[],"Configuration options for synapses",{"id":4021,"title":1640,"titles":4022,"content":4023,"level":111},"/v1.0.6/reference/options#options",[],"Configuration options for synapses.",{"id":4025,"title":4026,"titles":4027,"content":4028,"level":129},"/v1.0.6/reference/options#usage","Usage",[1640],"Options are passed when creating synapses: synapse, err := zyn.Binary(\"question\", provider,\n    zyn.WithRetry(3),\n    zyn.WithTimeout(10*time.Second),\n)",{"id":4030,"title":4031,"titles":4032,"content":103,"level":129},"/v1.0.6/reference/options#reliability-options","Reliability Options",[1640],{"id":4034,"title":892,"titles":4035,"content":4036,"level":143},"/v1.0.6/reference/options#withretry",[1640,4031],"func WithRetry(maxAttempts int) Option Retry failed calls up to maxAttempts times. zyn.WithRetry(3)  // Try up to 3 times",{"id":4038,"title":4039,"titles":4040,"content":4041,"level":143},"/v1.0.6/reference/options#withbackoff","WithBackoff",[1640,4031],"func WithBackoff(maxAttempts int, initialDelay time.Duration) Option Retry with exponential backoff. Delays double after each failure. zyn.WithBackoff(3, 100*time.Millisecond)\n// Delays: 100ms, 200ms, 400ms",{"id":4043,"title":910,"titles":4044,"content":4045,"level":143},"/v1.0.6/reference/options#withtimeout",[1640,4031],"func WithTimeout(duration time.Duration) Option Set maximum execution time for the entire call (including retries). zyn.WithTimeout(10 * time.Second)",{"id":4047,"title":4048,"titles":4049,"content":4050,"level":143},"/v1.0.6/reference/options#withcircuitbreaker","WithCircuitBreaker",[1640,4031],"func WithCircuitBreaker(threshold int, recoveryTime time.Duration) Option Open circuit after threshold consecutive failures. Attempt recovery after recoveryTime. zyn.WithCircuitBreaker(5, 30*time.Second)\n// Opens after 5 failures, tries again after 30s States: Closed - Normal operationOpen - Fails immediately without calling providerHalf-Open - After recovery time, allows one test request",{"id":4052,"title":4053,"titles":4054,"content":4055,"level":143},"/v1.0.6/reference/options#withratelimit","WithRateLimit",[1640,4031],"func WithRateLimit(rps float64, burst int) Option Limit request rate with token bucket algorithm. zyn.WithRateLimit(10.0, 100)\n// 10 requests/second sustained, burst up to 100",{"id":4057,"title":4058,"titles":4059,"content":4060,"level":143},"/v1.0.6/reference/options#withfallback","WithFallback",[1640,4031],"func WithFallback(fallbackSynapse Synapse) Option Use fallback synapse when primary fails. backup, _ := zyn.Binary(\"question\", backupProvider)\nprimary, _ := zyn.Binary(\"question\", primaryProvider,\n    zyn.WithFallback(backup),\n)",{"id":4062,"title":4063,"titles":4064,"content":4065,"level":143},"/v1.0.6/reference/options#witherrorhandler","WithErrorHandler",[1640,4031],"func WithErrorHandler(handler pipz.Chainable[*pipz.Error[*SynapseRequest]]) Option Custom error handling pipeline. // Define identity for the error handler\nvar logErrorsID = pipz.NewIdentity(\"log-errors\", \"Logs errors\")\n\nhandler := pipz.Apply(logErrorsID,\n    func(ctx context.Context, e *pipz.Error[*zyn.SynapseRequest]) (*pipz.Error[*zyn.SynapseRequest], error) {\n        log.Printf(\"Error: %v\", e.Err)\n        return e, nil\n    },\n)\n\nsynapse, _ := zyn.Binary(\"q\", provider, zyn.WithErrorHandler(handler))",{"id":4067,"title":2618,"titles":4068,"content":4069,"level":129},"/v1.0.6/reference/options#temperature",[1640],"Temperature is set per-input on each synapse's input struct, not as a construction option. // Set temperature via input struct\ninput := zyn.BinaryInput{\n    Subject:     \"test@example.com\",\n    Temperature: 0.1,\n}\nresult, err := synapse.FireWithInput(ctx, session, input) Constants: // Special values\nzyn.TemperatureUnset float32 = -1    // Use synapse default\nzyn.TemperatureZero  float32 = 0.0001 // Near-zero (0.0 treated as unset)\n\n// Default temperatures by task type\nzyn.DefaultTemperatureDeterministic float32 = 0.1 // Binary, Extraction, Convert\nzyn.DefaultTemperatureAnalytical    float32 = 0.2 // Sentiment, Ranking, Analyze\nzyn.DefaultTemperatureCreative      float32 = 0.3 // Classification, Transform Note: A zero-value float32 (0.0) is treated as unset for ergonomic struct initialization. Use TemperatureZero for explicit near-zero temperature.",{"id":4071,"title":2960,"titles":4072,"content":4073,"level":129},"/v1.0.6/reference/options#combining-options",[1640],"Options compose in order. Multiple options of the same type may override or wrap. synapse, _ := zyn.Classification(\"classify\", categories, provider,\n    // Retry with backoff first\n    zyn.WithBackoff(3, 100*time.Millisecond),\n\n    // Then timeout bounds total duration\n    zyn.WithTimeout(30*time.Second),\n\n    // Circuit breaker protects against outages\n    zyn.WithCircuitBreaker(5, 60*time.Second),\n\n    // Rate limit controls throughput\n    zyn.WithRateLimit(10, 50),\n\n    // Fallback as last resort\n    zyn.WithFallback(backupSynapse),\n)",{"id":4075,"title":4076,"titles":4077,"content":4078,"level":129},"/v1.0.6/reference/options#execution-order","Execution Order",[1640],"Request\n  │\n  ▼\nRateLimit (wait for token)\n  │\n  ▼\nCircuitBreaker (fail if open)\n  │\n  ▼\nTimeout (start timer)\n  │\n  ▼\nRetry/Backoff (retry loop)\n  │\n  ▼\nProvider (actual LLM call)\n  │\n  ▼\nErrorHandler (on failure)\n  │\n  ▼\nFallback (if configured and failed)",{"id":4080,"title":4081,"titles":4082,"content":4083,"level":129},"/v1.0.6/reference/options#option-compatibility","Option Compatibility",[1640],"OptionStacksNotesWithRetryNoLast one winsWithBackoffNoLast one wins, includes retryWithTimeoutNoLast one winsWithCircuitBreakerYesMultiple breakers chainWithRateLimitYesMultiple limiters chainWithFallbackNoLast one winsWithErrorHandlerYesMultiple handlers chain html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}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 pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .soy-K, html code.shiki .soy-K{--shiki-default:#BBBBBB}html pre.shiki code .scyPU, html code.shiki .scyPU{--shiki-default:var(--shiki-placeholder)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}",{"id":4085,"title":1647,"titles":4086,"content":4087,"level":111},"/v1.0.6/reference/session",[],"Session API reference",{"id":4089,"title":1647,"titles":4090,"content":4091,"level":111},"/v1.0.6/reference/session#session",[],"Session manages conversation context across synapse calls.",{"id":4093,"title":3605,"titles":4094,"content":4095,"level":129},"/v1.0.6/reference/session#constructor",[1647],"func NewSession() *Session Create a new empty session. session := zyn.NewSession()",{"id":4097,"title":4098,"titles":4099,"content":103,"level":129},"/v1.0.6/reference/session#read-methods","Read Methods",[1647],{"id":4101,"title":4102,"titles":4103,"content":4104,"level":143},"/v1.0.6/reference/session#messages","Messages",[1647,4098],"func (s *Session) Messages() []Message Get all messages in the session. messages := session.Messages()\nfor _, msg := range messages {\n    fmt.Printf(\"%s: %s\\n\", msg.Role, msg.Content)\n}",{"id":4106,"title":4107,"titles":4108,"content":4109,"level":143},"/v1.0.6/reference/session#len","Len",[1647,4098],"func (s *Session) Len() int Get the number of messages. count := session.Len()",{"id":4111,"title":4112,"titles":4113,"content":4114,"level":143},"/v1.0.6/reference/session#at","At",[1647,4098],"func (s *Session) At(index int) (Message, error) Get message at index. Returns error if out of bounds. msg, err := session.At(0)\nif err != nil {\n    // Index out of bounds\n}",{"id":4116,"title":4117,"titles":4118,"content":4119,"level":143},"/v1.0.6/reference/session#lastusage","LastUsage",[1647,4098],"func (s *Session) LastUsage() *TokenUsage Get token usage from the last successful call. Returns nil if no usage recorded. if usage := session.LastUsage(); usage != nil {\n    fmt.Printf(\"Tokens: %d\\n\", usage.Total)\n}",{"id":4121,"title":4122,"titles":4123,"content":103,"level":129},"/v1.0.6/reference/session#write-methods","Write Methods",[1647],{"id":4125,"title":4126,"titles":4127,"content":4128,"level":143},"/v1.0.6/reference/session#append","Append",[1647,4122],"func (s *Session) Append(role Role, content string) Add a message to the end. session.Append(zyn.RoleUser, \"Hello\")\nsession.Append(zyn.RoleAssistant, \"Hi there!\")",{"id":4130,"title":4131,"titles":4132,"content":4133,"level":143},"/v1.0.6/reference/session#clear","Clear",[1647,4122],"func (s *Session) Clear() Remove all messages. session.Clear()",{"id":4135,"title":4136,"titles":4137,"content":4138,"level":143},"/v1.0.6/reference/session#remove","Remove",[1647,4122],"func (s *Session) Remove(index int) error Remove message at index. Returns error if out of bounds. err := session.Remove(0)",{"id":4140,"title":4141,"titles":4142,"content":4143,"level":143},"/v1.0.6/reference/session#replace","Replace",[1647,4122],"func (s *Session) Replace(index int, msg Message) error Replace message at index. Returns error if out of bounds. err := session.Replace(0, zyn.Message{\n    Role:    zyn.RoleUser,\n    Content: \"Updated message\",\n})",{"id":4145,"title":4146,"titles":4147,"content":4148,"level":143},"/v1.0.6/reference/session#insert","Insert",[1647,4122],"func (s *Session) Insert(index int, msg Message) error Insert message at index. Returns error if out of bounds. err := session.Insert(0, zyn.Message{\n    Role:    zyn.RoleSystem,\n    Content: \"You are a helpful assistant\",\n})",{"id":4150,"title":4151,"titles":4152,"content":103,"level":129},"/v1.0.6/reference/session#bulk-methods","Bulk Methods",[1647],{"id":4154,"title":2857,"titles":4155,"content":4156,"level":143},"/v1.0.6/reference/session#prune",[1647,4151],"func (s *Session) Prune(n int) error Remove the last n message pairs (user + assistant). Each pair is 2 messages, so n=1 removes 2 messages. Returns error if n is negative. err := session.Prune(2)  // Remove last 2 exchanges (4 messages)",{"id":4158,"title":2862,"titles":4159,"content":4160,"level":143},"/v1.0.6/reference/session#truncate",[1647,4151],"func (s *Session) Truncate(keepFirst, keepLast int) error Keep first keepFirst and last keepLast messages, remove middle. err := session.Truncate(2, 2)  // Keep first 2 and last 2",{"id":4162,"title":4163,"titles":4164,"content":4165,"level":143},"/v1.0.6/reference/session#setmessages","SetMessages",[1647,4151],"func (s *Session) SetMessages(messages []Message) Replace entire message history. session.SetMessages([]zyn.Message{\n    {Role: zyn.RoleUser, Content: \"Summary of previous conversation\"},\n    {Role: zyn.RoleAssistant, Content: \"Acknowledged\"},\n})",{"id":4167,"title":4168,"titles":4169,"content":4170,"level":143},"/v1.0.6/reference/session#setusage","SetUsage",[1647,4151],"func (s *Session) SetUsage(usage *TokenUsage) Set token usage (typically called internally by synapses). session.SetUsage(&zyn.TokenUsage{\n    Prompt:     100,\n    Completion: 50,\n    Total:      150,\n})",{"id":4172,"title":3729,"titles":4173,"content":103,"level":129},"/v1.0.6/reference/session#types",[1647],{"id":4175,"title":4176,"titles":4177,"content":4178,"level":143},"/v1.0.6/reference/session#message","Message",[1647,3729],"type Message struct {\n    Role    string // RoleUser, RoleAssistant, or RoleSystem\n    Content string\n}",{"id":4180,"title":4181,"titles":4182,"content":4183,"level":143},"/v1.0.6/reference/session#role-constants","Role Constants",[1647,3729],"const (\n    RoleUser      = \"user\"\n    RoleAssistant = \"assistant\"\n    RoleSystem    = \"system\"\n)",{"id":4185,"title":4186,"titles":4187,"content":4188,"level":143},"/v1.0.6/reference/session#tokenusage","TokenUsage",[1647,3729],"type TokenUsage struct {\n    Prompt     int\n    Completion int\n    Total      int\n}",{"id":4190,"title":4191,"titles":4192,"content":103,"level":129},"/v1.0.6/reference/session#behavior","Behavior",[1647],{"id":4194,"title":2599,"titles":4195,"content":4196,"level":143},"/v1.0.6/reference/session#transactional-updates",[1647,4191],"Synapses update sessions atomically: session := zyn.NewSession()\ninitialLen := session.Len()  // 0\n\n_, err := synapse.Fire(ctx, session, \"input\")\nif err != nil {\n    // Session unchanged on error\n    assert(session.Len() == initialLen)\n} else {\n    // Session has user message + assistant response\n    assert(session.Len() == initialLen + 2)\n}",{"id":4198,"title":4199,"titles":4200,"content":4201,"level":143},"/v1.0.6/reference/session#thread-safety","Thread Safety",[1647,4191],"Sessions are safe for concurrent use by multiple goroutines. All methods are protected by a read-write mutex. // ✅ OK: Concurrent access\ngo func() { synapse.Fire(ctx, session, \"input1\") }()\ngo func() { synapse.Fire(ctx, session, \"input2\") }()\n\n// ✅ Also OK: Sequential access\nsynapse.Fire(ctx, session, \"input1\")\nsynapse.Fire(ctx, session, \"input2\")\n\n// ✅ Also OK: Separate sessions for independent conversations\ngo func() { synapse.Fire(ctx, zyn.NewSession(), \"input1\") }()\ngo func() { synapse.Fire(ctx, zyn.NewSession(), \"input2\") }() Note: While concurrent access is safe, the message ordering in concurrent scenarios depends on which goroutine completes first. For deterministic conversation flow, sequential access is recommended. html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}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 pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .scyPU, html code.shiki .scyPU{--shiki-default:var(--shiki-placeholder)}html pre.shiki code .suWN2, html code.shiki .suWN2{--shiki-default:var(--shiki-tag)}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sfm-E, html code.shiki .sfm-E{--shiki-default:var(--shiki-variable)}",{"id":4203,"title":1136,"titles":4204,"content":4205,"level":111},"/v1.0.6/reference/testing",[],"Testing package API reference",{"id":4207,"title":3113,"titles":4208,"content":4209,"level":111},"/v1.0.6/reference/testing#testing-package",[],"import zynt \"github.com/zoobz-io/zyn/testing\" Test utilities for deterministic synapse testing.",{"id":4211,"title":4212,"titles":4213,"content":4214,"level":129},"/v1.0.6/reference/testing#responsebuilder","ResponseBuilder",[3113],"Fluent interface for constructing mock LLM responses. func NewResponseBuilder() *ResponseBuilder",{"id":4216,"title":3610,"titles":4217,"content":4218,"level":143},"/v1.0.6/reference/testing#methods",[3113,4212],"MethodDescriptionWithDecision(bool)Set decision field (binary synapses)WithConfidence(float64)Set confidence scoreWithReasoning(...string)Set reasoning listWithPrimary(string)Set primary label (classification)WithSecondary(string)Set secondary label (classification)WithRanked(...string)Set ranked items (ranking)WithOutput(string)Set output text (transform)WithChanges(...string)Set changes list (transform)WithOverall(string)Set overall sentiment (sentiment)WithScores(positive, negative, neutral float64)Set sentiment scoresWithEmotions(...string)Set detected emotions (sentiment)WithAspects(map[string]string)Set aspect sentiments (sentiment)WithField(string, any)Set an arbitrary fieldBuild() stringReturn JSON stringBuildBytes() []byteReturn JSON bytes",{"id":4220,"title":4221,"titles":4222,"content":4223,"level":129},"/v1.0.6/reference/testing#sequencedprovider","SequencedProvider",[3113],"Returns responses in order. After exhaustion, repeats the last response. func NewSequencedProvider(responses ...string) *SequencedProvider",{"id":4225,"title":3610,"titles":4226,"content":4227,"level":143},"/v1.0.6/reference/testing#methods-1",[3113,4221],"MethodDescriptionCall(ctx, messages, temperature)Return next response in sequenceName() stringReturns \"sequenced-mock\"CallCount() intNumber of calls madeReset()Reset call counter",{"id":4229,"title":4230,"titles":4231,"content":4232,"level":129},"/v1.0.6/reference/testing#failingprovider","FailingProvider",[3113],"Fails a specified number of times before succeeding. Useful for testing retry behavior. func NewFailingProvider(failCount int) *FailingProvider",{"id":4234,"title":3610,"titles":4235,"content":4236,"level":143},"/v1.0.6/reference/testing#methods-2",[3113,4230],"MethodDescriptionWithSuccessResponse(string)Set response after failures exhaustWithFailError(string)Set failure error messageCall(ctx, messages, temperature)Fail until count reached, then succeedName() stringReturns \"failing-mock\"CallCount() intNumber of calls madeReset()Reset call counter",{"id":4238,"title":4239,"titles":4240,"content":4241,"level":129},"/v1.0.6/reference/testing#callrecorder","CallRecorder",[3113],"Wraps a provider and records all calls for inspection. func NewCallRecorder(provider zyn.Provider) *CallRecorder",{"id":4243,"title":3610,"titles":4244,"content":4245,"level":143},"/v1.0.6/reference/testing#methods-3",[3113,4239],"MethodDescriptionCall(ctx, messages, temperature)Delegate and recordName() stringWrapped provider's nameCalls() []RecordedCallCopy of all recorded callsCallCount() intNumber of calls recordedLastCall() *RecordedCallMost recent call, or nilReset()Clear recorded calls",{"id":4247,"title":4248,"titles":4249,"content":4250,"level":143},"/v1.0.6/reference/testing#recordedcall","RecordedCall",[3113,4239],"type RecordedCall struct {\n    Messages    []zyn.Message\n    Temperature float32\n}",{"id":4252,"title":4253,"titles":4254,"content":4255,"level":129},"/v1.0.6/reference/testing#latencyprovider","LatencyProvider",[3113],"Wraps a provider with artificial delay. Respects context cancellation. func NewLatencyProvider(provider zyn.Provider, delay time.Duration) *LatencyProvider",{"id":4257,"title":3610,"titles":4258,"content":4259,"level":143},"/v1.0.6/reference/testing#methods-4",[3113,4253],"MethodDescriptionCall(ctx, messages, temperature)Delay then delegateName() stringWrapped provider's name",{"id":4261,"title":4262,"titles":4263,"content":4264,"level":129},"/v1.0.6/reference/testing#usageaccumulator","UsageAccumulator",[3113],"Tracks total token usage across multiple calls. func NewUsageAccumulator() *UsageAccumulator",{"id":4266,"title":3610,"titles":4267,"content":4268,"level":143},"/v1.0.6/reference/testing#methods-5",[3113,4262],"MethodDescriptionAdd(session)Accumulate from session's last usageAddUsage(usage)Accumulate directlyPromptTokens() intTotal prompt tokensCompletionTokens() intTotal completion tokensTotalTokens() intTotal tokensCallCount() intNumber of calls accumulatedReset()Clear all values",{"id":4270,"title":4271,"titles":4272,"content":4273,"level":129},"/v1.0.6/reference/testing#streamrecorder","StreamRecorder",[3113],"Records chunks delivered during streaming. func NewStreamRecorder() *StreamRecorder",{"id":4275,"title":3610,"titles":4276,"content":4277,"level":143},"/v1.0.6/reference/testing#methods-6",[3113,4271],"MethodDescriptionCallback() StreamCallbackReturns callback that records chunksChunks() []stringCopy of all recorded chunksCombined() stringAll chunks joinedChunkCount() intNumber of chunksReset()Clear recorded chunks",{"id":4279,"title":4280,"titles":4281,"content":4282,"level":129},"/v1.0.6/reference/testing#streameventrecorder","StreamEventRecorder",[3113],"Records typed stream events. func NewStreamEventRecorder() *StreamEventRecorder",{"id":4284,"title":3610,"titles":4285,"content":4286,"level":143},"/v1.0.6/reference/testing#methods-7",[3113,4280],"MethodDescriptionCallback() StreamEventCallbackReturns callback that records eventsEvents() []StreamEventCopy of all recorded eventsEventCount() intNumber of eventsTextEvents() []StreamEventOnly text eventsToolStartEvents() []StreamEventOnly tool_start eventsReset()Clear recorded events html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}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 pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}",[4288],{"title":4289,"path":4290,"stem":4291,"children":4292,"page":4305},"V106","/v1.0.6","v1.0.6",[4293,4295,4306,4324,4336],{"title":1508,"path":2446,"stem":4294,"description":2448},"v1.0.6/1.overview",{"title":1514,"path":4296,"stem":4297,"children":4298,"page":4305},"/v1.0.6/learn","v1.0.6/2.learn",[4299,4301,4303],{"title":1522,"path":2497,"stem":4300,"description":2499},"v1.0.6/2.learn/1.quickstart",{"title":1528,"path":2547,"stem":4302,"description":2549},"v1.0.6/2.learn/2.concepts",{"title":1535,"path":2631,"stem":4304,"description":2633},"v1.0.6/2.learn/3.architecture",false,{"title":1540,"path":4307,"stem":4308,"children":4309,"page":4305},"/v1.0.6/guides","v1.0.6/3.guides",[4310,4312,4314,4316,4318,4320,4322],{"title":1548,"path":2710,"stem":4311,"description":2712},"v1.0.6/3.guides/1.installation",{"title":1555,"path":2758,"stem":4313,"description":2760},"v1.0.6/3.guides/2.providers",{"title":1073,"path":2825,"stem":4315,"description":2827},"v1.0.6/3.guides/3.sessions",{"title":1109,"path":2918,"stem":4317,"description":2920},"v1.0.6/3.guides/4.reliability",{"title":1114,"path":2992,"stem":4319,"description":2994},"v1.0.6/3.guides/5.observability",{"title":1136,"path":3085,"stem":4321,"description":3087},"v1.0.6/3.guides/6.testing",{"title":1582,"path":3175,"stem":4323,"description":3177},"v1.0.6/3.guides/7.best-practices",{"title":1587,"path":4325,"stem":4326,"children":4327,"page":4305},"/v1.0.6/cookbook","v1.0.6/4.cookbook",[4328,4330,4332,4334],{"title":1595,"path":3317,"stem":4329,"description":3319},"v1.0.6/4.cookbook/1.classification-workflows",{"title":1602,"path":3354,"stem":4331,"description":3356},"v1.0.6/4.cookbook/2.extraction-pipelines",{"title":1609,"path":3391,"stem":4333,"description":3393},"v1.0.6/4.cookbook/3.multi-turn-conversations",{"title":1616,"path":3433,"stem":4335,"description":3435},"v1.0.6/4.cookbook/4.error-handling",{"title":1621,"path":4337,"stem":4338,"children":4339,"page":4305},"/v1.0.6/reference","v1.0.6/5.reference",[4340,4342,4362,4364,4366],{"title":1628,"path":3490,"stem":4341,"description":3492},"v1.0.6/5.reference/1.cheatsheet",{"title":1068,"path":4343,"stem":4344,"children":4345,"page":4305},"/v1.0.6/reference/synapses","v1.0.6/5.reference/2.synapses",[4346,4348,4350,4352,4354,4356,4358,4360],{"title":3596,"path":3595,"stem":4347,"description":3598},"v1.0.6/5.reference/2.synapses/analyze",{"title":3651,"path":3650,"stem":4349,"description":3653},"v1.0.6/5.reference/2.synapses/binary",{"title":3700,"path":3699,"stem":4351,"description":3702},"v1.0.6/5.reference/2.synapses/classification",{"title":3754,"path":3753,"stem":4353,"description":3756},"v1.0.6/5.reference/2.synapses/convert",{"title":3804,"path":3803,"stem":4355,"description":3806},"v1.0.6/5.reference/2.synapses/extraction",{"title":3869,"path":3868,"stem":4357,"description":3871},"v1.0.6/5.reference/2.synapses/ranking",{"title":3917,"path":3916,"stem":4359,"description":3919},"v1.0.6/5.reference/2.synapses/sentiment",{"title":3965,"path":3964,"stem":4361,"description":3967},"v1.0.6/5.reference/2.synapses/transform",{"title":1640,"path":4017,"stem":4363,"description":4019},"v1.0.6/5.reference/3.options",{"title":1647,"path":4085,"stem":4365,"description":4087},"v1.0.6/5.reference/4.session",{"title":1136,"path":4203,"stem":4367,"description":4205},"v1.0.6/5.reference/5.testing",[4369],{"title":4289,"path":4290,"stem":4291,"children":4370,"page":4305},[4371,4372,4377,4386,4392],{"title":1508,"path":2446,"stem":4294},{"title":1514,"path":4296,"stem":4297,"children":4373,"page":4305},[4374,4375,4376],{"title":1522,"path":2497,"stem":4300},{"title":1528,"path":2547,"stem":4302},{"title":1535,"path":2631,"stem":4304},{"title":1540,"path":4307,"stem":4308,"children":4378,"page":4305},[4379,4380,4381,4382,4383,4384,4385],{"title":1548,"path":2710,"stem":4311},{"title":1555,"path":2758,"stem":4313},{"title":1073,"path":2825,"stem":4315},{"title":1109,"path":2918,"stem":4317},{"title":1114,"path":2992,"stem":4319},{"title":1136,"path":3085,"stem":4321},{"title":1582,"path":3175,"stem":4323},{"title":1587,"path":4325,"stem":4326,"children":4387,"page":4305},[4388,4389,4390,4391],{"title":1595,"path":3317,"stem":4329},{"title":1602,"path":3354,"stem":4331},{"title":1609,"path":3391,"stem":4333},{"title":1616,"path":3433,"stem":4335},{"title":1621,"path":4337,"stem":4338,"children":4393,"page":4305},[4394,4395,4405,4406,4407],{"title":1628,"path":3490,"stem":4341},{"title":1068,"path":4343,"stem":4344,"children":4396,"page":4305},[4397,4398,4399,4400,4401,4402,4403,4404],{"title":3596,"path":3595,"stem":4347},{"title":3651,"path":3650,"stem":4349},{"title":3700,"path":3699,"stem":4351},{"title":3754,"path":3753,"stem":4353},{"title":3804,"path":3803,"stem":4355},{"title":3869,"path":3868,"stem":4357},{"title":3917,"path":3916,"stem":4359},{"title":3965,"path":3964,"stem":4361},{"title":1640,"path":4017,"stem":4363},{"title":1647,"path":4085,"stem":4365},{"title":1136,"path":4203,"stem":4367},[4409],{"title":4289,"path":4290,"stem":4291,"children":4410,"page":4305},[4411,4412,4417,4426,4432],{"title":1508,"path":2446,"stem":4294,"description":2448},{"title":1514,"path":4296,"stem":4297,"children":4413,"page":4305},[4414,4415,4416],{"title":1522,"path":2497,"stem":4300,"description":2499},{"title":1528,"path":2547,"stem":4302,"description":2549},{"title":1535,"path":2631,"stem":4304,"description":2633},{"title":1540,"path":4307,"stem":4308,"children":4418,"page":4305},[4419,4420,4421,4422,4423,4424,4425],{"title":1548,"path":2710,"stem":4311,"description":2712},{"title":1555,"path":2758,"stem":4313,"description":2760},{"title":1073,"path":2825,"stem":4315,"description":2827},{"title":1109,"path":2918,"stem":4317,"description":2920},{"title":1114,"path":2992,"stem":4319,"description":2994},{"title":1136,"path":3085,"stem":4321,"description":3087},{"title":1582,"path":3175,"stem":4323,"description":3177},{"title":1587,"path":4325,"stem":4326,"children":4427,"page":4305},[4428,4429,4430,4431],{"title":1595,"path":3317,"stem":4329,"description":3319},{"title":1602,"path":3354,"stem":4331,"description":3356},{"title":1609,"path":3391,"stem":4333,"description":3393},{"title":1616,"path":3433,"stem":4335,"description":3435},{"title":1621,"path":4337,"stem":4338,"children":4433,"page":4305},[4434,4435,4445,4446,4447],{"title":1628,"path":3490,"stem":4341,"description":3492},{"title":1068,"path":4343,"stem":4344,"children":4436,"page":4305},[4437,4438,4439,4440,4441,4442,4443,4444],{"title":3596,"path":3595,"stem":4347,"description":3598},{"title":3651,"path":3650,"stem":4349,"description":3653},{"title":3700,"path":3699,"stem":4351,"description":3702},{"title":3754,"path":3753,"stem":4353,"description":3756},{"title":3804,"path":3803,"stem":4355,"description":3806},{"title":3869,"path":3868,"stem":4357,"description":3871},{"title":3917,"path":3916,"stem":4359,"description":3919},{"title":3965,"path":3964,"stem":4361,"description":3967},{"title":1640,"path":4017,"stem":4363,"description":4019},{"title":1647,"path":4085,"stem":4365,"description":4087},{"title":1136,"path":4203,"stem":4367,"description":4205},1776189401991]