[{"data":1,"prerenderedAt":3461},["ShallowReactive",2],{"navigation_docs":3,"-engineering-contributing-back-end-llm-prompts":348,"-engineering-contributing-back-end-llm-prompts-surround":3457},[4,8,68,98,216,245,259,280,344],{"title":5,"path":6,"stem":7},"Introduction","\u002Fintroduction","0.introduction",{"title":9,"icon":10,"path":11,"stem":12,"children":13,"page":63},"Company","i-lucide-building-2","\u002Fcompany","1.company",[14,18,22,26,30,34,38,42,46,50,64],{"title":15,"path":16,"stem":17},"About","\u002Fcompany\u002Fabout","1.company\u002F0.about",{"title":19,"path":20,"stem":21},"Values","\u002Fcompany\u002Fvalues","1.company\u002F1.values",{"title":23,"path":24,"stem":25},"Communication","\u002Fcompany\u002Fcommunication","1.company\u002Fcommunication",{"title":27,"path":28,"stem":29},"Competition","\u002Fcompany\u002Fcompetition","1.company\u002Fcompetition",{"title":31,"path":32,"stem":33},"Hybrid Working","\u002Fcompany\u002Fhybrid-working","1.company\u002Fhybrid-working",{"title":35,"path":36,"stem":37},"Manchester Office","\u002Fcompany\u002Foffice","1.company\u002Foffice",{"title":39,"path":40,"stem":41},"Operations","\u002Fcompany\u002Foperations","1.company\u002Foperations",{"title":43,"path":44,"stem":45},"Policies","\u002Fcompany\u002Fpolicies","1.company\u002Fpolicies",{"title":47,"path":48,"stem":49},"Product Strategy","\u002Fcompany\u002Fproduct-strategy","1.company\u002Fproduct-strategy",{"title":51,"path":52,"stem":53,"children":54,"page":63},"Products","\u002Fcompany\u002Fproducts","1.company\u002Fproducts",[55,59],{"title":56,"path":57,"stem":58},"Capability Exchange","\u002Fcompany\u002Fproducts\u002Fcapability-exchange","1.company\u002Fproducts\u002Fcapability-exchange",{"title":60,"path":61,"stem":62},"ESProfiler Platform","\u002Fcompany\u002Fproducts\u002Fesprofiler","1.company\u002Fproducts\u002Fesprofiler",false,{"title":65,"path":66,"stem":67},"Security","\u002Fcompany\u002Fsecurity","1.company\u002Fsecurity",{"title":69,"icon":70,"path":71,"stem":72,"children":73,"page":63},"People Ops","i-lucide-users","\u002Fpeople-ops","2.people-ops",[74,78,82,86,90,94],{"title":75,"path":76,"stem":77},"Compensation","\u002Fpeople-ops\u002Fcompensation","2.people-ops\u002Fcompensation",{"title":79,"path":80,"stem":81},"Education","\u002Fpeople-ops\u002Feducation","2.people-ops\u002Feducation",{"title":83,"path":84,"stem":85},"Expenses","\u002Fpeople-ops\u002Fexpenses","2.people-ops\u002Fexpenses",{"title":87,"path":88,"stem":89},"Holiday & Leave","\u002Fpeople-ops\u002Fleave","2.people-ops\u002Fleave",{"title":91,"path":92,"stem":93},"Onboarding","\u002Fpeople-ops\u002Fonboarding","2.people-ops\u002Fonboarding",{"title":95,"path":96,"stem":97},"Recruitment","\u002Fpeople-ops\u002Frecruitment","2.people-ops\u002Frecruitment",{"title":99,"icon":100,"path":101,"stem":102,"children":103,"page":63},"Engineering","i-lucide-rocket","\u002Fengineering","3.engineering",[104,147,151,171,192,196,204,208,212],{"title":105,"path":106,"stem":107,"children":108,"page":63},"Contributing","\u002Fengineering\u002Fcontributing","3.engineering\u002Fcontributing",[109,113,117,121,125,138],{"title":110,"path":111,"stem":112},"Development Setup","\u002Fengineering\u002Fcontributing\u002Fdevelopment-setup","3.engineering\u002Fcontributing\u002F1.development-setup",{"title":114,"path":115,"stem":116},"Engineering Operations","\u002Fengineering\u002Fcontributing\u002Fengineering-operations","3.engineering\u002Fcontributing\u002F2.engineering-operations",{"title":118,"path":119,"stem":120},"Documentation","\u002Fengineering\u002Fcontributing\u002Fdocumentation","3.engineering\u002Fcontributing\u002F3.documentation",{"title":122,"path":123,"stem":124},"Agentic Coding","\u002Fengineering\u002Fcontributing\u002Fagentic-coding","3.engineering\u002Fcontributing\u002Fagentic-coding",{"title":126,"path":127,"stem":128,"children":129,"page":63},"Back End","\u002Fengineering\u002Fcontributing\u002Fback-end","3.engineering\u002Fcontributing\u002Fback-end",[130,134],{"title":131,"path":132,"stem":133},"API Guidelines","\u002Fengineering\u002Fcontributing\u002Fback-end\u002Fapi-guidelines","3.engineering\u002Fcontributing\u002Fback-end\u002Fapi-guidelines",{"title":135,"path":136,"stem":137},"LLM Prompts & Langfuse Integration","\u002Fengineering\u002Fcontributing\u002Fback-end\u002Fllm-prompts","3.engineering\u002Fcontributing\u002Fback-end\u002Fllm-prompts",{"title":139,"path":140,"stem":141,"children":142,"page":63},"Front End","\u002Fengineering\u002Fcontributing\u002Ffront-end","3.engineering\u002Fcontributing\u002Ffront-end",[143],{"title":144,"path":145,"stem":146},"Testing","\u002Fengineering\u002Fcontributing\u002Ffront-end\u002Ftesting","3.engineering\u002Fcontributing\u002Ffront-end\u002Ftesting",{"title":148,"path":149,"stem":150},"Production Database","\u002Fengineering\u002Fdatabase-connection","3.engineering\u002Fdatabase-connection",{"title":152,"path":153,"stem":154,"children":155},"Deployment","\u002Fengineering\u002Fdeployment","3.engineering\u002Fdeployment",[156,159,163,167],{"title":56,"path":157,"stem":158},"\u002Fengineering\u002Fdeployment\u002Fcapability-exchange","3.engineering\u002Fdeployment\u002Fcapability-exchange",{"title":160,"path":161,"stem":162},"Langfuse Deployment","\u002Fengineering\u002Fdeployment\u002Fecs-langfuse-deployment","3.engineering\u002Fdeployment\u002Fecs-langfuse-deployment",{"title":164,"path":165,"stem":166},"ESP Platform Configuration","\u002Fengineering\u002Fdeployment\u002Fesp-platform-configuration","3.engineering\u002Fdeployment\u002Fesp-platform-configuration",{"title":168,"path":169,"stem":170},"Platform","\u002Fengineering\u002Fdeployment\u002Fplatform","3.engineering\u002Fdeployment\u002Fplatform",{"title":172,"path":173,"stem":174,"children":175,"page":63},"Github","\u002Fengineering\u002Fgithub","3.engineering\u002Fgithub",[176,180,184,188],{"title":177,"path":178,"stem":179},"Packages","\u002Fengineering\u002Fgithub\u002Fpackages","3.engineering\u002Fgithub\u002Fpackages",{"title":181,"path":182,"stem":183},"Personal Access Token","\u002Fengineering\u002Fgithub\u002Fpersonal-access-token","3.engineering\u002Fgithub\u002Fpersonal-access-token",{"title":185,"path":186,"stem":187},"Troubleshooting","\u002Fengineering\u002Fgithub\u002Ftroubleshooting","3.engineering\u002Fgithub\u002Ftroubleshooting",{"title":189,"path":190,"stem":191},"Workflows","\u002Fengineering\u002Fgithub\u002Fworkflows","3.engineering\u002Fgithub\u002Fworkflows",{"title":193,"path":194,"stem":195},"Platform Ops","\u002Fengineering\u002Fplatform-ops","3.engineering\u002Fplatform-ops",{"title":168,"path":197,"stem":198,"children":199,"page":63},"\u002Fengineering\u002Fplatform","3.engineering\u002Fplatform",[200],{"title":201,"path":202,"stem":203},"useAPI","\u002Fengineering\u002Fplatform\u002Fuse-api","3.engineering\u002Fplatform\u002Fuse-api",{"title":205,"path":206,"stem":207},"Project Management","\u002Fengineering\u002Fproject-management","3.engineering\u002Fproject-management",{"title":209,"path":210,"stem":211},"Releases","\u002Fengineering\u002Frelease","3.engineering\u002Frelease",{"title":213,"path":214,"stem":215},"Tools","\u002Fengineering\u002Ftools","3.engineering\u002Ftools",{"title":217,"icon":218,"path":219,"stem":220,"children":221,"page":63},"Design","i-lucide-palette","\u002Fdesign","4.design",[222,226,230,234,238,241],{"title":223,"path":224,"stem":225},"Design Thinking","\u002Fdesign\u002Fdesign-thinking","4.design\u002F1.design-thinking",{"title":227,"path":228,"stem":229},"Figma","\u002Fdesign\u002Ffigma-structure","4.design\u002F2.figma-structure",{"title":231,"path":232,"stem":233},"Design & Development","\u002Fdesign\u002Fdesign-and-development","4.design\u002F3.design-and-development",{"title":235,"path":236,"stem":237},"Branding","\u002Fdesign\u002Fbranding","4.design\u002F4.branding",{"title":213,"path":239,"stem":240},"\u002Fdesign\u002Ftools","4.design\u002F5.tools",{"title":242,"path":243,"stem":244},"Customer Success","\u002Fdesign\u002Fworking-with-customers","4.design\u002F6.working-with-customers",{"title":246,"icon":247,"path":248,"stem":249,"children":250,"page":63},"Sales","i-lucide-dollar-sign","\u002Fsales","4.sales",[251,255],{"title":252,"path":253,"stem":254},"Customer Onboarding","\u002Fsales\u002Fonboarding","4.sales\u002Fonboarding",{"title":256,"path":257,"stem":258},"Sales Tools","\u002Fsales\u002Ftools","4.sales\u002Ftools",{"title":260,"icon":261,"path":262,"stem":263,"children":264,"page":63},"Marketing","i-lucide-book-image","\u002Fmarketing","5.marketing",[265,269,273,276],{"title":266,"path":267,"stem":268},"Content","\u002Fmarketing\u002Fcontent","5.marketing\u002Fcontent",{"title":270,"path":271,"stem":272},"Messaging","\u002Fmarketing\u002Fmessaging","5.marketing\u002Fmessaging",{"title":213,"path":274,"stem":275},"\u002Fmarketing\u002Ftools","5.marketing\u002Ftools",{"title":277,"path":278,"stem":279},"Website","\u002Fmarketing\u002Fwebsite","5.marketing\u002Fwebsite",{"title":281,"icon":282,"path":283,"stem":284,"children":285,"page":63},"AI & Data Ops","i-lucide-database","\u002Fdata-ops","6.data-ops",[286,294,298,323,340],{"title":56,"path":287,"stem":288,"children":289,"page":63},"\u002Fdata-ops\u002Fcapability-exchange","6.data-ops\u002FCapability Exchange",[290],{"title":291,"path":292,"stem":293},"Leaderboard Calculation","\u002Fdata-ops\u002Fcapability-exchange\u002Fleaderboard-calculation","6.data-ops\u002FCapability Exchange\u002Fleaderboard-calculation",{"title":295,"path":296,"stem":297},"Account Portal (CAS)","\u002Fdata-ops\u002Faccount-portal","6.data-ops\u002Faccount-portal",{"title":299,"path":300,"stem":301,"children":302,"page":63},"Data Management","\u002Fdata-ops\u002Fdata-management","6.data-ops\u002Fdata-management",[303,307,311,315,319],{"title":304,"path":305,"stem":306},"Adding Products","\u002Fdata-ops\u002Fdata-management\u002Fadding-products","6.data-ops\u002Fdata-management\u002Fadding-products",{"title":308,"path":309,"stem":310},"Adding Vendors","\u002Fdata-ops\u002Fdata-management\u002Fadding-vendors","6.data-ops\u002Fdata-management\u002Fadding-vendors",{"title":312,"path":313,"stem":314},"Framework Mapping","\u002Fdata-ops\u002Fdata-management\u002Fframework-mapping","6.data-ops\u002Fdata-management\u002Fframework-mapping",{"title":316,"path":317,"stem":318},"Refreshing Vendors","\u002Fdata-ops\u002Fdata-management\u002Frefreshing-vendors","6.data-ops\u002Fdata-management\u002Frefreshing-vendors",{"title":320,"path":321,"stem":322},"Reviewing Draft Vendors","\u002Fdata-ops\u002Fdata-management\u002Freviewing-draft-vendors","6.data-ops\u002Fdata-management\u002Freviewing-draft-vendors",{"title":324,"path":325,"stem":326,"children":327,"page":63},"LLM Ops","\u002Fdata-ops\u002Fllm-ops","6.data-ops\u002Fllm-ops",[328,332,336],{"title":329,"path":330,"stem":331},"Agents","\u002Fdata-ops\u002Fllm-ops\u002Fagents","6.data-ops\u002Fllm-ops\u002F1.agents",{"title":333,"path":334,"stem":335},"ESPi Architecture & Query Flow","\u002Fdata-ops\u002Fllm-ops\u002Fespi-architecture","6.data-ops\u002Fllm-ops\u002F2.espi-architecture",{"title":337,"path":338,"stem":339},"Evaluating Agents","\u002Fdata-ops\u002Fllm-ops\u002Fevaluations","6.data-ops\u002Fllm-ops\u002F3.evaluations",{"title":341,"path":342,"stem":343},"Message Queues","\u002Fdata-ops\u002Fmessage-queues","6.data-ops\u002Fmessage-queues",{"title":345,"path":346,"stem":347},"Glossary","\u002Fglossary","glossary",{"id":349,"title":135,"body":350,"description":3451,"extension":3452,"links":3453,"meta":3454,"navigation":730,"path":136,"seo":3455,"stem":137,"__hash__":3456},"docs\u002F3.engineering\u002Fcontributing\u002Fback-end\u002Fllm-prompts.md",{"type":351,"value":352,"toc":3414},"minimark",[353,358,362,367,372,437,440,444,447,451,454,466,489,497,504,540,548,558,565,588,592,599,663,670,689,1097,1101,1121,1643,1647,1656,1658,1665,1673,1677,1680,1706,1722,1728,1734,1751,1759,1770,1791,1793,1797,1800,1845,1847,1851,1857,1860,1883,1890,1942,1948,1967,1969,1973,1976,2036,2057,2059,2063,2072,2075,2078,2080,2084,2088,2091,2114,2118,2125,2153,2155,2164,2177,2208,2214,2216,2220,2250,2252,2256,2305,2311,2325,2327,2331,2334,2352,2436,2446,2448,2452,2456,2459,2593,2597,2603,2653,2657,2706,2710,2759,2761,2763,2767,2771,2780,2878,2892,2894,2898,2901,2926,2930,2967,2969,2973,2977,3065,3069,3072,3125,3127,3131,3278,3280,3286,3292,3334,3336,3340,3410],[354,355,357],"h2",{"id":356},"overview-architecture","Overview & Architecture",[359,360,361],"p",{},"We maintain a strict separation between application code, prompt definitions, and observability:",[363,364],"mermaid",{":zoom":365,"code":366},"1","graph TD\n    A(\"\u003Cdiv align='left'>\u003Cb>platform-api \u002F api-cps\u003C\u002Fb>\u003C\u002Fdiv>\"):::client\n    B(\"\u003Cdiv align='left'>\u003Cb>esp-prompts\u003C\u002Fb> (Git Repo)\u003C\u002Fdiv>\"):::client\n    C(\"\u003Cdiv align='left'>\u003Cb>Langfuse LLMOps Platform\u003C\u002Fb>\u003Cbr\u002F>https:\u002F\u002Fesplf.esprofiler.com\u003Cbr\u002F>• Prompt Versioning & Storage\u003Cbr\u002F>• Environment Labels (staging vs production)\u003Cbr\u002F>• Traces & Generation Spans\u003C\u002Fdiv>\"):::agent\n    D(\"\u003Cdiv align='left'>\u003Cb>Spring Boot: LangfusePromptService\u003C\u002Fb>\u003Cbr\u002F>• Startup Ingestion (ApplicationReadyEvent)\u003Cbr\u002F>• Scheduled Quartz Sweep (Every 20 mins)\u003Cbr\u002F>• Instant Ingestion API (PATCH \u002Fschedules\u002Frun)\u003Cbr\u002F>• Dual-Layer Cache (In-Memory RAM + Disk)\u003Cbr\u002F>• StringTemplate Raw Compilation\u003C\u002Fdiv>\"):::domain\n\n    A -->|Fallback Classpath .st| C\n    B -->|Automated GitHub Actions| C\n    C -->|Dynamic HTTP Fetch & Caching| D\n",[368,369,371],"h3",{"id":370},"core-principles","Core Principles",[373,374,375,394,412,422,431],"ol",{},[376,377,378,382,383,393],"li",{},[379,380,381],"strong",{},"Git is the Single Source of Truth:"," All prompts live in the ",[384,385,389],"a",{"href":386,"rel":387},"https:\u002F\u002Fgithub.com\u002FES-Profiler\u002Fesp-prompts",[388],"nofollow",[390,391,392],"code",{},"esp-prompts"," repository.",[376,395,396,399,400,403,404,407,408,411],{},[379,397,398],{},"Dynamic Ingestion via Langfuse:"," At runtime, services query Langfuse (",[390,401,402],{},"https:\u002F\u002Fesplf.esprofiler.com",") for the prompt version tagged with their target environment label (",[390,405,406],{},"production"," by default, or ",[390,409,410],{},"staging"," in test environments).",[376,413,414,417,418,421],{},[379,415,416],{},"Resilient Local Fallbacks:"," Every prompt declared in code includes a local classpath fallback file (e.g. ",[390,419,420],{},"src\u002Fmain\u002Fresources\u002Fintelligence\u002Fprompts\u002F*.st",") to ensure services start reliably even if Langfuse is unreachable.",[376,423,424,427,428,430],{},[379,425,426],{},"Testing on Staging Before Production:"," Changes must always be verified on Staging before being promoted to ",[390,429,406],{},".",[376,432,433,436],{},[379,434,435],{},"Benchmarking & Evaluation (Future \u002F TBD):"," Automated evaluation pipelines and benchmark datasets by the Data\u002FAI team are planned for future releases. Developers can log data-tasks to contribute to this future benchmark suite.",[438,439],"hr",{},[354,441,443],{"id":442},"adding-new-prompts","Adding New Prompts",[359,445,446],{},"Follow these steps when creating a brand new prompt that has never existed in the platform or Langfuse.",[368,448,450],{"id":449},"workflow-summary","Workflow Summary",[363,452],{":zoom":365,"code":453},"graph TD\n    S1(\"\u003Cdiv align='left'>\u003Cb>1. Backend Implementation\u003C\u002Fb> (platform-api \u002F api-cps)\u003Cbr\u002F>• Create classpath fallback prompt (.st file)\u003Cbr\u002F>• Inject LangfusePromptService and wire ChatClient\u003Cbr\u002F>• Add LangfusePromptObservationAdvisor\u003Cbr\u002F>• Create PR and obtain review approval\u003C\u002Fdiv>\"):::infra\n    S2(\"\u003Cdiv align='left'>\u003Cb>2. Create Prompt in esp-prompts Repository\u003C\u002Fb>\u003Cbr\u002F>• Add prompt markdown file in platform\u002F or cps\u002F\u003Cbr\u002F>• Open PR in esp-prompts referencing backend PR\u003Cbr\u002F>• Merge to main → auto-syncs to Langfuse with staging label\u003C\u002Fdiv>\"):::infra\n    S3(\"\u003Cdiv align='left'>\u003Cb>3. Staging Verification & Testing\u003C\u002Fb>\u003Cbr\u002F>• Deploy\u002Ftest backend on Staging (ESP_LANGFUSE_PROMPTS_LABEL=staging)\u003Cbr\u002F>• Verify generation spans and traces in Langfuse\u003C\u002Fdiv>\"):::infra\n    S4(\"\u003Cdiv align='left'>\u003Cb>4. Open Data-Task for Benchmarking\u003C\u002Fb> (Optional \u002F TBD)\u003Cbr\u002F>• Create GitHub Issue with Data and Back-End labels\u003Cbr\u002F>• Log golden dataset \u002F test scenarios for future AI benchmark suite\u003C\u002Fdiv>\"):::infra\n    S5(\"\u003Cdiv align='left'>\u003Cb>5. Promote Prompt to Production & Release Backend\u003C\u002Fb>\u003Cbr\u002F>• Run 'Promote Prompts to Production' GitHub Action in esp-prompts\u003Cbr\u002F>• Reviewer approves production environment gate in GitHub\u003Cbr\u002F>• Prompt version is labelled production\u003Cbr\u002F>• Merge and release the backend service PR\u003C\u002Fdiv>\"):::client\n\n    S1 --> S2 --> S3 --> S4 --> S5\n",[368,455,457,458,461,462,465],{"id":456},"step-1-backend-implementation-platform-api-api-cps","Step 1: Backend Implementation (",[390,459,460],{},"platform-api"," \u002F ",[390,463,464],{},"api-cps",")",[467,468,470,473,474,477,478,480,481,484,485,488],"callout",{"icon":469},"i-lucide-lightbulb",[379,471,472],{},"Local Development Independence:"," As a backend developer, you do ",[379,475,476],{},"not"," need to wait for ",[390,479,392],{}," or Langfuse to start coding or running unit tests. The backend service is completely functional locally because ",[390,482,483],{},"LangfusePromptService"," uses your local static classpath ",[390,486,487],{},".st"," file whenever a remote prompt is not found or when running offline.",[490,491,493,494,496],"h4",{"id":492},"_1-add-the-static-fallback-prompt-st-file","1. Add the Static Fallback Prompt (",[390,495,487],{}," file)",[359,498,499,500,503],{},"Static fallback prompt templates live under ",[390,501,502],{},"src\u002Fmain\u002Fresources\u002F"," in your backend application:",[505,506,507,526],"ul",{},[376,508,509,514,515,518,519,518,522,525],{},[379,510,511],{},[390,512,513],{},"src\u002Fmain\u002Fresources\u002Fintelligence\u002Fprompts\u002F"," — Standard copilot, insight, and platform agents (e.g., ",[390,516,517],{},"insights\u002Fsignal-evaluation.st",", ",[390,520,521],{},"agent-copilot.st",[390,523,524],{},"agent-notebook.st",").",[376,527,528,533,534,518,537,525],{},[379,529,530],{},[390,531,532],{},"src\u002Fmain\u002Fresources\u002Fagent-tasks\u002F"," — Workflow-specific agents (e.g., ",[390,535,536],{},"agent-tasks\u002Fgeneral\u002F",[390,538,539],{},"agent-tasks\u002Fproduct-comparison\u002F",[359,541,542],{},[379,543,544,545],{},"Example: ",[390,546,547],{},"src\u002Fmain\u002Fresources\u002Fintelligence\u002Fprompts\u002Finsights\u002Fsignal-evaluation.st",[549,550,556],"pre",{"className":551,"code":553,"language":554,"meta":555},[552],"language-text","You are an expert Cybersecurity Intelligence Analyst. Your task is to map a new observation (Finding) to the single best matching high-level trend (Signal) from a provided list of candidate Signals.\n\nStrict Rule: A Finding can only belong to AT MOST ONE Signal.\n\nHere is the Finding to evaluate:\nTitle: \u003Cfinding.title>\nDescription: \u003Cfinding.description>\n\nHere are the candidate Signals:\n\u003CcandidateSignals:{s |\n- ID: \u003Cs.id>\n  Title: \u003Cs.title>\n  Description: \u003Cs.description>\n  Type: \u003Cs.type>\n}>\n","text","",[390,557,553],{"__ignoreMap":555},[359,559,560,561,430],{},"The variables injected are injected into the prompt when ",[384,562,564],{"href":563},"#3-calling-the-agent-service-in-java","calling the agent service in Java",[467,566,568,571,572,575,576,579,580,583,584,587],{"icon":567},"i-lucide-info",[379,569,570],{},"StringTemplate Syntax:"," Prompts support ",[390,573,574],{},"{variable}"," and ",[390,577,578],{},"\u003Cvariable>"," placeholders, object property access (",[390,581,582],{},"\u003Cfinding.title>","), and collection iterations (",[390,585,586],{},"\u003CcandidateSignals:{s | ...}>","). Prompts are synchronized raw so that Spring Boot's StringTemplate engine compiles them directly.",[490,589,591],{"id":590},"understanding-the-prompt-resolution-cache-hierarchy","Understanding the Prompt Resolution & Cache Hierarchy",[359,593,594,595,598],{},"When ",[390,596,597],{},"langfusePromptService.getPrompt(PROMPT_NAME, fallbackPrompt)"," is called at runtime, it resolves the prompt through a 4-tier hierarchy:",[373,600,601,611,630,652],{},[376,602,603,610],{},[379,604,605,606,609],{},"RAM Cache (",[390,607,608],{},"memoryCache"," Map):"," Checked first (0ms latency, zero disk I\u002FO).",[376,612,613,616,617,620,621,624,625,627,628,525],{},[379,614,615],{},"Remote Langfuse Ingestion:"," If online and configured (",[390,618,619],{},"ESP_LLM_OBSERVATION_OTLP_ENDPOINT","), fetches the version tagged with ",[390,622,623],{},"ESP_LANGFUSE_PROMPTS_LABEL"," (",[390,626,406],{}," or ",[390,629,410],{},[376,631,632,643,644,647,648,651],{},[379,633,634,635,638,639,642],{},"Disk Cache (",[390,636,637],{},"resources\u002Fprompts\u002F\u003Cprompt>.st"," & ",[390,640,641],{},".version","):"," Persisted on the container filesystem (configured via ",[390,645,646],{},"esp.langfuse.prompts.cache-dir",", defaults to ",[390,649,650],{},"resources\u002Fprompts\u002F",") so prompts survive network blips.",[376,653,654,657,658,660,661,430],{},[379,655,656],{},"Local Classpath Fallback:"," If Langfuse is unreachable, disabled, or if the prompt hasn't been created in Langfuse yet, it falls back to your local ",[390,659,487],{}," resource in ",[390,662,502],{},[490,664,666,667,669],{"id":665},"_2-wire-langfusepromptservice-and-chatclient-advisor","2. Wire ",[390,668,483],{}," and ChatClient Advisor",[359,671,672,673,676,677,680,681,684,685,688],{},"In your Spring configuration class (e.g., ",[390,674,675],{},"SignalGenerationAgentConfig.java"," in ",[379,678,679],{},"esp-platform"," project), declare a ",[390,682,683],{},"ChatClient"," bean wrapped in ",[390,686,687],{},"ReloadableChatClient",". This binds your feature to Langfuse, attaches OpenTelemetry tracing, and allows the prompt to be hot-reloaded dynamically at runtime:",[549,690,694],{"className":691,"code":692,"filename":675,"language":693,"meta":555,"style":555},"language-java shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","@Configuration\npublic class SignalGenerationAgentConfig {\n\n  private static final String SIGNAL_EVALUATION_PROMPT_NAME = \"signal-evaluation\";\n\n  @Bean\n  public ChatClient signalEvaluationAgent(\n      @Value(\"classpath:intelligence\u002Fprompts\u002Finsights\u002Fsignal-evaluation.st\") Resource systemPrompt,\n      GoogleGenAiChatModel chatModel,\n      ObservedChatClientBuilder observedChatClientBuilder,\n      LangfusePromptService langfusePromptService\n  ) {\n    \u002F\u002F ReloadableChatClient enables zero-downtime hot-swapping of prompt updates\n    return new ReloadableChatClient(SIGNAL_EVALUATION_PROMPT_NAME, () ->\n        observedChatClientBuilder.from(chatModel, \"signal-evaluation\")\n            \u002F\u002F Dynamically loads from Langfuse with fallback to local classpath\n            .defaultSystem(\n                langfusePromptService.getPrompt(SIGNAL_EVALUATION_PROMPT_NAME, systemPrompt))\n            .defaultOptions(GoogleGenAiChatOptions.builder()\n                .model(IntelligenceLevel.MEDIUM.model)\n                .includeThoughts(false))\n            .defaultAdvisors(\n                \u002F\u002F Links OTel spans and Langfuse generation traces to this prompt & version\n                new LangfusePromptObservationAdvisor(SIGNAL_EVALUATION_PROMPT_NAME,\n                    langfusePromptService)\n            )\n            .build()\n    );\n  }\n}\n","java",[390,695,696,709,725,732,767,772,781,797,828,839,850,859,867,874,901,928,934,945,967,988,1013,1024,1034,1040,1055,1063,1069,1079,1085,1091],{"__ignoreMap":555},[697,698,701,705],"span",{"class":699,"line":700},"line",1,[697,702,704],{"class":703},"sMK4o","@",[697,706,708],{"class":707},"spNyl","Configuration\n",[697,710,712,715,718,722],{"class":699,"line":711},2,[697,713,714],{"class":707},"public",[697,716,717],{"class":707}," class",[697,719,721],{"class":720},"sBMFI"," SignalGenerationAgentConfig",[697,723,724],{"class":703}," {\n",[697,726,728],{"class":699,"line":727},3,[697,729,731],{"emptyLinePlaceholder":730},true,"\n",[697,733,735,738,741,744,747,751,754,757,761,764],{"class":699,"line":734},4,[697,736,737],{"class":707},"  private",[697,739,740],{"class":707}," static",[697,742,743],{"class":707}," final",[697,745,746],{"class":707}," String",[697,748,750],{"class":749},"sTEyZ"," SIGNAL_EVALUATION_PROMPT_NAME ",[697,752,753],{"class":703},"=",[697,755,756],{"class":703}," \"",[697,758,760],{"class":759},"sfazB","signal-evaluation",[697,762,763],{"class":703},"\"",[697,765,766],{"class":703},";\n",[697,768,770],{"class":699,"line":769},5,[697,771,731],{"emptyLinePlaceholder":730},[697,773,775,778],{"class":699,"line":774},6,[697,776,777],{"class":703},"  @",[697,779,780],{"class":707},"Bean\n",[697,782,784,787,790,794],{"class":699,"line":783},7,[697,785,786],{"class":707},"  public",[697,788,789],{"class":707}," ChatClient",[697,791,793],{"class":792},"s2Zo4"," signalEvaluationAgent",[697,795,796],{"class":703},"(\n",[697,798,800,803,806,809,811,814,816,818,821,825],{"class":699,"line":799},8,[697,801,802],{"class":703},"      @",[697,804,805],{"class":707},"Value",[697,807,808],{"class":703},"(",[697,810,763],{"class":703},[697,812,813],{"class":759},"classpath:intelligence\u002Fprompts\u002Finsights\u002Fsignal-evaluation.st",[697,815,763],{"class":703},[697,817,465],{"class":703},[697,819,820],{"class":707}," Resource",[697,822,824],{"class":823},"sHdIc"," systemPrompt",[697,826,827],{"class":703},",\n",[697,829,831,834,837],{"class":699,"line":830},9,[697,832,833],{"class":707},"      GoogleGenAiChatModel",[697,835,836],{"class":823}," chatModel",[697,838,827],{"class":703},[697,840,842,845,848],{"class":699,"line":841},10,[697,843,844],{"class":707},"      ObservedChatClientBuilder",[697,846,847],{"class":823}," observedChatClientBuilder",[697,849,827],{"class":703},[697,851,853,856],{"class":699,"line":852},11,[697,854,855],{"class":707},"      LangfusePromptService",[697,857,858],{"class":823}," langfusePromptService\n",[697,860,862,865],{"class":699,"line":861},12,[697,863,864],{"class":703},"  )",[697,866,724],{"class":703},[697,868,870],{"class":699,"line":869},13,[697,871,873],{"class":872},"sHwdD","    \u002F\u002F ReloadableChatClient enables zero-downtime hot-swapping of prompt updates\n",[697,875,877,881,884,887,889,892,895,898],{"class":699,"line":876},14,[697,878,880],{"class":879},"s7zQu","    return",[697,882,883],{"class":879}," new",[697,885,886],{"class":792}," ReloadableChatClient",[697,888,808],{"class":703},[697,890,891],{"class":749},"SIGNAL_EVALUATION_PROMPT_NAME",[697,893,894],{"class":703},",",[697,896,897],{"class":703}," ()",[697,899,900],{"class":707}," ->\n",[697,902,904,907,909,912,914,917,919,921,923,925],{"class":699,"line":903},15,[697,905,906],{"class":749},"        observedChatClientBuilder",[697,908,430],{"class":703},[697,910,911],{"class":792},"from",[697,913,808],{"class":703},[697,915,916],{"class":749},"chatModel",[697,918,894],{"class":703},[697,920,756],{"class":703},[697,922,760],{"class":759},[697,924,763],{"class":703},[697,926,927],{"class":703},")\n",[697,929,931],{"class":699,"line":930},16,[697,932,933],{"class":872},"            \u002F\u002F Dynamically loads from Langfuse with fallback to local classpath\n",[697,935,937,940,943],{"class":699,"line":936},17,[697,938,939],{"class":703},"            .",[697,941,942],{"class":792},"defaultSystem",[697,944,796],{"class":703},[697,946,948,951,953,956,958,960,962,964],{"class":699,"line":947},18,[697,949,950],{"class":749},"                langfusePromptService",[697,952,430],{"class":703},[697,954,955],{"class":792},"getPrompt",[697,957,808],{"class":703},[697,959,891],{"class":749},[697,961,894],{"class":703},[697,963,824],{"class":749},[697,965,966],{"class":703},"))\n",[697,968,970,972,975,977,980,982,985],{"class":699,"line":969},19,[697,971,939],{"class":703},[697,973,974],{"class":792},"defaultOptions",[697,976,808],{"class":703},[697,978,979],{"class":749},"GoogleGenAiChatOptions",[697,981,430],{"class":703},[697,983,984],{"class":792},"builder",[697,986,987],{"class":703},"()\n",[697,989,991,994,997,999,1002,1004,1007,1009,1011],{"class":699,"line":990},20,[697,992,993],{"class":703},"                .",[697,995,996],{"class":792},"model",[697,998,808],{"class":703},[697,1000,1001],{"class":749},"IntelligenceLevel",[697,1003,430],{"class":703},[697,1005,1006],{"class":749},"MEDIUM",[697,1008,430],{"class":703},[697,1010,996],{"class":749},[697,1012,927],{"class":703},[697,1014,1016,1018,1021],{"class":699,"line":1015},21,[697,1017,993],{"class":703},[697,1019,1020],{"class":792},"includeThoughts",[697,1022,1023],{"class":703},"(false))\n",[697,1025,1027,1029,1032],{"class":699,"line":1026},22,[697,1028,939],{"class":703},[697,1030,1031],{"class":792},"defaultAdvisors",[697,1033,796],{"class":703},[697,1035,1037],{"class":699,"line":1036},23,[697,1038,1039],{"class":872},"                \u002F\u002F Links OTel spans and Langfuse generation traces to this prompt & version\n",[697,1041,1043,1046,1049,1051,1053],{"class":699,"line":1042},24,[697,1044,1045],{"class":879},"                new",[697,1047,1048],{"class":792}," LangfusePromptObservationAdvisor",[697,1050,808],{"class":703},[697,1052,891],{"class":749},[697,1054,827],{"class":703},[697,1056,1058,1061],{"class":699,"line":1057},25,[697,1059,1060],{"class":749},"                    langfusePromptService",[697,1062,927],{"class":703},[697,1064,1066],{"class":699,"line":1065},26,[697,1067,1068],{"class":703},"            )\n",[697,1070,1072,1074,1077],{"class":699,"line":1071},27,[697,1073,939],{"class":703},[697,1075,1076],{"class":792},"build",[697,1078,987],{"class":703},[697,1080,1082],{"class":699,"line":1081},28,[697,1083,1084],{"class":703},"    );\n",[697,1086,1088],{"class":699,"line":1087},29,[697,1089,1090],{"class":703},"  }\n",[697,1092,1094],{"class":699,"line":1093},30,[697,1095,1096],{"class":703},"}\n",[490,1098,1100],{"id":1099},"_3-calling-the-agent-service-in-java","3. Calling the Agent Service in Java",[359,1102,1103,1104,1106,1107,1113,1114,627,1117,1120],{},"Inject your configured ",[390,1105,683],{}," bean into your service (e.g., ",[384,1108,1110],{"href":1109},"file:\u002F\u002F\u002Fc:\u002Fdevelopment\u002Fbackend\u002Fapplications\u002Fesp-platform\u002Fsrc\u002Fmain\u002Fjava\u002Fcom\u002Fesprofiler\u002Fplatform\u002Finsight\u002Fservice\u002FSignalGenerationService.java",[390,1111,1112],{},"SignalGenerationService.java","), passing parameters into the prompt using ",[390,1115,1116],{},".system(s -> s.param(...))",[390,1118,1119],{},".system(s -> s.params(map))",":",[549,1122,1124],{"className":691,"code":1123,"language":693,"meta":555,"style":555},"package com.esprofiler.platform.insight.service;\n\nimport com.esprofiler.platform.insight.dto.SignalGenerationResponses.SignalMatchResponse;\nimport com.esprofiler.platform.insight.entity.FindingEntity;\nimport com.esprofiler.platform.insight.entity.SignalEntity;\nimport java.util.List;\nimport lombok.RequiredArgsConstructor;\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.ai.chat.client.ChatClient;\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.stereotype.Service;\n\n@Slf4j\n@Service\n@RequiredArgsConstructor\npublic class SignalGenerationService {\n\n  @Qualifier(\"signalEvaluationAgent\")\n  private final ChatClient signalEvaluationAgent;\n\n  public SignalMatchResponse evaluateFinding(FindingEntity finding, List\u003CSignalEntity> candidates) {\n    return signalEvaluationAgent.prompt()\n        \u002F\u002F Passes 'finding' object and 'candidateSignals' collection into the template\n        .system(s -> s\n            .param(\"finding\", finding)\n            .param(\"candidateSignals\", candidates))\n        .user(\"Please evaluate this finding against the candidate signals.\")\n        .call()\n        .entity(SignalMatchResponse.class);\n  }\n}\n",[390,1125,1126,1157,1161,1197,1227,1256,1275,1289,1312,1345,1377,1399,1403,1410,1417,1424,1435,1439,1456,1468,1472,1509,1522,1527,1546,1568,1589,1607,1616,1634,1638],{"__ignoreMap":555},[697,1127,1128,1132,1135,1137,1140,1142,1145,1147,1150,1152,1155],{"class":699,"line":700},[697,1129,1131],{"class":1130},"sbssI","package",[697,1133,1134],{"class":707}," com",[697,1136,430],{"class":703},[697,1138,1139],{"class":707},"esprofiler",[697,1141,430],{"class":703},[697,1143,1144],{"class":707},"platform",[697,1146,430],{"class":703},[697,1148,1149],{"class":707},"insight",[697,1151,430],{"class":703},[697,1153,1154],{"class":707},"service",[697,1156,766],{"class":703},[697,1158,1159],{"class":699,"line":711},[697,1160,731],{"emptyLinePlaceholder":730},[697,1162,1163,1166,1168,1170,1172,1174,1176,1178,1180,1182,1185,1187,1190,1192,1195],{"class":699,"line":727},[697,1164,1165],{"class":1130},"import",[697,1167,1134],{"class":707},[697,1169,430],{"class":703},[697,1171,1139],{"class":707},[697,1173,430],{"class":703},[697,1175,1144],{"class":707},[697,1177,430],{"class":703},[697,1179,1149],{"class":707},[697,1181,430],{"class":703},[697,1183,1184],{"class":707},"dto",[697,1186,430],{"class":703},[697,1188,1189],{"class":707},"SignalGenerationResponses",[697,1191,430],{"class":703},[697,1193,1194],{"class":707},"SignalMatchResponse",[697,1196,766],{"class":703},[697,1198,1199,1201,1203,1205,1207,1209,1211,1213,1215,1217,1220,1222,1225],{"class":699,"line":734},[697,1200,1165],{"class":1130},[697,1202,1134],{"class":707},[697,1204,430],{"class":703},[697,1206,1139],{"class":707},[697,1208,430],{"class":703},[697,1210,1144],{"class":707},[697,1212,430],{"class":703},[697,1214,1149],{"class":707},[697,1216,430],{"class":703},[697,1218,1219],{"class":707},"entity",[697,1221,430],{"class":703},[697,1223,1224],{"class":707},"FindingEntity",[697,1226,766],{"class":703},[697,1228,1229,1231,1233,1235,1237,1239,1241,1243,1245,1247,1249,1251,1254],{"class":699,"line":769},[697,1230,1165],{"class":1130},[697,1232,1134],{"class":707},[697,1234,430],{"class":703},[697,1236,1139],{"class":707},[697,1238,430],{"class":703},[697,1240,1144],{"class":707},[697,1242,430],{"class":703},[697,1244,1149],{"class":707},[697,1246,430],{"class":703},[697,1248,1219],{"class":707},[697,1250,430],{"class":703},[697,1252,1253],{"class":707},"SignalEntity",[697,1255,766],{"class":703},[697,1257,1258,1260,1263,1265,1268,1270,1273],{"class":699,"line":774},[697,1259,1165],{"class":1130},[697,1261,1262],{"class":707}," java",[697,1264,430],{"class":703},[697,1266,1267],{"class":707},"util",[697,1269,430],{"class":703},[697,1271,1272],{"class":707},"List",[697,1274,766],{"class":703},[697,1276,1277,1279,1282,1284,1287],{"class":699,"line":783},[697,1278,1165],{"class":1130},[697,1280,1281],{"class":707}," lombok",[697,1283,430],{"class":703},[697,1285,1286],{"class":707},"RequiredArgsConstructor",[697,1288,766],{"class":703},[697,1290,1291,1293,1295,1297,1300,1302,1305,1307,1310],{"class":699,"line":799},[697,1292,1165],{"class":1130},[697,1294,1281],{"class":707},[697,1296,430],{"class":703},[697,1298,1299],{"class":707},"extern",[697,1301,430],{"class":703},[697,1303,1304],{"class":707},"slf4j",[697,1306,430],{"class":703},[697,1308,1309],{"class":707},"Slf4j",[697,1311,766],{"class":703},[697,1313,1314,1316,1319,1321,1324,1326,1329,1331,1334,1336,1339,1341,1343],{"class":699,"line":830},[697,1315,1165],{"class":1130},[697,1317,1318],{"class":707}," org",[697,1320,430],{"class":703},[697,1322,1323],{"class":707},"springframework",[697,1325,430],{"class":703},[697,1327,1328],{"class":707},"ai",[697,1330,430],{"class":703},[697,1332,1333],{"class":707},"chat",[697,1335,430],{"class":703},[697,1337,1338],{"class":707},"client",[697,1340,430],{"class":703},[697,1342,683],{"class":707},[697,1344,766],{"class":703},[697,1346,1347,1349,1351,1353,1355,1357,1360,1362,1365,1367,1370,1372,1375],{"class":699,"line":841},[697,1348,1165],{"class":1130},[697,1350,1318],{"class":707},[697,1352,430],{"class":703},[697,1354,1323],{"class":707},[697,1356,430],{"class":703},[697,1358,1359],{"class":707},"beans",[697,1361,430],{"class":703},[697,1363,1364],{"class":707},"factory",[697,1366,430],{"class":703},[697,1368,1369],{"class":707},"annotation",[697,1371,430],{"class":703},[697,1373,1374],{"class":707},"Qualifier",[697,1376,766],{"class":703},[697,1378,1379,1381,1383,1385,1387,1389,1392,1394,1397],{"class":699,"line":852},[697,1380,1165],{"class":1130},[697,1382,1318],{"class":707},[697,1384,430],{"class":703},[697,1386,1323],{"class":707},[697,1388,430],{"class":703},[697,1390,1391],{"class":707},"stereotype",[697,1393,430],{"class":703},[697,1395,1396],{"class":707},"Service",[697,1398,766],{"class":703},[697,1400,1401],{"class":699,"line":861},[697,1402,731],{"emptyLinePlaceholder":730},[697,1404,1405,1407],{"class":699,"line":869},[697,1406,704],{"class":703},[697,1408,1409],{"class":707},"Slf4j\n",[697,1411,1412,1414],{"class":699,"line":876},[697,1413,704],{"class":703},[697,1415,1416],{"class":707},"Service\n",[697,1418,1419,1421],{"class":699,"line":903},[697,1420,704],{"class":703},[697,1422,1423],{"class":707},"RequiredArgsConstructor\n",[697,1425,1426,1428,1430,1433],{"class":699,"line":930},[697,1427,714],{"class":707},[697,1429,717],{"class":707},[697,1431,1432],{"class":720}," SignalGenerationService",[697,1434,724],{"class":703},[697,1436,1437],{"class":699,"line":936},[697,1438,731],{"emptyLinePlaceholder":730},[697,1440,1441,1443,1445,1447,1449,1452,1454],{"class":699,"line":947},[697,1442,777],{"class":703},[697,1444,1374],{"class":707},[697,1446,808],{"class":703},[697,1448,763],{"class":703},[697,1450,1451],{"class":759},"signalEvaluationAgent",[697,1453,763],{"class":703},[697,1455,927],{"class":703},[697,1457,1458,1460,1462,1464,1466],{"class":699,"line":969},[697,1459,737],{"class":707},[697,1461,743],{"class":707},[697,1463,789],{"class":707},[697,1465,793],{"class":749},[697,1467,766],{"class":703},[697,1469,1470],{"class":699,"line":990},[697,1471,731],{"emptyLinePlaceholder":730},[697,1473,1474,1476,1479,1482,1484,1486,1489,1491,1494,1497,1499,1502,1505,1507],{"class":699,"line":1015},[697,1475,786],{"class":707},[697,1477,1478],{"class":707}," SignalMatchResponse",[697,1480,1481],{"class":792}," evaluateFinding",[697,1483,808],{"class":703},[697,1485,1224],{"class":707},[697,1487,1488],{"class":823}," finding",[697,1490,894],{"class":703},[697,1492,1493],{"class":707}," List",[697,1495,1496],{"class":703},"\u003C",[697,1498,1253],{"class":707},[697,1500,1501],{"class":703},">",[697,1503,1504],{"class":823}," candidates",[697,1506,465],{"class":703},[697,1508,724],{"class":703},[697,1510,1511,1513,1515,1517,1520],{"class":699,"line":1026},[697,1512,880],{"class":879},[697,1514,793],{"class":749},[697,1516,430],{"class":703},[697,1518,1519],{"class":792},"prompt",[697,1521,987],{"class":703},[697,1523,1524],{"class":699,"line":1036},[697,1525,1526],{"class":872},"        \u002F\u002F Passes 'finding' object and 'candidateSignals' collection into the template\n",[697,1528,1529,1532,1535,1537,1540,1543],{"class":699,"line":1042},[697,1530,1531],{"class":703},"        .",[697,1533,1534],{"class":792},"system",[697,1536,808],{"class":703},[697,1538,1539],{"class":749},"s ",[697,1541,1542],{"class":707},"->",[697,1544,1545],{"class":749}," s\n",[697,1547,1548,1550,1553,1555,1557,1560,1562,1564,1566],{"class":699,"line":1057},[697,1549,939],{"class":703},[697,1551,1552],{"class":792},"param",[697,1554,808],{"class":703},[697,1556,763],{"class":703},[697,1558,1559],{"class":759},"finding",[697,1561,763],{"class":703},[697,1563,894],{"class":703},[697,1565,1488],{"class":749},[697,1567,927],{"class":703},[697,1569,1570,1572,1574,1576,1578,1581,1583,1585,1587],{"class":699,"line":1065},[697,1571,939],{"class":703},[697,1573,1552],{"class":792},[697,1575,808],{"class":703},[697,1577,763],{"class":703},[697,1579,1580],{"class":759},"candidateSignals",[697,1582,763],{"class":703},[697,1584,894],{"class":703},[697,1586,1504],{"class":749},[697,1588,966],{"class":703},[697,1590,1591,1593,1596,1598,1600,1603,1605],{"class":699,"line":1071},[697,1592,1531],{"class":703},[697,1594,1595],{"class":792},"user",[697,1597,808],{"class":703},[697,1599,763],{"class":703},[697,1601,1602],{"class":759},"Please evaluate this finding against the candidate signals.",[697,1604,763],{"class":703},[697,1606,927],{"class":703},[697,1608,1609,1611,1614],{"class":699,"line":1081},[697,1610,1531],{"class":703},[697,1612,1613],{"class":792},"call",[697,1615,987],{"class":703},[697,1617,1618,1620,1622,1624,1626,1628,1631],{"class":699,"line":1087},[697,1619,1531],{"class":703},[697,1621,1219],{"class":792},[697,1623,808],{"class":703},[697,1625,1194],{"class":749},[697,1627,430],{"class":703},[697,1629,1630],{"class":749},"class",[697,1632,1633],{"class":703},");\n",[697,1635,1636],{"class":699,"line":1093},[697,1637,1090],{"class":703},[697,1639,1641],{"class":699,"line":1640},31,[697,1642,1096],{"class":703},[490,1644,1646],{"id":1645},"_4-open-backend-pull-request","4. Open Backend Pull Request",[359,1648,1649,1650,627,1652,1655],{},"Push your branch and open a PR in ",[390,1651,679],{},[390,1653,1654],{},"esp-cps",". Follow standard code review guidelines and obtain approval.",[438,1657],{},[368,1659,1661,1662,1664],{"id":1660},"step-2-create-prompt-in-esp-prompts-repository","Step 2: Create Prompt in ",[390,1663,392],{}," Repository",[359,1666,1667,1668,430],{},"Once your backend PR is reviewed and approved, create the prompt definition in ",[384,1669,1671],{"href":386,"rel":1670},[388],[390,1672,392],{},[490,1674,1676],{"id":1675},"_1-add-the-prompt-file","1. Add the Prompt File",[359,1678,1679],{},"Place your prompt file in the corresponding folder:",[505,1681,1682,1690,1698],{},[376,1683,1684,1689],{},[379,1685,1686],{},[390,1687,1688],{},"platform\u002Fespi\u002F"," — Copilot conversation agents and skills.",[376,1691,1692,1697],{},[379,1693,1694],{},[390,1695,1696],{},"platform\u002Finsights\u002F"," — Automated findings, signals, and synthesis agents.",[376,1699,1700,1705],{},[379,1701,1702],{},[390,1703,1704],{},"cps\u002F"," — Central Provider Service categorization and mapping engines.",[359,1707,1708,1711,1712,1715,1716,627,1719,525],{},[379,1709,1710],{},"Naming Convention:"," Use short, lowercase, hyphenated names matching your ",[390,1713,1714],{},"PROMPT_NAME"," constant (e.g. ",[390,1717,1718],{},"platform\u002Finsights\u002Fsignals\u002Fmy-feature.md",[390,1720,1721],{},"platform\u002Fespi\u002Fskills\u002Fmy-feature-skill\u002FSKILL.md",[490,1723,1725,1726],{"id":1724},"_2-open-pr-in-esp-prompts","2. Open PR in ",[390,1727,392],{},[359,1729,1730,1731,1733],{},"Open a PR in ",[390,1732,392],{}," referencing your backend PR:",[549,1735,1739],{"className":1736,"code":1737,"language":1738,"meta":555,"style":555},"language-markdown shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","Relates to ES-Profiler\u002Fplatform-apim#1234\nAdds the new prompt definition for the MyFeature assistant.\n","markdown",[390,1740,1741,1746],{"__ignoreMap":555},[697,1742,1743],{"class":699,"line":700},[697,1744,1745],{},"Relates to ES-Profiler\u002Fplatform-apim#1234\n",[697,1747,1748],{"class":699,"line":711},[697,1749,1750],{},"Adds the new prompt definition for the MyFeature assistant.\n",[490,1752,1754,1755,1758],{"id":1753},"_3-merge-to-main-automatic-staging-sync","3. Merge to ",[390,1756,1757],{},"main"," (Automatic Staging Sync)",[359,1760,1761,1762,676,1764,1766,1767,1120],{},"When merged into ",[390,1763,1757],{},[390,1765,392],{},", GitHub Actions automatically triggers ",[390,1768,1769],{},".github\u002Fworkflows\u002Fsync-prompts-staging.yml",[505,1771,1772,1775,1782],{},[376,1773,1774],{},"It uploads the new prompt to Langfuse.",[376,1776,1777,1778,430],{},"Labels the version as ",[379,1779,1780],{},[390,1781,410],{},[376,1783,1784,1785,518,1788,525],{},"Applies routing tags (e.g. ",[390,1786,1787],{},"service-platform",[390,1789,1790],{},"domain-insights",[438,1792],{},[368,1794,1796],{"id":1795},"step-3-staging-verification-testing","Step 3: Staging Verification & Testing",[359,1798,1799],{},"Verify that your new prompt works end-to-end on Staging:",[373,1801,1802,1816,1819],{},[376,1803,1804,1805],{},"Deploy your backend branch\u002Fbuild to Staging with the staging label enabled:\n",[549,1806,1810],{"className":1807,"code":1808,"language":1809,"meta":555,"style":555},"language-properties shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","ESP_LANGFUSE_PROMPTS_LABEL=staging\n","properties",[390,1811,1812],{"__ignoreMap":555},[697,1813,1814],{"class":699,"line":700},[697,1815,1808],{},[376,1817,1818],{},"Trigger the feature in the staging UI or via API endpoint.",[376,1820,1821,1822,1826,1827],{},"Open the ",[384,1823,1825],{"href":402,"rel":1824},[388],"Langfuse Console",":\n",[505,1828,1829,1839],{},[376,1830,1831,1832,1835,1836,1838],{},"Under ",[379,1833,1834],{},"Prompts",", verify that your prompt appears and the ",[390,1837,410],{}," label is assigned.",[376,1840,1831,1841,1844],{},[379,1842,1843],{},"Tracing",", inspect the execution trace and confirm that the generation span is linked to your prompt name and version.",[438,1846],{},[368,1848,1850],{"id":1849},"step-4-open-a-data-task-for-benchmarking-optional-future-tbd","Step 4: Open a Data-Task for Benchmarking (Optional \u002F Future TBD)",[467,1852,1853,1856],{"icon":567},[379,1854,1855],{},"Benchmarking Status (TBD):"," Formal automated evaluation suites with the Data\u002FAI team are currently under active design. While not currently a blocking requirement for releasing prompts today, logging test scenarios helps populate the future evaluation pipeline.",[359,1858,1859],{},"If you wish to log a task for future benchmarking:",[373,1861,1862,1876],{},[376,1863,1864,1865,1868,1869,430],{},"In the repository, go to ",[379,1866,1867],{},"Issues"," > ",[384,1870,1873],{"href":1871,"rel":1872},"https:\u002F\u002Fgithub.com\u002FES-Profiler\u002Fplatform-api\u002Fissues\u002Fnew\u002Fchoose",[388],[379,1874,1875],{},"New Issue",[376,1877,1878,1879,1882],{},"Select the ",[379,1880,1881],{},"Data Benchmarking & Evaluation Task (AI \u002F Prompts)"," template:",[359,1884,1885],{},[1886,1887],"img",{"alt":1888,"src":1889},"GitHub Issue Template Selection","\u002Fimages\u002Fengineering\u002Fllm-prompts\u002Fissue-template-selection.png",[373,1891,1892],{"start":727},[376,1893,1894,1895],{},"Fill out the pre-populated form fields:\n",[505,1896,1897,1905,1916,1924,1930,1936],{},[376,1898,1899,1902,1903],{},[379,1900,1901],{},"Prompt Name in Langfuse:"," e.g. ",[390,1904,760],{},[376,1906,1907,1902,1910,1913,1914,465],{},[379,1908,1909],{},"Langfuse Version:",[390,1911,1912],{},"v1"," (currently tagged ",[390,1915,410],{},[376,1917,1918,1902,1921],{},[379,1919,1920],{},"Target Service & Related PRs:",[390,1922,1923],{},"platform-api (ES-Profiler\u002Fplatform-api#1234, ES-Profiler\u002Fesp-prompts#56)",[376,1925,1926,1929],{},[379,1927,1928],{},"Objective & Functional Role:"," Purpose, input context parameters, and expected JSON output structure.",[376,1931,1932,1935],{},[379,1933,1934],{},"Test Scenarios & Golden Dataset:"," Test cases or edge cases to populate the evaluation suite.",[376,1937,1938,1941],{},[379,1939,1940],{},"Langfuse Reference URLs:"," Direct links to the prompt in Langfuse and sample staging trace.",[359,1943,1944],{},[1886,1945],{"alt":1946,"src":1947},"GitHub Issue Form Fields","\u002Fimages\u002Fengineering\u002Fllm-prompts\u002Fissue-template-form.png",[373,1949,1950],{"start":734},[376,1951,1952,1953,575,1958,1963,1964,430],{},"The template automatically attaches the ",[379,1954,1955],{},[390,1956,1957],{},"Data",[379,1959,1960],{},[390,1961,1962],{},"Back-End"," labels. Click ",[379,1965,1966],{},"Submit new issue",[438,1968],{},[368,1970,1972],{"id":1971},"step-5-promote-prompt-to-production-release-backend","Step 5: Promote Prompt to Production & Release Backend",[359,1974,1975],{},"Once staging testing is complete:",[373,1977,1978,2014],{},[376,1979,1980,1985],{},[379,1981,1982,1983,1120],{},"Promote Prompt in ",[390,1984,392],{},[505,1986,1987,1998,2008],{},[376,1988,1989,1990,1868,1993,430],{},"Go to ",[379,1991,1992],{},"Actions",[384,1994,1997],{"href":1995,"rel":1996},"https:\u002F\u002Fgithub.com\u002FES-Profiler\u002Fesp-prompts\u002Factions\u002Fworkflows\u002Fpromote-prompts.yml",[388],"Promote Prompts to Production",[376,1999,2000,2001,2004,2005,525],{},"Enter your prompt name in the ",[390,2002,2003],{},"prompts"," input (e.g. ",[390,2006,2007],{},"my-feature",[376,2009,2010,2011,2013],{},"Run workflow. Review the dry-run plan, and have a required reviewer approve the ",[390,2012,406],{}," environment gate.",[376,2015,2016,2019],{},[379,2017,2018],{},"Release Backend Code:",[505,2020,2021,2029],{},[376,2022,2023,2024,461,2026,2028],{},"Merge and release the ",[390,2025,460],{},[390,2027,464],{}," PR.",[376,2030,2031,2032,2035],{},"Production containers boot up, query Langfuse for ",[390,2033,2034],{},"label=production",", and ingest the newly promoted prompt.",[467,2037,2038,2041,2042,2044,2045,2049,2050,2053,2054,2056],{"icon":567},[379,2039,2040],{},"How Version Promotion Works:"," The promotion workflow does ",[379,2043,476],{}," blindly promote the latest unverified version number. Instead, it explicitly targets the version currently tagged with the ",[379,2046,2047],{},[390,2048,410],{}," label (the version you tested), prints a dry-run diff in the ",[390,2051,2052],{},"plan"," step, and applies the ",[390,2055,406],{}," label only after review approval.",[438,2058],{},[354,2060,2062],{"id":2061},"modifying-existing-prompts","Modifying Existing Prompts",[359,2064,2065,2066,627,2069,430],{},"When modifying a prompt that already exists in production, determine whether the change is ",[379,2067,2068],{},"prompt-content only",[379,2070,2071],{},"requires backend code changes",[368,2073,450],{"id":2074},"workflow-summary-1",[363,2076],{":zoom":365,"code":2077},"graph TD\n    Start{\"Modifying an Existing Prompt\"}:::agent\n\n    ScenA(\"\u003Cdiv align='left'>\u003Cb>Scenario A: Content-Only\u003C\u002Fb>\u003Cbr\u002F>Tuning wording, system instructions,\u003Cbr\u002F>few-shot examples, reasoning steps\u003C\u002Fdiv>\"):::infra\n    ScenB(\"\u003Cdiv align='left'>\u003Cb>Scenario B: With Code Changes\u003C\u002Fb>\u003Cbr\u002F>Adding\u002Fremoving template variables,\u003Cbr\u002F>changing DTO schema, modifying tools\u003C\u002Fdiv>\"):::infra\n\n    BCode(\"\u003Cdiv align='left'>\u003Cb>1. Update .st fallback & Java code\u003C\u002Fb>\u003Cbr\u002F>\u003Cb>2. Open PR in platform-api \u002F api-cps\u003C\u002Fb>\u003C\u002Fdiv>\"):::domain\n\n    Sync(\"\u003Cdiv align='left'>\u003Cb>1. Edit prompt file in esp-prompts\u003C\u002Fb>\u003Cbr\u002F>\u003Cb>2. Open PR in esp-prompts\u003C\u002Fb>\u003Cbr\u002F>\u003Cb>3. Merge to main → auto-syncs with staging label\u003C\u002Fb>\u003C\u002Fdiv>\"):::client\n\n    Stage(\"\u003Cdiv align='left'>\u003Cb>2. Test changes on Staging\u003C\u002Fb>\u003Cbr\u002F>ESP_LANGFUSE_PROMPTS_LABEL=staging\u003C\u002Fdiv>\"):::infra\n\n    Promote(\"\u003Cdiv align='left'>\u003Cb>3. Promote prompt to Production via\u003C\u002Fb>\u003Cbr\u002F>GitHub Action in esp-prompts\u003C\u002Fdiv>\"):::agent\n\n    Ingest(\"\u003Cdiv align='left'>\u003Cb>4. Ingest Prompt Updates:\u003C\u002Fb>\u003Cbr\u002F>• Automatic: Quartz (Every 20 mins)\u003Cbr\u002F>• OR Instant: PATCH \u002Fapi\u002Fv1\u002Fschedules\u002Frun\u003C\u002Fdiv>\"):::domain\n\n    Start -->|Content Only| ScenA\n    Start -->|Code Changes| ScenB\n    ScenB --> BCode\n    BCode --> Sync\n    ScenA --> Sync\n    Sync --> Stage\n    Stage --> Promote\n    Promote --> Ingest\n",[438,2079],{},[368,2081,2083],{"id":2082},"step-1-determine-modification-type-content-only-vs-code-changes","Step 1: Determine Modification Type (Content-Only vs Code Changes)",[490,2085,2087],{"id":2086},"scenario-a-content-only-modification-zero-downtime-no-backend-redeploy","Scenario A: Content-Only Modification (Zero-Downtime, No Backend Redeploy)",[359,2089,2090],{},"If you are refining prompt instructions, improving persona prompts, tuning few-shot examples, or reducing hallucinations:",[373,2092,2093,2104,2110],{},[376,2094,2095,2096,2098,2099,627,2101,2103],{},"You do ",[379,2097,476],{}," need to touch ",[390,2100,460],{},[390,2102,464],{}," code immediately.",[376,2105,2106,2107,2109],{},"Go directly to ",[390,2108,392],{}," and edit the markdown prompt file.",[376,2111,1730,2112,430],{},[390,2113,392],{},[490,2115,2117],{"id":2116},"scenario-b-modification-with-backend-code-changes","Scenario B: Modification with Backend Code Changes",[359,2119,2120,2121,2124],{},"If your prompt change involves adding\u002Fremoving StringTemplate variables (e.g. ",[390,2122,2123],{},"\u003CnewVariable>","), altering input\u002Foutput JSON DTOs, or changing tool calls:",[373,2126,2127,2138,2145],{},[376,2128,2129,2130,2132,2133,627,2135,2137],{},"Update the fallback ",[390,2131,487],{}," file in ",[390,2134,460],{},[390,2136,464],{}," and modify the corresponding Java classes.",[376,2139,1730,2140,461,2142,2144],{},[390,2141,460],{},[390,2143,464],{}," and obtain review approval.",[376,2146,2147,2148,2150,2151,430],{},"Update the prompt file in ",[390,2149,392],{}," to match the new variable schema and open a matching PR in ",[390,2152,392],{},[438,2154],{},[368,2156,2158,2159,676,2161,2163],{"id":2157},"step-2-merge-to-main-in-esp-prompts-staging-sync","Step 2: Merge to ",[390,2160,1757],{},[390,2162,392],{}," (Staging Sync)",[359,2165,2166,2167,2169,2170,2172,2173,2176],{},"When your ",[390,2168,392],{}," PR merges to ",[390,2171,1757],{},", the ",[390,2174,2175],{},"sync-prompts-staging.yml"," workflow triggers automatically:",[505,2178,2179,2190,2198],{},[376,2180,2181,2182,2185,2186,2189],{},"Langfuse creates a ",[379,2183,2184],{},"new version"," (e.g. ",[390,2187,2188],{},"v3",") with your updated prompt.",[376,2191,2192,2193,2197],{},"The ",[379,2194,2195],{},[390,2196,410],{}," label moves to this new version.",[376,2199,2192,2200,2204,2205,525],{},[379,2201,2202],{},[390,2203,406],{}," label remains untouched on the existing live version (e.g. ",[390,2206,2207],{},"v2",[549,2209,2212],{"className":2210,"code":2211,"language":554},[552],"Before Sync:   staging -> v2 (live)      production -> v2 (live)\nAfter Sync:    staging -> v3 (updated)   production -> v2 (live)\n",[390,2213,2211],{"__ignoreMap":555},[438,2215],{},[368,2217,2219],{"id":2218},"step-3-verify-on-staging","Step 3: Verify on Staging",[373,2221,2222,2229],{},[376,2223,2224,2225,2228],{},"On the Staging environment (",[390,2226,2227],{},"ESP_LANGFUSE_PROMPTS_LABEL=staging","), execute the modified workflow.",[376,2230,2231,2232,2236,2237],{},"Check the ",[384,2233,2235],{"href":402,"rel":2234},[388],"Langfuse Tracing dashboard"," to verify:\n",[505,2238,2239,2247],{},[376,2240,2241,2242,2244,2245,525],{},"The trace links to the new ",[390,2243,410],{}," version number (e.g. ",[390,2246,2188],{},[376,2248,2249],{},"The LLM response meets expectations and adheres to formatting.",[438,2251],{},[368,2253,2255],{"id":2254},"step-4-promote-prompt-to-production","Step 4: Promote Prompt to Production",[373,2257,2258,2267,2275],{},[376,2259,1989,2260,676,2262,1868,2264,430],{},[379,2261,1992],{},[390,2263,392],{},[384,2265,1997],{"href":1995,"rel":2266},[388],[376,2268,2269,2270,2004,2272,2274],{},"Enter the specific prompt name in the ",[390,2271,2003],{},[390,2273,2007],{},") to promote only the targeted prompt.",[376,2276,2277,2278,1826,2281],{},"Click ",[379,2279,2280],{},"Run workflow",[505,2282,2283,2290,2298],{},[376,2284,2192,2285,2289],{},[379,2286,2287],{},[390,2288,2052],{}," job prints a dry-run diff of the versions that will move.",[376,2291,2292,2293,2297],{},"The workflow pauses at the ",[379,2294,2295],{},[390,2296,406],{}," environment review gate.",[376,2299,2300,2301,430],{},"Once approved, the job copies the staging version and labels it ",[379,2302,2303],{},[390,2304,406],{},[549,2306,2309],{"className":2307,"code":2308,"language":554},[552],"After Promotion:   staging -> v3             production -> v4 (copy of v3)\n",[390,2310,2308],{"__ignoreMap":555},[467,2312,2313,2316,2317,2321,2322,2324],{"icon":567},[379,2314,2315],{},"Targeting the Verified Version:"," Promotion does not select untracked or raw drafts; it targets the specific version currently tagged with ",[379,2318,2319],{},[390,2320,410],{},", allowing you to inspect the version diff during the ",[390,2323,2052],{}," step prior to approval.",[438,2326],{},[368,2328,2330],{"id":2329},"step-5-ingest-prompt-updates-automatic-vs-instant-refresh","Step 5: Ingest Prompt Updates (Automatic vs Instant Refresh)",[359,2332,2333],{},"After promoting a prompt in Langfuse, backend services pick up the change without restarting:",[373,2335,2336,2346],{},[376,2337,2338,2341,2342,2345],{},[379,2339,2340],{},"Automatic Quartz Refresh:"," The backend background job runs every ",[379,2343,2344],{},"20 minutes"," and automatically fetches updated prompt versions.",[376,2347,2348,2351],{},[379,2349,2350],{},"Instant Manual Trigger:"," If you need the change to take effect immediately without waiting for the 20-minute timer, trigger the prompt refresh Quartz job via the API endpoint:",[549,2353,2357],{"className":2354,"code":2355,"language":2356,"meta":555,"style":555},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","curl -X PATCH \"https:\u002F\u002Fplatform.esprofiler.com\u002Fapi\u002Fv1\u002Fschedules\u002Frun\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -H \"Authorization: Bearer \u003CAPI_OR_SSO_TOKEN>\" \\\n  -d '{\n    \"jobName\": \"langfusePromptRefreshJob\",\n    \"groupName\": \"DEFAULT\"\n  }'\n","bash",[390,2358,2359,2380,2394,2407,2418,2423,2428],{"__ignoreMap":555},[697,2360,2361,2364,2367,2370,2372,2375,2377],{"class":699,"line":700},[697,2362,2363],{"class":720},"curl",[697,2365,2366],{"class":759}," -X",[697,2368,2369],{"class":759}," PATCH",[697,2371,756],{"class":703},[697,2373,2374],{"class":759},"https:\u002F\u002Fplatform.esprofiler.com\u002Fapi\u002Fv1\u002Fschedules\u002Frun",[697,2376,763],{"class":703},[697,2378,2379],{"class":749}," \\\n",[697,2381,2382,2385,2387,2390,2392],{"class":699,"line":711},[697,2383,2384],{"class":759},"  -H",[697,2386,756],{"class":703},[697,2388,2389],{"class":759},"Content-Type: application\u002Fjson",[697,2391,763],{"class":703},[697,2393,2379],{"class":749},[697,2395,2396,2398,2400,2403,2405],{"class":699,"line":727},[697,2397,2384],{"class":759},[697,2399,756],{"class":703},[697,2401,2402],{"class":759},"Authorization: Bearer \u003CAPI_OR_SSO_TOKEN>",[697,2404,763],{"class":703},[697,2406,2379],{"class":749},[697,2408,2409,2412,2415],{"class":699,"line":734},[697,2410,2411],{"class":759},"  -d",[697,2413,2414],{"class":703}," '",[697,2416,2417],{"class":759},"{\n",[697,2419,2420],{"class":699,"line":769},[697,2421,2422],{"class":759},"    \"jobName\": \"langfusePromptRefreshJob\",\n",[697,2424,2425],{"class":699,"line":774},[697,2426,2427],{"class":759},"    \"groupName\": \"DEFAULT\"\n",[697,2429,2430,2433],{"class":699,"line":783},[697,2431,2432],{"class":759},"  }",[697,2434,2435],{"class":703},"'\n",[467,2437,2439,2442,2443,2445],{"icon":2438},"i-lucide-check-circle",[379,2440,2441],{},"Zero-Downtime Live Update:"," For content-only changes (Scenario A), ",[390,2444,460],{}," updates its RAM and disk cache immediately upon running the schedule action. No container restart or deployment is required!",[438,2447],{},[354,2449,2451],{"id":2450},"quartz-scheduled-ingestion-manual-refresh-api","Quartz Scheduled Ingestion & Manual Refresh API",[368,2453,2455],{"id":2454},"quartz-background-job-configuration","Quartz Background Job Configuration",[359,2457,2458],{},"Backend services run a background Quartz job dedicated to refreshing dynamic prompts:",[2460,2461,2462,2478],"table",{},[2463,2464,2465],"thead",{},[2466,2467,2468,2472,2475],"tr",{},[2469,2470,2471],"th",{},"Attribute",[2469,2473,2474],{},"Value \u002F Default",[2469,2476,2477],{},"Description",[2479,2480,2481,2497,2512,2527,2545,2563,2578],"tbody",{},[2466,2482,2483,2489,2494],{},[2484,2485,2486],"td",{},[379,2487,2488],{},"Job Name",[2484,2490,2491],{},[390,2492,2493],{},"langfusePromptRefreshJob",[2484,2495,2496],{},"Identifier of the Quartz job bean.",[2466,2498,2499,2504,2509],{},[2484,2500,2501],{},[379,2502,2503],{},"Job Group",[2484,2505,2506],{},[390,2507,2508],{},"DEFAULT",[2484,2510,2511],{},"Quartz job group.",[2466,2513,2514,2519,2524],{},[2484,2515,2516],{},[379,2517,2518],{},"Trigger Name",[2484,2520,2521],{},[390,2522,2523],{},"Langfuse Prompt Refresh Trigger",[2484,2525,2526],{},"Quartz trigger bean name.",[2466,2528,2529,2534,2542],{},[2484,2530,2531],{},[379,2532,2533],{},"Startup Delay",[2484,2535,2536,624,2539,465],{},[390,2537,2538],{},"15 minutes",[390,2540,2541],{},"TimeUnit.MINUTES.toMillis(15)",[2484,2543,2544],{},"Initial delay after server boot before first periodic sweep.",[2466,2546,2547,2552,2560],{},[2484,2548,2549],{},[379,2550,2551],{},"Repeat Interval",[2484,2553,2554,624,2556,2559],{},[390,2555,2344],{},[390,2557,2558],{},"1200000"," ms)",[2484,2561,2562],{},"Frequency of automatic prompt refresh sweeps.",[2466,2564,2565,2570,2575],{},[2484,2566,2567],{},[379,2568,2569],{},"Configuration Property",[2484,2571,2572],{},[390,2573,2574],{},"esp.langfuse.prompts.refresh-interval-ms",[2484,2576,2577],{},"Config property to customize the repeat interval.",[2466,2579,2580,2585,2590],{},[2484,2581,2582],{},[379,2583,2584],{},"Environment Variable",[2484,2586,2587],{},[390,2588,2589],{},"ESP_LANGFUSE_PROMPTS_REFRESH_INTERVAL_MS",[2484,2591,2592],{},"Override via container environment variable.",[368,2594,2596],{"id":2595},"triggering-manual-prompt-refresh-via-api","Triggering Manual Prompt Refresh via API",[359,2598,2599,2600,2602],{},"You can trigger ",[390,2601,2493],{}," at any time using the Schedule Management API:",[505,2604,2605,2614,2622,2640],{},[376,2606,2607,2610,2611],{},[379,2608,2609],{},"Endpoint:"," ",[390,2612,2613],{},"PATCH \u002Fapi\u002Fv1\u002Fschedules\u002Frun",[376,2615,2616,2610,2619],{},[379,2617,2618],{},"Controller:",[390,2620,2621],{},"ScheduleController.admScheduleRunAction",[376,2623,2624,2627,2628,2631,2632,624,2637,465],{},[379,2625,2626],{},"Swagger UI:"," Accessible at ",[390,2629,2630],{},"\u002Fapi\u002Fv1\u002Fdocs\u002Fui"," under tag ",[379,2633,2634],{},[390,2635,2636],{},"Z1 - Schedule Management",[390,2638,2639],{},"Z2.02 -- admScheduleRunAction",[376,2641,2642,2645,2646,2649,2650,430],{},[379,2643,2644],{},"Security:"," Requires ",[390,2647,2648],{},"ESP-SSO"," authentication or ",[390,2651,2652],{},"X-API-KEY",[490,2654,2656],{"id":2655},"request-example-json","Request Example (JSON)",[549,2658,2662],{"className":2659,"code":2660,"language":2661,"meta":555,"style":555},"language-http shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","PATCH \u002Fapi\u002Fv1\u002Fschedules\u002Frun HTTP\u002F1.1\nHost: platform.esprofiler.com\nContent-Type: application\u002Fjson\nAuthorization: Bearer \u003CAUTH_TOKEN>\n\n{\n  \"jobName\": \"langfusePromptRefreshJob\",\n  \"groupName\": \"DEFAULT\"\n}\n","http",[390,2663,2664,2669,2674,2679,2684,2688,2692,2697,2702],{"__ignoreMap":555},[697,2665,2666],{"class":699,"line":700},[697,2667,2668],{},"PATCH \u002Fapi\u002Fv1\u002Fschedules\u002Frun HTTP\u002F1.1\n",[697,2670,2671],{"class":699,"line":711},[697,2672,2673],{},"Host: platform.esprofiler.com\n",[697,2675,2676],{"class":699,"line":727},[697,2677,2678],{},"Content-Type: application\u002Fjson\n",[697,2680,2681],{"class":699,"line":734},[697,2682,2683],{},"Authorization: Bearer \u003CAUTH_TOKEN>\n",[697,2685,2686],{"class":699,"line":769},[697,2687,731],{"emptyLinePlaceholder":730},[697,2689,2690],{"class":699,"line":774},[697,2691,2417],{},[697,2693,2694],{"class":699,"line":783},[697,2695,2696],{},"  \"jobName\": \"langfusePromptRefreshJob\",\n",[697,2698,2699],{"class":699,"line":799},[697,2700,2701],{},"  \"groupName\": \"DEFAULT\"\n",[697,2703,2704],{"class":699,"line":830},[697,2705,1096],{},[490,2707,2709],{"id":2708},"success-response","Success Response",[549,2711,2715],{"className":2712,"code":2713,"language":2714,"meta":555,"style":555},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  \"success\": true,\n  \"message\": \"Task run request processed!\"\n}\n","json",[390,2716,2717,2721,2736,2755],{"__ignoreMap":555},[697,2718,2719],{"class":699,"line":700},[697,2720,2417],{"class":703},[697,2722,2723,2726,2729,2731,2733],{"class":699,"line":711},[697,2724,2725],{"class":703},"  \"",[697,2727,2728],{"class":707},"success",[697,2730,763],{"class":703},[697,2732,1120],{"class":703},[697,2734,2735],{"class":703}," true,\n",[697,2737,2738,2740,2743,2745,2747,2749,2752],{"class":699,"line":727},[697,2739,2725],{"class":703},[697,2741,2742],{"class":707},"message",[697,2744,763],{"class":703},[697,2746,1120],{"class":703},[697,2748,756],{"class":703},[697,2750,2751],{"class":759},"Task run request processed!",[697,2753,2754],{"class":703},"\"\n",[697,2756,2757],{"class":699,"line":734},[697,2758,1096],{"class":703},[438,2760],{},[438,2762],{},[354,2764,2766],{"id":2765},"technical-reference-best-practices","Technical Reference & Best Practices",[368,2768,2770],{"id":2769},"environment-configuration-target-labels","Environment Configuration & Target Labels",[359,2772,2773,2774,2776,2777,642],{},"Backend services configure which prompt versions to fetch via the ",[390,2775,623],{}," environment variable (mapped to ",[390,2778,2779],{},"esp.langfuse.prompts.label",[2460,2781,2782,2797],{},[2463,2783,2784],{},[2466,2785,2786,2789,2794],{},[2469,2787,2788],{},"Environment",[2469,2790,2791,2792,465],{},"Configured Label (",[390,2793,623],{},[2469,2795,2796],{},"Behavior & Purpose",[2479,2798,2799,2827,2848],{},[2466,2800,2801,2809,2813],{},[2484,2802,2803],{},[379,2804,2805,2806,465],{},"Staging (",[390,2807,2808],{},"stage",[2484,2810,2811],{},[390,2812,410],{},[2484,2814,2815,2821,2822,676,2824,2826],{},[379,2816,2817,2818,2820],{},"Always reads ",[390,2819,410],{}," prompts."," Picks up the latest prompts merged into ",[390,2823,1757],{},[390,2825,392],{}," for verification before release.",[2466,2828,2829,2837,2841],{},[2484,2830,2831],{},[379,2832,2833,2834,465],{},"Production (",[390,2835,2836],{},"prod",[2484,2838,2839],{},[390,2840,406],{},[2484,2842,2843,2847],{},[379,2844,2817,2845,2820],{},[390,2846,406],{}," Strictly uses versions that have passed through the promotion review gate in GitHub Actions.",[2466,2849,2850,2859,2867],{},[2484,2851,2852],{},[379,2853,2854,2855,2858],{},"Development (",[390,2856,2857],{},"dev"," \u002F Local)",[2484,2860,2861,2610,2863],{},[390,2862,406],{},[2864,2865,2866],"em",{},"(default)",[2484,2868,2869,2874,2875,2877],{},[379,2870,2871,2872],{},"Defaults to ",[390,2873,406],{}," so local development mirrors live production behavior. Can be overridden to ",[390,2876,410],{}," in local properties or IDE run configurations to test upcoming prompts.",[549,2879,2881],{"className":1807,"code":2880,"language":1809,"meta":555,"style":555},"# Example: Switch local or test environment to read staging prompts\nESP_LANGFUSE_PROMPTS_LABEL=staging\n",[390,2882,2883,2888],{"__ignoreMap":555},[697,2884,2885],{"class":699,"line":700},[697,2886,2887],{},"# Example: Switch local or test environment to read staging prompts\n",[697,2889,2890],{"class":699,"line":711},[697,2891,1808],{},[438,2893],{},[368,2895,2897],{"id":2896},"disabling-langfuse-prompt-sync-during-local-testing","Disabling Langfuse Prompt Sync During Local Testing",[359,2899,2900],{},"When testing local prompt changes or debugging offline, you can completely disable remote Langfuse prompt synchronization:",[549,2902,2904],{"className":1807,"code":2903,"language":1809,"meta":555,"style":555},"# In application-local.properties or your IDE Environment Variables\nESP_LANGFUSE_PROMPTS_ENABLED=false\n# or in application.yml \u002F properties:\nesp.langfuse.prompts.enabled=false\n",[390,2905,2906,2911,2916,2921],{"__ignoreMap":555},[697,2907,2908],{"class":699,"line":700},[697,2909,2910],{},"# In application-local.properties or your IDE Environment Variables\n",[697,2912,2913],{"class":699,"line":711},[697,2914,2915],{},"ESP_LANGFUSE_PROMPTS_ENABLED=false\n",[697,2917,2918],{"class":699,"line":727},[697,2919,2920],{},"# or in application.yml \u002F properties:\n",[697,2922,2923],{"class":699,"line":734},[697,2924,2925],{},"esp.langfuse.prompts.enabled=false\n",[490,2927,2929],{"id":2928},"what-happens-when-prompt-sync-is-disabled","What happens when prompt sync is disabled?",[373,2931,2932,2940,2952,2958],{},[376,2933,2934,2610,2937,2939],{},[379,2935,2936],{},"Zero Remote Calls:",[390,2938,483],{}," completely skips remote HTTP requests to Langfuse.",[376,2941,2942,2945,2946,2948,2949,2951],{},[379,2943,2944],{},"Direct Classpath Fallback:"," Services immediately use your local ",[390,2947,487],{}," template files from ",[390,2950,513],{}," on every invocation.",[376,2953,2954,2957],{},[379,2955,2956],{},"Bypasses Cache:"," Disk cache reads\u002Fwrites and Quartz periodic refresh sweeps are bypassed.",[376,2959,2960,2963,2964,2966],{},[379,2961,2962],{},"Instant Iteration:"," You can modify your local ",[390,2965,487],{}," file and test changes immediately without any remote sync or cache invalidation.",[438,2968],{},[368,2970,2972],{"id":2971},"langfuse-labels-tags-reference","Langfuse Labels & Tags Reference",[490,2974,2976],{"id":2975},"_1-version-labels-prompt-routing","1. Version Labels (Prompt Routing)",[2460,2978,2979,2994],{},[2463,2980,2981],{},[2466,2982,2983,2986,2989,2992],{},[2469,2984,2985],{},"Label",[2469,2987,2988],{},"Managed By",[2469,2990,2991],{},"Environment Target",[2469,2993,2477],{},[2479,2995,2996,3019,3042],{},[2466,2997,2998,3004,3008,3012],{},[2484,2999,3000],{},[379,3001,3002],{},[390,3003,410],{},[2484,3005,3006],{},[390,3007,2175],{},[2484,3009,2805,3010,465],{},[390,3011,2808],{},[2484,3013,3014,3015,676,3017,430],{},"Automatically assigned when a PR merges into ",[390,3016,1757],{},[390,3018,392],{},[2466,3020,3021,3027,3032,3039],{},[2484,3022,3023],{},[379,3024,3025],{},[390,3026,406],{},[2484,3028,3029],{},[390,3030,3031],{},"promote-prompts.yml",[2484,3033,2833,3034,3036,3037,465],{},[390,3035,2836],{},"), Dev (",[390,3038,2857],{},[2484,3040,3041],{},"Assigned when a prompt is approved and promoted via the GitHub Action.",[2466,3043,3044,3051,3054,3059],{},[2484,3045,3046],{},[379,3047,3048],{},[390,3049,3050],{},"latest",[2484,3052,3053],{},"Langfuse Internal",[2484,3055,3056],{},[2864,3057,3058],{},"None",[2484,3060,3061,3062],{},"Internal Langfuse pointer to the newest draft. ",[379,3063,3064],{},"DO NOT USE in application code.",[490,3066,3068],{"id":3067},"_2-metadata-tags-filtering-categorization","2. Metadata Tags (Filtering & Categorization)",[359,3070,3071],{},"Prompts in Langfuse are automatically tagged during CI sync to allow easy filtering:",[505,3073,3074,3095],{},[376,3075,3076,3079],{},[379,3077,3078],{},"Service Tags:",[505,3080,3081,3088],{},[376,3082,3083,3085,3086,430],{},[390,3084,1787],{}," — Prompts consumed by ",[390,3087,460],{},[376,3089,3090,3085,3093,430],{},[390,3091,3092],{},"service-cps",[390,3094,464],{},[376,3096,3097,3100],{},[379,3098,3099],{},"Domain \u002F Subsystem Tags:",[505,3101,3102,3107,3113,3119],{},[376,3103,3104,3106],{},[390,3105,1790],{}," — Finding and Signal generation, emergence, and evaluation agents.",[376,3108,3109,3112],{},[390,3110,3111],{},"domain-copilot"," — Interactive chat assistants, skills, and conversation namers.",[376,3114,3115,3118],{},[390,3116,3117],{},"domain-tasks"," — Deep research, report generation, and background analyst workflows.",[376,3120,3121,3124],{},[390,3122,3123],{},"domain-changelog"," — Changelog and revision comparison agents.",[438,3126],{},[368,3128,3130],{"id":3129},"environment-variables-summary","Environment Variables Summary",[2460,3132,3133,3148],{},[2463,3134,3135],{},[2466,3136,3137,3140,3143,3146],{},[2469,3138,3139],{},"Variable",[2469,3141,3142],{},"Property",[2469,3144,3145],{},"Default",[2469,3147,2477],{},[2479,3149,3150,3174,3197,3216,3234,3256],{},[2466,3151,3152,3157,3162,3167],{},[2484,3153,3154],{},[390,3155,3156],{},"ESP_LANGFUSE_PROMPTS_ENABLED",[2484,3158,3159],{},[390,3160,3161],{},"esp.langfuse.prompts.enabled",[2484,3163,3164],{},[390,3165,3166],{},"true",[2484,3168,3169,3170,3173],{},"Enable\u002Fdisable remote Langfuse prompt fetching. Set ",[390,3171,3172],{},"false"," for offline local testing.",[2466,3175,3176,3180,3184,3188],{},[2484,3177,3178],{},[390,3179,623],{},[2484,3181,3182],{},[390,3183,2779],{},[2484,3185,3186],{},[390,3187,406],{},[2484,3189,3190,3191,3193,3194,3196],{},"Target prompt label (",[390,3192,406],{}," in Prod\u002FDev, ",[390,3195,410],{}," in Staging).",[2466,3198,3199,3204,3208,3213],{},[2484,3200,3201],{},[390,3202,3203],{},"ESP_LANGFUSE_PROMPTS_CACHE_DIR",[2484,3205,3206],{},[390,3207,646],{},[2484,3209,3210],{},[390,3211,3212],{},"resources\u002Fprompts",[2484,3214,3215],{},"Local container directory for caching fetched prompt templates on disk.",[2466,3217,3218,3222,3226,3231],{},[2484,3219,3220],{},[390,3221,2589],{},[2484,3223,3224],{},[390,3225,2574],{},[2484,3227,3228,3230],{},[390,3229,2558],{}," (20m)",[2484,3232,3233],{},"Interval in ms for the periodic Quartz background prompt refresh job.",[2466,3235,3236,3240,3245,3250],{},[2484,3237,3238],{},[390,3239,619],{},[2484,3241,3242],{},[390,3243,3244],{},"esp.llm.observation.otlp.endpoint",[2484,3246,3247],{},[390,3248,3249],{},"\"\"",[2484,3251,3252,3253,525],{},"Langfuse OTLP endpoint (e.g. ",[390,3254,3255],{},"https:\u002F\u002Fesplf.esprofiler.com\u002Fapi\u002Fpublic\u002Fotel\u002Fv1\u002Ftraces",[2466,3257,3258,3263,3268,3272],{},[2484,3259,3260],{},[390,3261,3262],{},"ESP_LLM_OBSERVATION_OTLP_AUTH",[2484,3264,3265],{},[390,3266,3267],{},"esp.llm.observation.otlp.auth",[2484,3269,3270],{},[390,3271,3249],{},[2484,3273,3274,3275,525],{},"Base64-encoded Langfuse public and secret key (",[390,3276,3277],{},"Basic \u003Cauth>",[438,3279],{},[368,3281,3283,3284,465],{"id":3282},"caching-architecture-in-spring-boot-langfusepromptservice","Caching Architecture in Spring Boot (",[390,3285,483],{},[359,3287,3288,3289,3291],{},"To eliminate latency and avoid external API limits, ",[390,3290,483],{}," implements a resilient multi-tier cache:",[373,3293,3294,3302,3312,3325],{},[376,3295,3296,3301],{},[379,3297,605,3298,642],{},[390,3299,3300],{},"ConcurrentHashMap"," Instant prompt lookup during request processing.",[376,3303,3304,3311],{},[379,3305,634,3306,575,3308,642],{},[390,3307,637],{},[390,3309,3310],{},"\u003Cprompt>.version"," Persisted locally across container restarts.",[376,3313,3314,3317,3318,3321,3322,3324],{},[379,3315,3316],{},"Startup Ingestion:"," During ",[390,3319,3320],{},"ApplicationReadyEvent",", the service performs a remote ingestion sweep of all registered ",[390,3323,687],{}," beans.",[376,3326,3327,3330,3331,3333],{},[379,3328,3329],{},"Periodic Refresh:"," Scheduled background Quartz job (",[390,3332,2493],{},") periodically sweeps and reloads prompt updates from Langfuse every 20 minutes.",[438,3335],{},[368,3337,3339],{"id":3338},"troubleshooting-common-issues","Troubleshooting Common Issues",[505,3341,3342,3370,3391],{},[376,3343,3344,3347],{},[379,3345,3346],{},"Prompt returns fallback content on startup:",[505,3348,3349,3357,3367],{},[376,3350,3351,3352,3354,3355,525],{},"Check that ",[390,3353,619],{}," is configured correctly (e.g. ",[390,3356,3255],{},[376,3358,3359,3360,3362,3363,627,3365,525],{},"Verify that ",[390,3361,623],{}," matches the label present in Langfuse (",[390,3364,410],{},[390,3366,406],{},[376,3368,3369],{},"Check that the prompt name passed in Java matches the prompt name in Langfuse exactly.",[376,3371,3372,3375],{},[379,3373,3374],{},"HTTP 403 \u002F Cloudflare WAF block during sync:",[505,3376,3377,3380],{},[376,3378,3379],{},"Some prompts contain HTML\u002FJavaScript snippets. Cloudflare WAF rules may block POST requests containing script tags.",[376,3381,3382,3383,3386,3387,3390],{},"Ensure the Cloudflare WAF skip rule is configured for ",[390,3384,3385],{},"\u002Fapi\u002Fpublic\u002F"," or that ",[390,3388,3389],{},"LANGFUSE_EXTRA_HEADERS"," contains the appropriate bypass secret.",[376,3392,3393,3396],{},[379,3394,3395],{},"Span not linked in Langfuse Traces:",[505,3397,3398],{},[376,3399,3400,3401,3404,3405,3407,3408,430],{},"Ensure ",[390,3402,3403],{},"new LangfusePromptObservationAdvisor(PROMPT_NAME, langfusePromptService)"," is registered in ",[390,3406,1031],{}," on the ",[390,3409,683],{},[3411,3412,3413],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}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 .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":555,"searchDepth":711,"depth":711,"links":3415},[3416,3419,3429,3438,3442],{"id":356,"depth":711,"text":357,"children":3417},[3418],{"id":370,"depth":727,"text":371},{"id":442,"depth":711,"text":443,"children":3420},[3421,3422,3424,3426,3427,3428],{"id":449,"depth":727,"text":450},{"id":456,"depth":727,"text":3423},"Step 1: Backend Implementation (platform-api \u002F api-cps)",{"id":1660,"depth":727,"text":3425},"Step 2: Create Prompt in esp-prompts Repository",{"id":1795,"depth":727,"text":1796},{"id":1849,"depth":727,"text":1850},{"id":1971,"depth":727,"text":1972},{"id":2061,"depth":711,"text":2062,"children":3430},[3431,3432,3433,3435,3436,3437],{"id":2074,"depth":727,"text":450},{"id":2082,"depth":727,"text":2083},{"id":2157,"depth":727,"text":3434},"Step 2: Merge to main in esp-prompts (Staging Sync)",{"id":2218,"depth":727,"text":2219},{"id":2254,"depth":727,"text":2255},{"id":2329,"depth":727,"text":2330},{"id":2450,"depth":711,"text":2451,"children":3439},[3440,3441],{"id":2454,"depth":727,"text":2455},{"id":2595,"depth":727,"text":2596},{"id":2765,"depth":711,"text":2766,"children":3443},[3444,3445,3446,3447,3448,3450],{"id":2769,"depth":727,"text":2770},{"id":2896,"depth":727,"text":2897},{"id":2971,"depth":727,"text":2972},{"id":3129,"depth":727,"text":3130},{"id":3282,"depth":727,"text":3449},"Caching Architecture in Spring Boot (LangfusePromptService)",{"id":3338,"depth":727,"text":3339},"Step-by-step guide for backend developers on adding new prompts, modifying existing prompts across platform-api and api-cps, integrating with Langfuse and esp-prompts, Quartz reload scheduling, and coordinating Data\u002FAI team benchmarking.","md",null,{},{"title":135,"description":3451},"4bX8TIzh7cvLEdIGO9MhbsP3gFrAGshWkR4thV3vRGk",[3458,3460],{"title":131,"path":132,"stem":133,"description":3459,"children":-1},"This guide provides a set of guidelines for designing and implementing APIs in the back-end of ESProfiler",{"title":144,"path":145,"stem":146,"description":555,"children":-1},1789726612871]