[{"data":1,"prerenderedAt":1735},["ShallowReactive",2],{"repo-tree":3,"repo-\u002Finternal\u002Fsupport-bot\u002Freadme":283},[4,7,10,13,16,19,22,25,28,31,34,37,40,43,46,49,52,55,58,61,64,67,69,72,75,78,81,84,86,88,90,93,96,99,102,105,108,111,114,117,120,123,125,127,129,131,133,135,138,141,143,146,149,152,155,158,161,164,167,169,172,175,178,180,183,186,189,192,195,198,201,203,206,209,212,215,218,221,224,227,230,233,236,239,242,245,248,251,254,257,260,263,266,269,272,275,278,281],{"path":5,"title":6},"\u002Fagents\u002Fbackend-code-style","Backend Conventions",{"path":8,"title":9},"\u002Fagents\u002Fdatabase","Database",{"path":11,"title":12},"\u002Fagents\u002Fportal-code-style","Portal Conventions",{"path":14,"title":15},"\u002Fagents\u002Ftranslation","Translation",{"path":17,"title":18},"\u002Fconventions\u002Fbackend-coding","Backend coding conventions",{"path":20,"title":21},"\u002Fconventions\u002Ffrontend-coding","Frontend coding conventions",{"path":23,"title":24},"\u002Fdevelopment-process","Development process",{"path":26,"title":27},"\u002Flearning-api-preview-hetzner-setup","Learning API Preview on Hetzner + Cloudflare",{"path":29,"title":30},"\u002Flearning-api-preview-vm-plan","Learning API Preview VM Plan",{"path":32,"title":33},"\u002Fmonorepo-structure","Monorepo structure",{"path":35,"title":36},"\u002Foperations","Operations — bugs and support",{"path":38,"title":39},"\u002Fpostmortems\u002F2026-03-16_onboarding-currency-regression","Onboarding Zod transform silently broken — web signups assigned wrong checkout currency",{"path":41,"title":42},"\u002Fpostmortems\u002Freadme","Postmortems",{"path":44,"title":45},"\u002Fpostmortems\u002F_template","TEMPLATE",{"path":47,"title":48},"\u002Fpostmortems\u002Fposthog-comparison","Postmortem practice — comparison with PostHog",{"path":50,"title":51},"\u002Fpreview-environment-plan","Preview Environment Plan",{"path":53,"title":54},"\u002Fprinciples","Engineering principles",{"path":56,"title":57},"\u002Fworking-with-ai","Working with AI",{"path":59,"title":60},"\u002F.claude\u002Fskills\u002Feval-playground\u002Fskill","Eval Playground — Co-development Skill",{"path":62,"title":63},"\u002F.claude\u002Fskills\u002Ffigma-diff-section\u002Fskill","Figma Diff Section Pipeline",{"path":65,"title":66},"\u002Fagents","AGENTS.md",{"path":68,"title":66},"\u002Fclaude",{"path":70,"title":71},"\u002Freadme","Studyflash",{"path":73,"title":74},"\u002Fapps\u002Fcore-api\u002Fagents","Core API (apps\u002Fcore-api)",{"path":76,"title":77},"\u002Fapps\u002Fcore-api\u002Freadme","README",{"path":79,"title":80},"\u002Fapps\u002Femail-previews\u002Fagents","Email Previews (apps\u002Femail-previews)",{"path":82,"title":83},"\u002Fapps\u002Flanding-page\u002Fagents","Landing Page (apps\u002Flanding-page)",{"path":85,"title":83},"\u002Fapps\u002Flanding-page\u002Fclaude",{"path":87,"title":66},"\u002Fapps\u002Flearning-api\u002Fagents",{"path":89,"title":77},"\u002Fapps\u002Flearning-api\u002Freadme",{"path":91,"title":92},"\u002Fapps\u002Flearning-api\u002Fevals-playground\u002Feval_metrics_design","Surface-Specific Eval Metrics Design",{"path":94,"title":95},"\u002Fapps\u002Flearning-api\u002Fevals-playground\u002Ftest_set","Quiz Eval Test Set",{"path":97,"title":98},"\u002Fapps\u002Flearning-api\u002Fevals-playground\u002Ffrontend\u002Freadme","React + TypeScript + Vite",{"path":100,"title":101},"\u002Fapps\u002Flearning-api\u002Fevals-playground\u002Fknown-issues\u002Fcontent-pillar-shallow-coverage\u002Freadme","Content pillar misses subtopics in dense documents",{"path":103,"title":104},"\u002Fapps\u002Flearning-api\u002Fevals-playground\u002Fknown-issues\u002Fdocling-empty-section-headers\u002Freadme","Empty section headers dropped by docling chunker",{"path":106,"title":107},"\u002Fapps\u002Flearning-api\u002Fevals-playground\u002Fknown-issues\u002Fdocling-table-reading-order\u002Freadme","Table\u002Fbox layout causes wrong reading order",{"path":109,"title":110},"\u002Fapps\u002Flearning-api\u002Fevals-playground\u002Fmetrics\u002Freadme","Quiz eval metrics — canonical rubrics",{"path":112,"title":113},"\u002Fapps\u002Flearning-api\u002Fevals-playground\u002Freports\u002F2026-04-12-quiz-summary-feedback-current-state","Quiz and Summary Feedback Current State",{"path":115,"title":116},"\u002Fapps\u002Flearning-api\u002Fevals-playground\u002Freports\u002F2026-04-24-quiz-eval-metrics","Quiz Evaluation Metrics",{"path":118,"title":119},"\u002Fapps\u002Flearning-api\u002Fevals-playground\u002Freports\u002F2026-05-01-quiz-eval-current-state","Quiz Eval Current State",{"path":121,"title":122},"\u002Fapps\u002Flearning-api\u002Fmonitoring\u002Freadme","Monitoring Stack",{"path":124,"title":77},"\u002Fapps\u002Flearning-api\u002Fshared\u002Freadme",{"path":126,"title":77},"\u002Fapps\u002Flearning-api\u002Fworkers\u002Flearning_agents\u002Fflashcard_agent\u002Freadme",{"path":128,"title":77},"\u002Fapps\u002Flearning-api\u002Fworkers\u002Flearning_agents\u002Fingestion_agent\u002Freadme",{"path":130,"title":77},"\u002Fapps\u002Flearning-api\u002Fworkers\u002Flearning_agents\u002Fquiz_agent\u002Freadme",{"path":132,"title":77},"\u002Fapps\u002Flearning-api\u002Fworkers\u002Flearning_agents\u002Fsummary_agent\u002Freadme",{"path":134,"title":77},"\u002Fapps\u002Flearning-api\u002Fworkers\u002Fparser\u002Freadme",{"path":136,"title":137},"\u002Fapps\u002Fmarketing-emails-preview\u002Fagents","Marketing Emails Preview (apps\u002Fmarketing-emails-preview)",{"path":139,"title":140},"\u002Fapps\u002Fmobile-app\u002Fagents","StudyFlash Mobile App - Claude Code Configuration",{"path":142,"title":140},"\u002Fapps\u002Fmobile-app\u002Fclaude",{"path":144,"title":145},"\u002Fapps\u002Fmountain-max\u002Fagents","Mountain Max (apps\u002Fmountain-max)",{"path":147,"title":148},"\u002Fapps\u002Fmountain-max\u002Fgame\u002Freadme","Mountain Max Game",{"path":150,"title":151},"\u002Fapps\u002Fportal\u002Fagents","Portal (apps\u002Fportal)",{"path":153,"title":154},"\u002Fapps\u002Fportal\u002Freadme","Nuxt Minimal Starter",{"path":156,"title":157},"\u002Fapps\u002Fportal\u002Fapp\u002Fcomposables\u002Ffiles\u002Freadme","File Upload Composables",{"path":159,"title":160},"\u002Fapps\u002Fportal\u002Fdocs\u002Flibrary-routing","Library Routing Documentation",{"path":162,"title":163},"\u002Fapps\u002Fsupabase\u002Fagents","Supabase (apps\u002Fsupabase)",{"path":165,"title":166},"\u002Fapps\u002Fwrapped\u002Fagents","Wrapped (apps\u002Fwrapped)",{"path":168,"title":98},"\u002Fapps\u002Fwrapped\u002Freadme",{"path":170,"title":171},"\u002Finfra\u002Freadme","infra\u002F",{"path":173,"title":174},"\u002Finfra\u002Fdns\u002Freadme","DNS Infrastructure",{"path":176,"title":177},"\u002Finfra\u002Fdokploy\u002Freadme","studyflash-dokploy",{"path":179,"title":77},"\u002Finfra\u002Fdokploy\u002Fsdk\u002Fnodejs\u002Freadme",{"path":181,"title":182},"\u002Finfra\u002Finfisical\u002Freadme","Infisical Infrastructure",{"path":184,"title":185},"\u002Finfra\u002Flearning-api\u002Freadme","Pulumi GCP TypeScript Template",{"path":187,"title":188},"\u002Finfra\u002Fopenreplay\u002Freadme","OpenReplay on Hetzner",{"path":190,"title":191},"\u002Finfra\u002Fscripts\u002Freadme","infra\u002Fscripts\u002F",{"path":193,"title":194},"\u002Finfra\u002Fturborepo-cache\u002Freadme","Turborepo Remote Cache Infrastructure",{"path":196,"title":197},"\u002Finternal\u002Fchatwoot\u002Freadme","Chatwoot Infrastructure",{"path":199,"title":200},"\u002Finternal\u002Fchatwoot\u002Fprovider\u002Freadme","studyflash-chatwoot-provider",{"path":202,"title":77},"\u002Finternal\u002Fchatwoot\u002Fprovider\u002Fsdk\u002Fnodejs\u002Freadme",{"path":204,"title":205},"\u002Finternal\u002Fdocs\u002Freadme","internal\u002Fdocs",{"path":207,"title":208},"\u002Finternal\u002Fsupport-bot\u002Fclaude","Support Bot (Maximilian)",{"path":210,"title":211},"\u002Finternal\u002Fsupport-bot\u002Freadme","Studyflash Customer Support Bot (Maximilian)",{"path":213,"title":214},"\u002Finternal\u002Fsupport-bot\u002Fkb\u002Faccount_issues","Account Issues",{"path":216,"title":217},"\u002Finternal\u002Fsupport-bot\u002Fkb\u002Fbilling_invoice","Billing Invoice",{"path":219,"title":220},"\u002Finternal\u002Fsupport-bot\u002Fkb\u002Fcontent_upload","Content Upload",{"path":222,"title":223},"\u002Finternal\u002Fsupport-bot\u002Fkb\u002Fdata_loss","Data Loss",{"path":225,"title":226},"\u002Finternal\u002Fsupport-bot\u002Fkb\u002Fflashcard_issues","Flashcard Issues",{"path":228,"title":229},"\u002Finternal\u002Fsupport-bot\u002Fkb\u002Fgarbage","Garbage",{"path":231,"title":232},"\u002Finternal\u002Fsupport-bot\u002Fkb\u002Fgeneral_how_to","General How To",{"path":234,"title":235},"\u002Finternal\u002Fsupport-bot\u002Fkb","Knowledge Base Index",{"path":237,"title":238},"\u002Finternal\u002Fsupport-bot\u002Fkb\u002Flanguage_issues","Language Issues",{"path":240,"title":241},"\u002Finternal\u002Fsupport-bot\u002Fkb\u002Fmindmap_issues","Mindmap Issues",{"path":243,"title":244},"\u002Finternal\u002Fsupport-bot\u002Fkb\u002Fmisunderstanding","Misunderstanding",{"path":246,"title":247},"\u002Finternal\u002Fsupport-bot\u002Fkb\u002Fmock_exam_issues","Mock Exam Issues",{"path":249,"title":250},"\u002Finternal\u002Fsupport-bot\u002Fkb\u002Fpodcast_issues","Podcast Issues",{"path":252,"title":253},"\u002Finternal\u002Fsupport-bot\u002Fkb\u002Fquiz_issues","Quiz Issues",{"path":255,"title":256},"\u002Finternal\u002Fsupport-bot\u002Fkb\u002Frefund_request","Refund Request",{"path":258,"title":259},"\u002Finternal\u002Fsupport-bot\u002Fkb\u002Fsubscription_cancellation","Subscription Cancellation",{"path":261,"title":262},"\u002Finternal\u002Fsupport-bot\u002Fkb\u002Fsubscription_info","Subscription Info",{"path":264,"title":265},"\u002Finternal\u002Fsupport-bot\u002Fkb\u002Fsummary_issues","Summary Issues",{"path":267,"title":268},"\u002Finternal\u002Fsupport-bot\u002Fkb\u002Ftechnical_errors","Technical Errors",{"path":270,"title":271},"\u002Finternal\u002Fsupport-bot\u002Fkb\u002Fvideo_issues","Video Issues",{"path":273,"title":274},"\u002Fpackages\u002Fcommon\u002Fdocs\u002Fearly-access-features","Declarative Early Access Features",{"path":276,"title":277},"\u002Fpackages\u002Fcommon\u002Fscripts\u002Freadme","Common Package Scripts",{"path":279,"title":280},"\u002Fpackages\u002Fdevtools\u002Ffigma-plugins\u002Freadme","Figma plugins",{"path":282,"title":77},"\u002Fpackages\u002Fpulumi-infisical\u002Freadme",{"id":284,"title":211,"body":285,"description":1728,"extension":1729,"lastReviewed":1730,"meta":1731,"navigation":417,"owner":1730,"path":210,"seo":1732,"status":1730,"stem":1733,"tags":1730,"__hash__":1734},"repo\u002Finternal\u002Fsupport-bot\u002FREADME.md",{"type":286,"value":287,"toc":1683},"minimark",[288,292,301,306,313,318,329,333,337,373,377,388,494,498,501,550,553,557,616,622,626,665,673,686,715,722,741,762,766,774,777,782,823,828,863,868,887,892,898,906,909,913,1005,1009,1068,1072,1078,1086,1089,1093,1127,1131,1153,1157,1161,1224,1228,1263,1267,1330,1334,1338,1376,1380,1387,1391,1394,1441,1448,1462,1466,1470,1496,1500,1526,1530,1534,1541,1555,1559,1566,1583,1587,1591,1608,1612,1635,1639,1652,1656,1672,1676,1679],[289,290,211],"h1",{"id":291},"studyflash-customer-support-bot-maximilian",[293,294,295,296,300],"p",{},"A modular, API-first customer support automation system built with FastAPI. Designed for easy integration with N8N workflows and implements a ",[297,298,299],"strong",{},"closed-loop learning system"," that continuously improves from human agent corrections.",[302,303,305],"h2",{"id":304},"architecture-overview","Architecture Overview",[293,307,308,309,312],{},"This system implements a ",[297,310,311],{},"Context Stuffing"," approach instead of vector databases. The entire Knowledge Base (~10 pages) is fed to the AI on every request, making responses more accurate and eliminating the complexity of embeddings and vector search.",[314,315,317],"h3",{"id":316},"key-components","Key Components",[319,320,325],"pre",{"className":321,"code":323,"language":324},[322],"language-text","customer_support_bot\u002F\n├── main.py                 # FastAPI application with 3 core endpoints\n├── config.py               # Environment configuration\n├── requirements.txt        # Python dependencies\n├── models\u002F\n│   └── api.py              # Pydantic data models for requests\u002Fresponses\n├── services\u002F\n│   ├── maximilian.py       # AI agent that answers support queries\n│   ├── analyst.py          # Weekly gap analyzer (suggests new KB entries)\n│   ├── kb_service.py       # Fetches KB from Google Docs or local file\n│   └── database.py         # Supabase logging (learning loop)\n└── utils\u002F\n    └── prompts.py          # System prompts for AI agents\n","text",[326,327,323],"code",{"__ignoreMap":328},"",[302,330,332],{"id":331},"setup","Setup",[314,334,336],{"id":335},"_1-install-dependencies","1. Install Dependencies",[319,338,342],{"className":339,"code":340,"language":341,"meta":328,"style":328},"language-bash shiki shiki-themes github-light github-dark","cd customer_support_bot\npip install -r requirements.txt\n","bash",[326,343,344,357],{"__ignoreMap":328},[345,346,349,353],"span",{"class":347,"line":348},"line",1,[345,350,352],{"class":351},"sj4cs","cd",[345,354,356],{"class":355},"sZZnC"," customer_support_bot\n",[345,358,360,364,367,370],{"class":347,"line":359},2,[345,361,363],{"class":362},"sScJk","pip",[345,365,366],{"class":355}," install",[345,368,369],{"class":351}," -r",[345,371,372],{"class":355}," requirements.txt\n",[314,374,376],{"id":375},"_2-configure-environment-variables","2. Configure Environment Variables",[293,378,379,380,383,384,387],{},"Create a ",[326,381,382],{},".env"," file in the ",[326,385,386],{},"customer_support_bot\u002F"," directory:",[319,389,391],{"className":339,"code":390,"language":341,"meta":328,"style":328},"# Required\nOPENAI_API_KEY=sk-your-openai-api-key\n\n# Optional - Google Docs Integration\nGOOGLE_DOC_ID=your-google-doc-id-here\n\n# Optional - Supabase Integration (for learning loop)\nSUPABASE_URL=https:\u002F\u002Fyour-project.supabase.co\nSUPABASE_KEY=your-supabase-key\n\n# Optional - Knowledge Base\nKB_FILE_PATH=..\u002FKnowledgeBase  # Path to local KB file (fallback)\n",[326,392,393,399,412,419,425,436,441,447,458,469,474,480],{"__ignoreMap":328},[345,394,395],{"class":347,"line":348},[345,396,398],{"class":397},"sJ8bj","# Required\n",[345,400,401,405,409],{"class":347,"line":359},[345,402,404],{"class":403},"sVt8B","OPENAI_API_KEY",[345,406,408],{"class":407},"szBVR","=",[345,410,411],{"class":355},"sk-your-openai-api-key\n",[345,413,415],{"class":347,"line":414},3,[345,416,418],{"emptyLinePlaceholder":417},true,"\n",[345,420,422],{"class":347,"line":421},4,[345,423,424],{"class":397},"# Optional - Google Docs Integration\n",[345,426,428,431,433],{"class":347,"line":427},5,[345,429,430],{"class":403},"GOOGLE_DOC_ID",[345,432,408],{"class":407},[345,434,435],{"class":355},"your-google-doc-id-here\n",[345,437,439],{"class":347,"line":438},6,[345,440,418],{"emptyLinePlaceholder":417},[345,442,444],{"class":347,"line":443},7,[345,445,446],{"class":397},"# Optional - Supabase Integration (for learning loop)\n",[345,448,450,453,455],{"class":347,"line":449},8,[345,451,452],{"class":403},"SUPABASE_URL",[345,454,408],{"class":407},[345,456,457],{"class":355},"https:\u002F\u002Fyour-project.supabase.co\n",[345,459,461,464,466],{"class":347,"line":460},9,[345,462,463],{"class":403},"SUPABASE_KEY",[345,465,408],{"class":407},[345,467,468],{"class":355},"your-supabase-key\n",[345,470,472],{"class":347,"line":471},10,[345,473,418],{"emptyLinePlaceholder":417},[345,475,477],{"class":347,"line":476},11,[345,478,479],{"class":397},"# Optional - Knowledge Base\n",[345,481,483,486,488,491],{"class":347,"line":482},12,[345,484,485],{"class":403},"KB_FILE_PATH",[345,487,408],{"class":407},[345,489,490],{"class":355},"..\u002FKnowledgeBase",[345,492,493],{"class":397},"  # Path to local KB file (fallback)\n",[314,495,497],{"id":496},"_3-google-docs-authentication-optional","3. Google Docs Authentication (Optional)",[293,499,500],{},"If using Google Docs for the Knowledge Base:",[319,502,504],{"className":339,"code":503,"language":341,"meta":328,"style":328},"# Authenticate with gcloud\ngcloud auth application-default login\n\n# Set your active account (if you have multiple)\ngcloud config set account alejandro@studyflash.ch\n",[326,505,506,511,525,529,534],{"__ignoreMap":328},[345,507,508],{"class":347,"line":348},[345,509,510],{"class":397},"# Authenticate with gcloud\n",[345,512,513,516,519,522],{"class":347,"line":359},[345,514,515],{"class":362},"gcloud",[345,517,518],{"class":355}," auth",[345,520,521],{"class":355}," application-default",[345,523,524],{"class":355}," login\n",[345,526,527],{"class":347,"line":414},[345,528,418],{"emptyLinePlaceholder":417},[345,530,531],{"class":347,"line":421},[345,532,533],{"class":397},"# Set your active account (if you have multiple)\n",[345,535,536,538,541,544,547],{"class":347,"line":427},[345,537,515],{"class":362},[345,539,540],{"class":355}," config",[345,542,543],{"class":355}," set",[345,545,546],{"class":355}," account",[345,548,549],{"class":355}," alejandro@studyflash.ch\n",[293,551,552],{},"The system will automatically use your gcloud credentials to fetch the document.",[302,554,556],{"id":555},"running-the-api","Running the API",[319,558,560],{"className":339,"code":559,"language":341,"meta":328,"style":328},"# Development mode with auto-reload\nuvicorn main:app --reload --port 8000\n\n# Production mode\nuvicorn main:app --host 0.0.0.0 --port 8000 --workers 4\n",[326,561,562,567,584,588,593],{"__ignoreMap":328},[345,563,564],{"class":347,"line":348},[345,565,566],{"class":397},"# Development mode with auto-reload\n",[345,568,569,572,575,578,581],{"class":347,"line":359},[345,570,571],{"class":362},"uvicorn",[345,573,574],{"class":355}," main:app",[345,576,577],{"class":351}," --reload",[345,579,580],{"class":351}," --port",[345,582,583],{"class":351}," 8000\n",[345,585,586],{"class":347,"line":414},[345,587,418],{"emptyLinePlaceholder":417},[345,589,590],{"class":347,"line":421},[345,591,592],{"class":397},"# Production mode\n",[345,594,595,597,599,602,605,607,610,613],{"class":347,"line":427},[345,596,571],{"class":362},[345,598,574],{"class":355},[345,600,601],{"class":351}," --host",[345,603,604],{"class":351}," 0.0.0.0",[345,606,580],{"class":351},[345,608,609],{"class":351}," 8000",[345,611,612],{"class":351}," --workers",[345,614,615],{"class":351}," 4\n",[293,617,618,619],{},"The API will be available at ",[326,620,621],{},"http:\u002F\u002Flocalhost:8000",[302,623,625],{"id":624},"deployment","Deployment",[293,627,628,629,636,637,640,641,644,645,648,649,652,653,656,657,660,661,664],{},"The bot runs on the self-hosted ",[630,631,635],"a",{"href":632,"rel":633},"https:\u002F\u002Fdokploy.com",[634],"nofollow","Dokploy"," instance at\n",[326,638,639],{},"dokploy.studyflash.ch"," (project ",[297,642,643],{},"Customer Support",", environment\n",[297,646,647],{},"production","). Pushes to ",[326,650,651],{},"main"," of ",[326,654,655],{},"studyflash-ai\u002Fstudyflash"," auto-deploy\nvia Dokploy's GitHub integration (",[326,658,659],{},"autoDeploy: true","); no ",[326,662,663],{},"just deploy","\nor local Docker build is involved.",[293,666,667,668,672],{},"The service is publicly reachable at ",[630,669,670],{"href":670,"rel":671},"https:\u002F\u002Fsupport-bot.studyflash.dev",[634],".",[293,674,675,676,679,680,685],{},"The Dokploy resources (project \u002F environment \u002F application \u002F domain) are\ndeclared in ",[326,677,678],{},"index.ts"," and reconciled by Pulumi via the Go-native\n",[630,681,683],{"href":682},"..\u002F..\u002Finfra\u002Fdokploy",[326,684,177],{}," provider. Apply changes with:",[319,687,689],{"className":339,"code":688,"language":341,"meta":328,"style":328},"pnpm preview   # pulumi preview --diff\npnpm run pulumi:up # pulumi up\n",[326,690,691,702],{"__ignoreMap":328},[345,692,693,696,699],{"class":347,"line":348},[345,694,695],{"class":362},"pnpm",[345,697,698],{"class":355}," preview",[345,700,701],{"class":397},"   # pulumi preview --diff\n",[345,703,704,706,709,712],{"class":347,"line":359},[345,705,695],{"class":362},[345,707,708],{"class":355}," run",[345,710,711],{"class":355}," pulumi:up",[345,713,714],{"class":397}," # pulumi up\n",[293,716,717,718,721],{},"Both inline ",[326,719,720],{},"infisical run --path=\u002Finternal\u002Fsupport-bot\u002F -- pulumi -s prod \u003Caction>",".\nFresh-machine setup:",[723,724,725,732],"ol",{},[726,727,728,731],"li",{},[326,729,730],{},".\u002Finfra\u002Fscripts\u002Fsetup-pulumi.sh"," — R2 backend login.",[726,733,734,737,738,672],{},[326,735,736],{},"cd infra\u002Fdokploy && make install-plugin"," — build the provider binary\nand register it under ",[326,739,740],{},"~\u002F.pulumi\u002Fplugins\u002F",[293,742,743,744,747,748,747,751,754,755,758,759,761],{},"Application env (",[326,745,746],{},"GEMINI_API_KEY",", ",[326,749,750],{},"CHATWOOT_API_URL",[326,752,753],{},"CHATWOOT_API_TOKEN",",\netc.) is sourced from Infisical at ",[326,756,757],{},"\u002Finternal\u002Fsupport-bot\u002F"," on the prod\nenv at apply time and written to Dokploy's native env — see ",[326,760,678],{},"\nfor the full key list.",[302,763,765],{"id":764},"api-endpoints","API Endpoints",[314,767,769,770,773],{"id":768},"_1-post-ask-live-support-agent-workflow-2","1. ",[326,771,772],{},"POST \u002Fask"," - Live Support Agent (Workflow 2)",[293,775,776],{},"The main endpoint for handling customer queries. Maximilian reads the entire KB and generates context-aware responses.",[293,778,779],{},[297,780,781],{},"Request:",[319,783,787],{"className":784,"code":785,"language":786,"meta":328,"style":328},"language-json shiki shiki-themes github-light github-dark","{\n  \"user_email_body\": \"How do I cancel my subscription?\",\n  \"user_email_subject\": \"Cancellation question\"\n}\n","json",[326,788,789,794,808,818],{"__ignoreMap":328},[345,790,791],{"class":347,"line":348},[345,792,793],{"class":403},"{\n",[345,795,796,799,802,805],{"class":347,"line":359},[345,797,798],{"class":351},"  \"user_email_body\"",[345,800,801],{"class":403},": ",[345,803,804],{"class":355},"\"How do I cancel my subscription?\"",[345,806,807],{"class":403},",\n",[345,809,810,813,815],{"class":347,"line":414},[345,811,812],{"class":351},"  \"user_email_subject\"",[345,814,801],{"class":403},[345,816,817],{"class":355},"\"Cancellation question\"\n",[345,819,820],{"class":347,"line":421},[345,821,822],{"class":403},"}\n",[293,824,825],{},[297,826,827],{},"Response:",[319,829,831],{"className":784,"code":830,"language":786,"meta":328,"style":328},"{\n  \"response_html\": \"\u003Cp>Hi there! To cancel your subscription...\u003C\u002Fp>\",\n  \"status\": \"success\"\n}\n",[326,832,833,837,849,859],{"__ignoreMap":328},[345,834,835],{"class":347,"line":348},[345,836,793],{"class":403},[345,838,839,842,844,847],{"class":347,"line":359},[345,840,841],{"class":351},"  \"response_html\"",[345,843,801],{"class":403},[345,845,846],{"class":355},"\"\u003Cp>Hi there! To cancel your subscription...\u003C\u002Fp>\"",[345,848,807],{"class":403},[345,850,851,854,856],{"class":347,"line":414},[345,852,853],{"class":351},"  \"status\"",[345,855,801],{"class":403},[345,857,858],{"class":355},"\"success\"\n",[345,860,861],{"class":347,"line":421},[345,862,822],{"class":403},[293,864,865],{},[297,866,867],{},"Status Values:",[869,870,871,877],"ul",{},[726,872,873,876],{},[326,874,875],{},"success",": Answer found in KB, HTML response ready to send",[726,878,879,882,883,886],{},[326,880,881],{},"fallback",": No answer found, returns ",[326,884,885],{},"\u003Cp>(No Answer)\u003C\u002Fp>",", logs to database for human review",[293,888,889],{},[297,890,891],{},"N8N Integration:",[319,893,896],{"className":894,"code":895,"language":324},[322],"Outlook Trigger → HTTP Request Node (\u002Fask) → Switch Node (check status) \n  → Success: Reply to customer\n  → Fallback: Forward to human agent\n",[326,897,895],{"__ignoreMap":328},[314,899,901,902,905],{"id":900},"_2-post-analyze-weekly-gap-analyzer-workflow-3b","2. ",[326,903,904],{},"POST \u002Fanalyze"," - Weekly Gap Analyzer (Workflow 3b)",[293,907,908],{},"Analyzes support gaps and suggests new Knowledge Base entries for recurring issues (3+ occurrences).",[293,910,911],{},[297,912,781],{},[319,914,916],{"className":784,"code":915,"language":786,"meta":328,"style":328},"{\n  \"logs\": [\n    {\n      \"user_query\": \"Can I use Studyflash offline?\",\n      \"ai_response\": \"(No Answer)\",\n      \"status\": \"processed_by_human\",\n      \"human_golden_answer\": \"Studyflash requires internet...\"\n    }\n  ],\n  \"current_kb\": \"Optional - will fetch from Google Docs if not provided\"\n}\n",[326,917,918,922,930,935,947,959,971,981,986,991,1001],{"__ignoreMap":328},[345,919,920],{"class":347,"line":348},[345,921,793],{"class":403},[345,923,924,927],{"class":347,"line":359},[345,925,926],{"class":351},"  \"logs\"",[345,928,929],{"class":403},": [\n",[345,931,932],{"class":347,"line":414},[345,933,934],{"class":403},"    {\n",[345,936,937,940,942,945],{"class":347,"line":421},[345,938,939],{"class":351},"      \"user_query\"",[345,941,801],{"class":403},[345,943,944],{"class":355},"\"Can I use Studyflash offline?\"",[345,946,807],{"class":403},[345,948,949,952,954,957],{"class":347,"line":427},[345,950,951],{"class":351},"      \"ai_response\"",[345,953,801],{"class":403},[345,955,956],{"class":355},"\"(No Answer)\"",[345,958,807],{"class":403},[345,960,961,964,966,969],{"class":347,"line":438},[345,962,963],{"class":351},"      \"status\"",[345,965,801],{"class":403},[345,967,968],{"class":355},"\"processed_by_human\"",[345,970,807],{"class":403},[345,972,973,976,978],{"class":347,"line":443},[345,974,975],{"class":351},"      \"human_golden_answer\"",[345,977,801],{"class":403},[345,979,980],{"class":355},"\"Studyflash requires internet...\"\n",[345,982,983],{"class":347,"line":449},[345,984,985],{"class":403},"    }\n",[345,987,988],{"class":347,"line":460},[345,989,990],{"class":403},"  ],\n",[345,992,993,996,998],{"class":347,"line":471},[345,994,995],{"class":351},"  \"current_kb\"",[345,997,801],{"class":403},[345,999,1000],{"class":355},"\"Optional - will fetch from Google Docs if not provided\"\n",[345,1002,1003],{"class":347,"line":476},[345,1004,822],{"class":403},[293,1006,1007],{},[297,1008,827],{},[319,1010,1012],{"className":784,"code":1011,"language":786,"meta":328,"style":328},"[\n  {\n    \"Headline\": \"Offline Mode Support\",\n    \"Problem\": \"Users asking about offline functionality\",\n    \"Solution\": \"Studyflash requires internet connection...\"\n  }\n]\n",[326,1013,1014,1019,1024,1036,1048,1058,1063],{"__ignoreMap":328},[345,1015,1016],{"class":347,"line":348},[345,1017,1018],{"class":403},"[\n",[345,1020,1021],{"class":347,"line":359},[345,1022,1023],{"class":403},"  {\n",[345,1025,1026,1029,1031,1034],{"class":347,"line":414},[345,1027,1028],{"class":351},"    \"Headline\"",[345,1030,801],{"class":403},[345,1032,1033],{"class":355},"\"Offline Mode Support\"",[345,1035,807],{"class":403},[345,1037,1038,1041,1043,1046],{"class":347,"line":421},[345,1039,1040],{"class":351},"    \"Problem\"",[345,1042,801],{"class":403},[345,1044,1045],{"class":355},"\"Users asking about offline functionality\"",[345,1047,807],{"class":403},[345,1049,1050,1053,1055],{"class":347,"line":427},[345,1051,1052],{"class":351},"    \"Solution\"",[345,1054,801],{"class":403},[345,1056,1057],{"class":355},"\"Studyflash requires internet connection...\"\n",[345,1059,1060],{"class":347,"line":438},[345,1061,1062],{"class":403},"  }\n",[345,1064,1065],{"class":347,"line":443},[345,1066,1067],{"class":403},"]\n",[293,1069,1070],{},[297,1071,891],{},[319,1073,1076],{"className":1074,"code":1075,"language":324},[322],"Schedule Trigger (Friday 8am) → Supabase Node (fetch logs) \n  → HTTP Request (\u002Fanalyze) → Slack Approval → Update Google Doc\n",[326,1077,1075],{"__ignoreMap":328},[314,1079,1081,1082,1085],{"id":1080},"_3-post-log-correction-forward-to-learn-workflow-3a","3. ",[326,1083,1084],{},"POST \u002Flog-correction"," - Forward-to-Learn (Workflow 3a)",[293,1087,1088],{},"Logs human corrections when an agent manually answers a query that the AI couldn't handle.",[293,1090,1091],{},[297,1092,781],{},[319,1094,1096],{"className":784,"code":1095,"language":786,"meta":328,"style":328},"{\n  \"user_email_body\": \"Original customer question\",\n  \"human_answer\": \"The human agent's correct answer\"\n}\n",[326,1097,1098,1102,1113,1123],{"__ignoreMap":328},[345,1099,1100],{"class":347,"line":348},[345,1101,793],{"class":403},[345,1103,1104,1106,1108,1111],{"class":347,"line":359},[345,1105,798],{"class":351},[345,1107,801],{"class":403},[345,1109,1110],{"class":355},"\"Original customer question\"",[345,1112,807],{"class":403},[345,1114,1115,1118,1120],{"class":347,"line":414},[345,1116,1117],{"class":351},"  \"human_answer\"",[345,1119,801],{"class":403},[345,1121,1122],{"class":355},"\"The human agent's correct answer\"\n",[345,1124,1125],{"class":347,"line":421},[345,1126,822],{"class":403},[293,1128,1129],{},[297,1130,827],{},[319,1132,1134],{"className":784,"code":1133,"language":786,"meta":328,"style":328},"{\n  \"status\": \"logged\"\n}\n",[326,1135,1136,1140,1149],{"__ignoreMap":328},[345,1137,1138],{"class":347,"line":348},[345,1139,793],{"class":403},[345,1141,1142,1144,1146],{"class":347,"line":359},[345,1143,853],{"class":351},[345,1145,801],{"class":403},[345,1147,1148],{"class":355},"\"logged\"\n",[345,1150,1151],{"class":347,"line":414},[345,1152,822],{"class":403},[302,1154,1156],{"id":1155},"n8n-integration-guide","N8N Integration Guide",[314,1158,1160],{"id":1159},"workflow-2-live-agent-maximilian","Workflow 2: Live Agent (Maximilian)",[723,1162,1163,1169,1195],{},[726,1164,1165,1168],{},[297,1166,1167],{},"Outlook Trigger"," - On new email in support inbox",[726,1170,1171,1174,1175],{},[297,1172,1173],{},"HTTP Request Node",":\n",[869,1176,1177,1183,1189],{},[726,1178,1179,1180],{},"URL: ",[326,1181,1182],{},"YOUR_GCF_URL\u002Fask",[726,1184,1185,1186],{},"Method: ",[326,1187,1188],{},"POST",[726,1190,1191,1192],{},"Body: ",[326,1193,1194],{},"{\"user_email_body\": \"{{ $json.body }}\"}",[726,1196,1197,1200,1201,1204],{},[297,1198,1199],{},"Switch Node"," - Check ",[326,1202,1203],{},"{{ $json.status }}",[869,1205,1206,1219],{},[726,1207,1208,1209,1211,1212,1215,1216],{},"Case ",[326,1210,875],{},": Use ",[297,1213,1214],{},"Outlook Node"," to reply with ",[326,1217,1218],{},"{{ $json.response_html }}",[726,1220,1208,1221,1223],{},[326,1222,881],{},": Forward to human agent folder",[314,1225,1227],{"id":1226},"workflow-3a-forward-to-learn","Workflow 3a: Forward-to-Learn",[723,1229,1230,1239,1245],{},[726,1231,1232,1234,1235,1238],{},[297,1233,1167],{}," - Watch ",[326,1236,1237],{},"n8n-Learn"," folder or specific email address",[726,1240,1241,1244],{},[297,1242,1243],{},"Parse Email"," - Extract original query + human answer",[726,1246,1247,1174,1249],{},[297,1248,1173],{},[869,1250,1251,1256,1260],{},[726,1252,1179,1253],{},[326,1254,1255],{},"YOUR_GCF_URL\u002Flog-correction",[726,1257,1185,1258],{},[326,1259,1188],{},[726,1261,1262],{},"Body: Query + human answer",[314,1264,1266],{"id":1265},"workflow-3b-weekly-analyst","Workflow 3b: Weekly Analyst",[723,1268,1269,1275,1284,1304,1310,1316,1322],{},[726,1270,1271,1274],{},[297,1272,1273],{},"Schedule Trigger"," - Every Friday at 8:00 AM",[726,1276,1277,1280,1281],{},[297,1278,1279],{},"Supabase Node"," - Fetch rows where ",[326,1282,1283],{},"status = 'processed_by_human'",[726,1285,1286,1174,1288],{},[297,1287,1173],{},[869,1289,1290,1295,1299],{},[726,1291,1179,1292],{},[326,1293,1294],{},"YOUR_GCF_URL\u002Fanalyze",[726,1296,1185,1297],{},[326,1298,1188],{},[726,1300,1191,1301],{},[326,1302,1303],{},"{\"logs\": {{ $json }}}",[726,1305,1306,1309],{},[297,1307,1308],{},"If Node"," - Check if response array is not empty",[726,1311,1312,1315],{},[297,1313,1314],{},"Slack Node"," - Send approval message",[726,1317,1318,1321],{},[297,1319,1320],{},"Google Docs Node"," - Append approved entries to Master KB",[726,1323,1324,1326,1327],{},[297,1325,1279],{}," - Update logs to ",[326,1328,1329],{},"status = 'added_to_kb'",[302,1331,1333],{"id":1332},"configuration-details","Configuration Details",[314,1335,1337],{"id":1336},"knowledge-base-sources-priority-order","Knowledge Base Sources (Priority Order)",[723,1339,1340,1360],{},[726,1341,1342,1345,1346,1348,1349],{},[297,1343,1344],{},"Google Docs"," (if ",[326,1347,430],{}," is set)",[869,1350,1351,1354,1357],{},[726,1352,1353],{},"Uses gcloud Application Default Credentials",[726,1355,1356],{},"Automatically fetches latest version",[726,1358,1359],{},"No caching needed - AI reads full doc each time",[726,1361,1362,1365,1366],{},[297,1363,1364],{},"Local File"," (fallback)",[869,1367,1368,1373],{},[726,1369,1370,1371],{},"Reads from ",[326,1372,485],{},[726,1374,1375],{},"Good for development\u002Ftesting",[314,1377,1379],{"id":1378},"ai-model-configuration","AI Model Configuration",[293,1381,1382,1383,1386],{},"Default: ",[326,1384,1385],{},"gpt-4o"," (set in config.py)",[314,1388,1390],{"id":1389},"supabase-database-schema","Supabase Database Schema",[293,1392,1393],{},"Create this table for the learning loop:",[319,1395,1399],{"className":1396,"code":1397,"language":1398,"meta":328,"style":328},"language-sql shiki shiki-themes github-light github-dark","CREATE TABLE learning_logs (\n  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,\n  timestamp TIMESTAMPTZ DEFAULT NOW(),\n  user_query TEXT NOT NULL,\n  ai_response TEXT,\n  status TEXT NOT NULL,  -- 'new_gap', 'processed_by_human', 'added_to_kb'\n  human_golden_answer TEXT\n);\n","sql",[326,1400,1401,1406,1411,1416,1421,1426,1431,1436],{"__ignoreMap":328},[345,1402,1403],{"class":347,"line":348},[345,1404,1405],{},"CREATE TABLE learning_logs (\n",[345,1407,1408],{"class":347,"line":359},[345,1409,1410],{},"  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,\n",[345,1412,1413],{"class":347,"line":414},[345,1414,1415],{},"  timestamp TIMESTAMPTZ DEFAULT NOW(),\n",[345,1417,1418],{"class":347,"line":421},[345,1419,1420],{},"  user_query TEXT NOT NULL,\n",[345,1422,1423],{"class":347,"line":427},[345,1424,1425],{},"  ai_response TEXT,\n",[345,1427,1428],{"class":347,"line":438},[345,1429,1430],{},"  status TEXT NOT NULL,  -- 'new_gap', 'processed_by_human', 'added_to_kb'\n",[345,1432,1433],{"class":347,"line":443},[345,1434,1435],{},"  human_golden_answer TEXT\n",[345,1437,1438],{"class":347,"line":449},[345,1439,1440],{},");\n",[293,1442,1443,1444,1447],{},"Enable it by uncommenting lines in ",[326,1445,1446],{},"services\u002Fdatabase.py"," and installing:",[319,1449,1451],{"className":339,"code":1450,"language":341,"meta":328,"style":328},"pip install supabase\n",[326,1452,1453],{"__ignoreMap":328},[345,1454,1455,1457,1459],{"class":347,"line":348},[345,1456,363],{"class":362},[345,1458,366],{"class":355},[345,1460,1461],{"class":355}," supabase\n",[302,1463,1465],{"id":1464},"key-design-decisions","Key Design Decisions",[314,1467,1469],{"id":1468},"why-context-stuffing-over-vectors","Why Context Stuffing Over Vectors?",[869,1471,1472,1478,1484,1490],{},[726,1473,1474,1477],{},[297,1475,1476],{},"Scale",": KB is only ~10 pages (~10k tokens)",[726,1479,1480,1483],{},[297,1481,1482],{},"Cost",": Processing 10k tokens costs ~$0.0015 per query",[726,1485,1486,1489],{},[297,1487,1488],{},"Accuracy",": AI sees full context, not just retrieved chunks",[726,1491,1492,1495],{},[297,1493,1494],{},"Simplicity",": No embeddings, no vector sync, no chunking logic",[314,1497,1499],{"id":1498},"why-python-api-n8n","Why Python API + N8N?",[869,1501,1502,1508,1514,1520],{},[726,1503,1504,1507],{},[297,1505,1506],{},"Separation of Concerns",": Business logic (Python) separate from orchestration (N8N)",[726,1509,1510,1513],{},[297,1511,1512],{},"Testability",": Easy to test API endpoints independently",[726,1515,1516,1519],{},[297,1517,1518],{},"Flexibility",": Can swap N8N for other workflow tools",[726,1521,1522,1525],{},[297,1523,1524],{},"Debugging",": Clear API boundaries make troubleshooting easier",[302,1527,1529],{"id":1528},"customization","Customization",[314,1531,1533],{"id":1532},"changing-prompts","Changing Prompts",[293,1535,1536,1537,1540],{},"Edit ",[326,1538,1539],{},"utils\u002Fprompts.py"," to modify:",[869,1542,1543,1546,1549,1552],{},[726,1544,1545],{},"Agent personality and tone",[726,1547,1548],{},"Language detection rules",[726,1550,1551],{},"Fallback behavior",[726,1553,1554],{},"Analyst criteria (e.g., change from 3+ to 5+ occurrences)",[314,1556,1558],{"id":1557},"adding-new-endpoints","Adding New Endpoints",[293,1560,1561,1562,1565],{},"Follow the pattern in ",[326,1563,1564],{},"main.py",":",[723,1567,1568,1574,1580],{},[726,1569,1570,1571],{},"Create service class in ",[326,1572,1573],{},"services\u002F",[726,1575,1576,1577],{},"Add Pydantic models in ",[326,1578,1579],{},"models\u002Fapi.py",[726,1581,1582],{},"Add endpoint with dependency injection",[302,1584,1586],{"id":1585},"troubleshooting","Troubleshooting",[314,1588,1590],{"id":1589},"no-module-named-google","\"No module named 'google'\"",[319,1592,1594],{"className":339,"code":1593,"language":341,"meta":328,"style":328},"pip install google-api-python-client google-auth\n",[326,1595,1596],{"__ignoreMap":328},[345,1597,1598,1600,1602,1605],{"class":347,"line":348},[345,1599,363],{"class":362},[345,1601,366],{"class":355},[345,1603,1604],{"class":355}," google-api-python-client",[345,1606,1607],{"class":355}," google-auth\n",[314,1609,1611],{"id":1610},"knowledge-base-content-is-empty","\"Knowledge Base content is empty\"",[869,1613,1614,1620,1626,1629],{},[726,1615,1616,1617,1619],{},"Check ",[326,1618,430],{}," is set correctly",[726,1621,1622,1623],{},"Verify gcloud authentication: ",[326,1624,1625],{},"gcloud auth application-default login",[726,1627,1628],{},"Ensure the document is shared with your service account",[726,1630,1631,1632,1634],{},"Check that local ",[326,1633,485],{}," exists as fallback",[314,1636,1638],{"id":1637},"ai-returning-no-answer-too-often","AI returning \"(No Answer)\" too often",[869,1640,1641,1644,1649],{},[726,1642,1643],{},"Verify KB content is loading (check logs)",[726,1645,1646,1647],{},"Review prompt in ",[326,1648,1539],{},[726,1650,1651],{},"Consider using GPT-4 instead of GPT-4o-mini for better instruction following",[314,1653,1655],{"id":1654},"supabase-not-logging","Supabase not logging",[869,1657,1658,1667],{},[726,1659,1660,1661,1663,1664,1666],{},"Ensure ",[326,1662,452],{}," and ",[326,1665,463],{}," are set",[726,1668,1616,1669,1671],{},[326,1670,1446],{}," exceptions",[302,1673,1675],{"id":1674},"license-support","License & Support",[293,1677,1678],{},"Built for Studyflash. For questions, contact the engineering team.",[1680,1681,1682],"style",{},"html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}",{"title":328,"searchDepth":359,"depth":359,"links":1684},[1685,1688,1693,1694,1695,1703,1708,1713,1717,1721,1727],{"id":304,"depth":359,"text":305,"children":1686},[1687],{"id":316,"depth":414,"text":317},{"id":331,"depth":359,"text":332,"children":1689},[1690,1691,1692],{"id":335,"depth":414,"text":336},{"id":375,"depth":414,"text":376},{"id":496,"depth":414,"text":497},{"id":555,"depth":359,"text":556},{"id":624,"depth":359,"text":625},{"id":764,"depth":359,"text":765,"children":1696},[1697,1699,1701],{"id":768,"depth":414,"text":1698},"1. POST \u002Fask - Live Support Agent (Workflow 2)",{"id":900,"depth":414,"text":1700},"2. POST \u002Fanalyze - Weekly Gap Analyzer (Workflow 3b)",{"id":1080,"depth":414,"text":1702},"3. POST \u002Flog-correction - Forward-to-Learn (Workflow 3a)",{"id":1155,"depth":359,"text":1156,"children":1704},[1705,1706,1707],{"id":1159,"depth":414,"text":1160},{"id":1226,"depth":414,"text":1227},{"id":1265,"depth":414,"text":1266},{"id":1332,"depth":359,"text":1333,"children":1709},[1710,1711,1712],{"id":1336,"depth":414,"text":1337},{"id":1378,"depth":414,"text":1379},{"id":1389,"depth":414,"text":1390},{"id":1464,"depth":359,"text":1465,"children":1714},[1715,1716],{"id":1468,"depth":414,"text":1469},{"id":1498,"depth":414,"text":1499},{"id":1528,"depth":359,"text":1529,"children":1718},[1719,1720],{"id":1532,"depth":414,"text":1533},{"id":1557,"depth":414,"text":1558},{"id":1585,"depth":359,"text":1586,"children":1722},[1723,1724,1725,1726],{"id":1589,"depth":414,"text":1590},{"id":1610,"depth":414,"text":1611},{"id":1637,"depth":414,"text":1638},{"id":1654,"depth":414,"text":1655},{"id":1674,"depth":359,"text":1675},"A modular, API-first customer support automation system built with FastAPI. Designed for easy integration with N8N workflows and implements a closed-loop learning system that continuously improves from human agent corrections.","md",null,{},{"title":211,"description":1728},"internal\u002Fsupport-bot\u002FREADME","sGEP1zWsP843imJNIRxMYI6JXmWWGZ13QBcFUvyzzOo",1779007964221]