2025-10-22 21:13:54 +00:00
<!DOCTYPE html>
2026-01-24 20:01:20 +00:00
< html :class = "{ 'dark' : darkMode === true }" data-content_root = "../" lang = "en" x-data = "{ darkMode: $persist(window.matchMedia('(prefers-color-scheme: dark)').matches), activeSection: ''}" >
2025-10-22 21:13:54 +00:00
< head >
2026-01-24 20:01:20 +00:00
< script >
(function () {
// Set initial color scheme
if ((localStorage.getItem("_x_darkMode") === "true") || (window.matchMedia("(prefers-color-scheme: dark)").matches)) {
document.documentElement.classList.add("dark");
}
// Watch for media preference changes
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", (event) => {
localStorage.setItem("_x_darkMode", event.matches);
document.documentElement.classList.toggle("dark", event.matches);
});
})();
< / script >
2025-10-22 21:13:54 +00:00
< meta content = "width=device-width, initial-scale=1.0" name = "viewport" / >
< meta charset = "utf-8" / >
2026-01-24 20:01:20 +00:00
< meta content = "#ffffff" media = "(prefers-color-scheme: light)" name = "theme-color" / >
< meta content = "#030711" media = "(prefers-color-scheme: dark)" name = "theme-color" / >
2025-10-22 21:13:54 +00:00
< meta content = "width=device-width, initial-scale=1" name = "viewport" / >
2026-04-18 04:16:45 +00:00
< title > Deployment | Plano Docs v0.4.20< / title >
< meta content = "Deployment | Plano Docs v0.4.20" property = "og:title" / >
< meta content = "Deployment | Plano Docs v0.4.20" name = "twitter:title" / >
2026-01-24 20:01:20 +00:00
< link href = "../_static/pygments.css?v=73db4dac" rel = "stylesheet" type = "text/css" / >
2026-04-16 20:17:24 +00:00
< link href = "../_static/theme.css?v=979577e3" rel = "stylesheet" type = "text/css" / >
2025-10-22 21:13:54 +00:00
< link href = "../_static/sphinx-design.min.css?v=95c83b7e" rel = "stylesheet" type = "text/css" / >
2025-12-24 01:15:19 +00:00
< link href = "../_static/css/custom.css?v=2929376a" rel = "stylesheet" type = "text/css" / >
2026-04-16 20:17:24 +00:00
< link href = "../_static/awesome-sphinx-design.css?v=b1d4564d" rel = "stylesheet" type = "text/css" / >
2025-10-22 21:13:54 +00:00
< link href = "./docs/resources/deployment.html" rel = "canonical" / >
< link href = "../_static/favicon.ico" rel = "icon" / >
< link href = "../search.html" rel = "search" title = "Search" / >
< link href = "configuration_reference.html" rel = "next" title = "Configuration Reference" / >
2025-12-24 01:15:19 +00:00
< link href = "tech_overview/threading_model.html" rel = "prev" title = "Threading Model" / >
2025-10-22 21:13:54 +00:00
< / head >
< body :class = "{ 'overflow-hidden': showSidebar }" class = "min-h-screen font-sans antialiased bg-background text-foreground" x-data = "{ showSidebar: false, showScrollTop: false }" >
< div @ click . self = "showSidebar = false" class = "fixed inset-0 z-50 overflow-hidden bg-background/80 backdrop-blur-sm md:hidden" x-cloak = "" x-show = "showSidebar" > < / div > < div class = "relative flex flex-col min-h-screen" id = "page" > < a class = "absolute top-0 left-0 z-[100] block bg-background p-4 text-xl transition -translate-x-full opacity-0 focus:translate-x-0 focus:opacity-100" href = "#content" >
Skip to content
2026-01-24 20:01:20 +00:00
< / a > < header class = "sticky top-0 z-40 w-full border-b shadow-xs border-border bg-background/90 backdrop-blur" > < div class = "container flex items-center h-14" >
2025-10-22 21:13:54 +00:00
< div class = "hidden mr-4 md:flex" >
< a class = "flex items-center mr-6" href = "../index.html" >
2026-04-18 04:16:45 +00:00
< img alt = "Logo" class = "mr-2 dark:invert" height = "24" src = "../_static/favicon.ico" width = "24" / > < span class = "hidden font-bold sm:inline-block text-clip whitespace-nowrap" > Plano Docs v0.4.20< / span >
2025-10-22 21:13:54 +00:00
< / a > < / div > < button @ click = "showSidebar = true" class = "inline-flex items-center justify-center h-10 px-0 py-2 mr-2 text-base font-medium transition-colors rounded-md hover:text-accent-foreground hover:bg-transparent md:hidden" type = "button" >
< svg aria-hidden = "true" fill = "currentColor" height = "24" viewbox = "0 96 960 960" width = "24" xmlns = "http://www.w3.org/2000/svg" >
< path d = "M152.587 825.087q-19.152 0-32.326-13.174t-13.174-32.326q0-19.152 13.174-32.326t32.326-13.174h440q19.152 0 32.326 13.174t13.174 32.326q0 19.152-13.174 32.326t-32.326 13.174h-440Zm0-203.587q-19.152 0-32.326-13.174T107.087 576q0-19.152 13.174-32.326t32.326-13.174h320q19.152 0 32.326 13.174T518.087 576q0 19.152-13.174 32.326T472.587 621.5h-320Zm0-203.587q-19.152 0-32.326-13.174t-13.174-32.326q0-19.152 13.174-32.326t32.326-13.174h440q19.152 0 32.326 13.174t13.174 32.326q0 19.152-13.174 32.326t-32.326 13.174h-440ZM708.913 576l112.174 112.174q12.674 12.674 12.674 31.826t-12.674 31.826Q808.413 764.5 789.261 764.5t-31.826-12.674l-144-144Q600 594.391 600 576t13.435-31.826l144-144q12.674-12.674 31.826-12.674t31.826 12.674q12.674 12.674 12.674 31.826t-12.674 31.826L708.913 576Z" > < / path >
< / svg >
< span class = "sr-only" > Toggle navigation menu< / span >
< / button >
2026-01-24 20:01:20 +00:00
< div class = "flex items-center justify-between flex-1 gap-2 sm:gap-4 md:justify-end" >
2025-10-22 21:13:54 +00:00
< div class = "flex-1 w-full md:w-auto md:flex-none" > < form @ keydown . k . window . meta = "$refs.search.focus()" action = "../search.html" class = "relative flex items-center group" id = "searchbox" method = "get" >
< input aria-label = "Search the docs" class = "inline-flex items-center font-medium transition-colors bg-transparent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 ring-offset-background border border-input hover:bg-accent focus:bg-accent hover:text-accent-foreground focus:text-accent-foreground hover:placeholder-accent-foreground py-2 px-4 relative h-9 w-full justify-start rounded-[0.5rem] text-sm text-muted-foreground sm:pr-12 md:w-40 lg:w-64" id = "search-input" name = "q" placeholder = "Search ..." type = "search" x-ref = "search" / >
< kbd class = "pointer-events-none absolute right-1.5 top-2 hidden h-5 select-none text-muted-foreground items-center gap-1 rounded border border-border bg-muted px-1.5 font-mono text-[10px] font-medium opacity-100 sm:flex group-hover:bg-accent group-hover:text-accent-foreground" >
< span class = "text-xs" > ⌘< / span >
K
< / kbd >
< / form >
< / div >
2026-01-24 20:01:20 +00:00
< nav class = "flex items-center gap-1" >
2025-12-24 01:15:19 +00:00
< a href = "https://github.com/katanemo/plano" rel = "noopener nofollow" title = "Visit repository on GitHub" >
2026-01-24 20:01:20 +00:00
< div class = "inline-flex items-center justify-center px-0 text-sm font-medium transition-colors rounded-md hover:bg-accent hover:text-accent-foreground h-9 w-9" >
2025-10-22 21:13:54 +00:00
< svg fill = "currentColor" height = "26px" style = "margin-top:-2px;display:inline" viewbox = "0 0 45 44" xmlns = "http://www.w3.org/2000/svg" > < path clip-rule = "evenodd" d = "M22.477.927C10.485.927.76 10.65.76 22.647c0 9.596 6.223 17.736 14.853 20.608 1.087.2 1.483-.47 1.483-1.047 0-.516-.019-1.881-.03-3.693-6.04 1.312-7.315-2.912-7.315-2.912-.988-2.51-2.412-3.178-2.412-3.178-1.972-1.346.149-1.32.149-1.32 2.18.154 3.327 2.24 3.327 2.24 1.937 3.318 5.084 2.36 6.321 1.803.197-1.403.759-2.36 1.379-2.903-4.823-.548-9.894-2.412-9.894-10.734 0-2.37.847-4.31 2.236-5.828-.224-.55-.969-2.759.214-5.748 0 0 1.822-.584 5.972 2.226 1.732-.482 3.59-.722 5.437-.732 1.845.01 3.703.25 5.437.732 4.147-2.81 5.967-2.226 5.967-2.226 1.185 2.99.44 5.198.217 5.748 1.392 1.517 2.232 3.457 2.232 5.828 0 8.344-5.078 10.18-9.916 10.717.779.67 1.474 1.996 1.474 4.021 0 2.904-.027 5.247-.027 5.96 0 .58.392 1.256 1.493 1.044C37.981 40.375 44.2 32.24 44.2 22.647c0-11.996-9.726-21.72-21.722-21.72" fill = "currentColor" fill-rule = "evenodd" > < / path > < / svg >
< / div >
< / a >
2026-01-24 20:01:20 +00:00
< button @ click = "darkMode = !darkMode" class = "relative inline-flex items-center justify-center px-0 text-sm font-medium transition-colors rounded-md hover:bg-accent hover:text-accent-foreground h-9 w-9" title = "Toggle color scheme" type = "button" >
< svg class = "absolute transition-all scale-100 rotate-0 dark:-rotate-90 dark:scale-0" fill = "currentColor" height = "16" viewbox = "0 96 960 960" width = "16" xmlns = "http://www.w3.org/2000/svg" >
2025-10-22 21:13:54 +00:00
< path d = "M480 685q45.456 0 77.228-31.772Q589 621.456 589 576q0-45.456-31.772-77.228Q525.456 467 480 467q-45.456 0-77.228 31.772Q371 530.544 371 576q0 45.456 31.772 77.228Q434.544 685 480 685Zm0 91q-83 0-141.5-58.5T280 576q0-83 58.5-141.5T480 376q83 0 141.5 58.5T680 576q0 83-58.5 141.5T480 776ZM80 621.5q-19.152 0-32.326-13.174T34.5 576q0-19.152 13.174-32.326T80 530.5h80q19.152 0 32.326 13.174T205.5 576q0 19.152-13.174 32.326T160 621.5H80Zm720 0q-19.152 0-32.326-13.174T754.5 576q0-19.152 13.174-32.326T800 530.5h80q19.152 0 32.326 13.174T925.5 576q0 19.152-13.174 32.326T880 621.5h-80Zm-320-320q-19.152 0-32.326-13.174T434.5 256v-80q0-19.152 13.174-32.326T480 130.5q19.152 0 32.326 13.174T525.5 176v80q0 19.152-13.174 32.326T480 301.5Zm0 720q-19.152 0-32.326-13.17Q434.5 995.152 434.5 976v-80q0-19.152 13.174-32.326T480 850.5q19.152 0 32.326 13.174T525.5 896v80q0 19.152-13.174 32.33-13.174 13.17-32.326 13.17ZM222.174 382.065l-43-42Q165.5 327.391 166 308.239t13.174-33.065q13.435-13.674 32.587-13.674t32.065 13.674l42.239 43q12.674 13.435 12.555 31.706-.12 18.272-12.555 31.946-12.674 13.674-31.445 13.413-18.772-.261-32.446-13.174Zm494 494.761-42.239-43q-12.674-13.435-12.674-32.087t12.674-31.565Q686.609 756.5 705.38 757q18.772.5 32.446 13.174l43 41.761Q794.5 824.609 794 843.761t-13.174 33.065Q767.391 890.5 748.239 890.5t-32.065-13.674Zm-42-494.761Q660.5 369.391 661 350.62q.5-18.772 13.174-32.446l41.761-43Q728.609 261.5 747.761 262t33.065 13.174q13.674 13.435 13.674 32.587t-13.674 32.065l-43 42.239q-13.435 12.674-31.706 12.555-18.272-.12-31.946-12.555Zm-495 494.761Q165.5 863.391 165.5 844.239t13.674-32.065l43-42.239q13.435-12.674 32.087-12.674t31.565 12.674Q299.5 782.609 299 801.38q-.5 18.772-13.174 32.446l-41.761 43Q231.391 890.5 212.239 890t-33.065-13.174ZM480 576Z" > < / path >
< / svg >
2026-01-24 20:01:20 +00:00
< svg class = "absolute transition-all scale-0 rotate-90 dark:rotate-0 dark:scale-100" fill = "currentColor" height = "16" viewbox = "0 96 960 960" width = "16" xmlns = "http://www.w3.org/2000/svg" >
2025-10-22 21:13:54 +00:00
< path d = "M480 936q-151 0-255.5-104.5T120 576q0-138 90-239.5T440 218q25-3 39 18t-1 44q-17 26-25.5 55t-8.5 61q0 90 63 153t153 63q31 0 61.5-9t54.5-25q21-14 43-1.5t19 39.5q-14 138-117.5 229T480 936Zm0-80q88 0 158-48.5T740 681q-20 5-40 8t-40 3q-123 0-209.5-86.5T364 396q0-20 3-40t8-40q-78 32-126.5 102T200 576q0 116 82 198t198 82Zm-10-270Z" > < / path >
< / svg >
< / button >
< / nav >
< / div >
< / div >
< / header >
2026-01-24 20:01:20 +00:00
< div class = "flex-1" > < div class = "container md:grid md:grid-cols-[220px_minmax(0,1fr)] md:gap-6 lg:grid-cols-[240px_minmax(0,1fr)] lg:gap-10" > < aside :aria-hidden = "!showSidebar" :class = "{ 'translate-x-0': showSidebar }" class = "fixed inset-y-0 left-0 md:top-14 z-50 md:z-30 bg-background md:bg-transparent transition-all duration-100 -translate-x-full md:translate-x-0 ml-0 p-6 md:p-0 md:-ml-2 md:h-[calc(100vh-3.5rem)] w-5/6 md:w-full overflow-y-auto border-r border-border md:sticky" id = "left-sidebar" >
< a class = "justify-start text-sm md:!hidden bg-background" href = "../index.html" >
2026-04-18 04:16:45 +00:00
< img alt = "Logo" class = "mr-2 dark:invert" height = "16" src = "../_static/favicon.ico" width = "16" / > < span class = "font-bold text-clip whitespace-nowrap" > Plano Docs v0.4.20< / span >
2025-10-22 21:13:54 +00:00
< / a >
2026-01-24 20:01:20 +00:00
< div class = "relative overflow-hidden md:overflow-auto my-4 md:my-0" >
2025-10-22 21:13:54 +00:00
< div class = "overflow-y-auto h-full w-full relative pr-6" >
2025-12-24 01:15:19 +00:00
< script async = "" src = "https://www.googletagmanager.com/gtag/js?id=G-EH2VW19FXE" > < / script >
2025-10-22 21:13:54 +00:00
< script >
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
2025-12-24 01:15:19 +00:00
gtag('config', 'G-EH2VW19FXE');
2025-10-22 21:13:54 +00:00
< / script >
< nav class = "table w-full min-w-full my-6 lg:my-8" >
< p class = "caption" role = "heading" > < span class = "caption-text" > Get Started< / span > < / p >
< ul >
< li class = "toctree-l1" > < a class = "reference internal" href = "../get_started/overview.html" > Overview< / a > < / li >
2025-12-24 01:15:19 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "../get_started/intro_to_plano.html" > Intro to Plano< / a > < / li >
2025-10-22 21:13:54 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "../get_started/quickstart.html" > Quickstart< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "../get_started/quickstart.html#next-steps" > Next Steps< / a > < / li >
< / ul >
< p class = "caption" role = "heading" > < span class = "caption-text" > Concepts< / span > < / p >
< ul >
2025-12-24 01:15:19 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "../concepts/listeners.html" > Listeners< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "../concepts/agents.html" > Agents< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "../concepts/filter_chain.html" > Filter Chains< / a > < / li >
2026-01-24 20:01:20 +00:00
< li class = "toctree-l1" x-data = "{ expanded: $el.classList.contains('current') ? true : false }" > < a :class = "{ 'expanded' : expanded }" @ click = "expanded = !expanded" class = "reference internal expandable" href = "../concepts/llm_providers/llm_providers.html" > Model (LLM) Providers< button @ click . prevent . stop = "expanded = !expanded" type = "button" x-cloak = "" > < span class = "sr-only" > < / span > < svg fill = "currentColor" height = "18px" stroke = "none" viewbox = "0 0 24 24" width = "18px" xmlns = "http://www.w3.org/2000/svg" > < path d = "M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z" > < / path > < / svg > < / button > < / a > < ul x-cloak = "" x-show = "expanded" >
2025-10-22 21:13:54 +00:00
< li class = "toctree-l2" > < a class = "reference internal" href = "../concepts/llm_providers/supported_providers.html" > Supported Providers & Configuration< / a > < / li >
< li class = "toctree-l2" > < a class = "reference internal" href = "../concepts/llm_providers/client_libraries.html" > Client Libraries< / a > < / li >
< li class = "toctree-l2" > < a class = "reference internal" href = "../concepts/llm_providers/model_aliases.html" > Model Aliases< / a > < / li >
< / ul >
< / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "../concepts/prompt_target.html" > Prompt Target< / a > < / li >
2026-01-07 19:21:18 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "../concepts/signals.html" > Signals™< / a > < / li >
2025-10-22 21:13:54 +00:00
< / ul >
< p class = "caption" role = "heading" > < span class = "caption-text" > Guides< / span > < / p >
< ul >
2025-12-24 01:15:19 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "../guides/orchestration.html" > Orchestration< / a > < / li >
2025-10-22 21:13:54 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "../guides/llm_router.html" > LLM Routing< / a > < / li >
2025-12-24 01:15:19 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "../guides/function_calling.html" > Function Calling< / a > < / li >
2026-01-24 20:01:20 +00:00
< li class = "toctree-l1" x-data = "{ expanded: $el.classList.contains('current') ? true : false }" > < a :class = "{ 'expanded' : expanded }" @ click = "expanded = !expanded" class = "reference internal expandable" href = "../guides/observability/observability.html" > Observability< button @ click . prevent . stop = "expanded = !expanded" type = "button" x-cloak = "" > < span class = "sr-only" > < / span > < svg fill = "currentColor" height = "18px" stroke = "none" viewbox = "0 0 24 24" width = "18px" xmlns = "http://www.w3.org/2000/svg" > < path d = "M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z" > < / path > < / svg > < / button > < / a > < ul x-cloak = "" x-show = "expanded" >
2025-10-22 21:13:54 +00:00
< li class = "toctree-l2" > < a class = "reference internal" href = "../guides/observability/tracing.html" > Tracing< / a > < / li >
< li class = "toctree-l2" > < a class = "reference internal" href = "../guides/observability/monitoring.html" > Monitoring< / a > < / li >
< li class = "toctree-l2" > < a class = "reference internal" href = "../guides/observability/access_logging.html" > Access Logging< / a > < / li >
< / ul >
< / li >
2025-12-24 01:15:19 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "../guides/prompt_guard.html" > Guardrails< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "../guides/state.html" > Conversational State< / a > < / li >
2025-10-22 21:13:54 +00:00
< / ul >
< p class = "caption" role = "heading" > < span class = "caption-text" > Resources< / span > < / p >
< ul class = "current" >
2026-01-24 20:01:20 +00:00
< li class = "toctree-l1" x-data = "{ expanded: $el.classList.contains('current') ? true : false }" > < a :class = "{ 'expanded' : expanded }" @ click = "expanded = !expanded" class = "reference internal expandable" href = "tech_overview/tech_overview.html" > Tech Overview< button @ click . prevent . stop = "expanded = !expanded" type = "button" x-cloak = "" > < span class = "sr-only" > < / span > < svg fill = "currentColor" height = "18px" stroke = "none" viewbox = "0 0 24 24" width = "18px" xmlns = "http://www.w3.org/2000/svg" > < path d = "M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z" > < / path > < / svg > < / button > < / a > < ul x-cloak = "" x-show = "expanded" >
2025-12-24 01:15:19 +00:00
< li class = "toctree-l2" > < a class = "reference internal" href = "tech_overview/request_lifecycle.html" > Request Lifecycle< / a > < / li >
< li class = "toctree-l2" > < a class = "reference internal" href = "tech_overview/model_serving.html" > Bright Staff< / a > < / li >
< li class = "toctree-l2" > < a class = "reference internal" href = "tech_overview/threading_model.html" > Threading Model< / a > < / li >
< / ul >
< / li >
2025-10-22 21:13:54 +00:00
< li class = "toctree-l1 current" > < a class = "current reference internal" href = "#" > Deployment< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "configuration_reference.html" > Configuration Reference< / a > < / li >
2026-02-25 03:18:07 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "cli_reference.html" > CLI Reference< / a > < / li >
2025-12-24 01:15:19 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "llms_txt.html" > llms.txt< / a > < / li >
2025-10-22 21:13:54 +00:00
< / ul >
< / nav >
< / div >
< / div >
< button @ click = "showSidebar = false" class = "absolute md:hidden right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100" type = "button" >
< svg class = "h-4 w-4" fill = "currentColor" height = "24" stroke = "none" viewbox = "0 96 960 960" width = "24" xmlns = "http://www.w3.org/2000/svg" >
< path d = "M480 632 284 828q-11 11-28 11t-28-11q-11-11-11-28t11-28l196-196-196-196q-11-11-11-28t11-28q11-11 28-11t28 11l196 196 196-196q11-11 28-11t28 11q11 11 11 28t-11 28L536 576l196 196q11 11 11 28t-11 28q-11 11-28 11t-28-11L480 632Z" > < / path >
< / svg >
< / button >
< / aside >
< main class = "relative py-6 lg:gap-10 lg:py-8 xl:grid xl:grid-cols-[1fr_300px]" >
< div class = "w-full min-w-0 mx-auto" >
< nav aria-label = "breadcrumbs" class = "flex items-center mb-4 space-x-1 text-sm text-muted-foreground" >
< a class = "overflow-hidden text-ellipsis whitespace-nowrap hover:text-foreground" href = "../index.html" >
2026-04-18 04:16:45 +00:00
< span class = "hidden md:inline" > Plano Docs v0.4.20< / span >
2025-10-22 21:13:54 +00:00
< svg aria-label = "Home" class = "md:hidden" fill = "currentColor" height = "18" stroke = "none" viewbox = "0 96 960 960" width = "18" xmlns = "http://www.w3.org/2000/svg" >
< path d = "M240 856h120V616h240v240h120V496L480 316 240 496v360Zm-80 80V456l320-240 320 240v480H520V696h-80v240H160Zm320-350Z" > < / path >
< / svg >
< / a >
< div class = "mr-1" > /< / div > < span aria-current = "page" class = "font-medium text-foreground overflow-hidden text-ellipsis whitespace-nowrap" > Deployment< / span >
< / nav >
< div id = "content" role = "main" >
< section id = "deployment" >
< span id = "id1" > < / span > < h1 > Deployment< a @ click . prevent = "window.navigator.clipboard.writeText($el.href); $el.setAttribute('data-tooltip', 'Copied!'); setTimeout(() => $el.setAttribute('data-tooltip', 'Copy link to this element'), 2000)" aria-label = "Copy link to this element" class = "headerlink" data-tooltip = "Copy link to this element" href = "#deployment" > < svg height = "1em" viewbox = "0 0 24 24" width = "1em" xmlns = "http://www.w3.org/2000/svg" > < path d = "M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z" > < / path > < / svg > < / a > < / h1 >
2026-03-05 15:35:59 +00:00
< p > Plano can be deployed in two ways: < strong > natively< / strong > on the host (default) or inside a < strong > Docker container< / strong > .< / p >
< section id = "native-deployment-default" >
< h2 > Native Deployment (Default)< a @ click . prevent = "window.navigator.clipboard.writeText($el.href); $el.setAttribute('data-tooltip', 'Copied!'); setTimeout(() => $el.setAttribute('data-tooltip', 'Copy link to this element'), 2000)" aria-label = "Copy link to this element" class = "headerlink" data-tooltip = "Copy link to this element" href = "#native-deployment-default" x-intersect . margin . 0 % . 0 % . -70 % . 0 % = " activeSection = '#native-deployment-default' " > < svg height = "1em" viewbox = "0 0 24 24" width = "1em" xmlns = "http://www.w3.org/2000/svg" > < path d = "M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z" > < / path > < / svg > < / a > < / h2 >
< p > Plano runs natively by default. Pre-compiled binaries (Envoy, WASM plugins, brightstaff) are automatically downloaded on the first run and cached at < code class = "docutils literal notranslate" > < span class = "pre" > ~/.plano/< / span > < / code > .< / p >
< p > Supported platforms: Linux (x86_64, aarch64), macOS (Apple Silicon).< / p >
< section id = "start-plano" >
< h3 > Start Plano< a @ click . prevent = "window.navigator.clipboard.writeText($el.href); $el.setAttribute('data-tooltip', 'Copied!'); setTimeout(() => $el.setAttribute('data-tooltip', 'Copy link to this element'), 2000)" aria-label = "Copy link to this element" class = "headerlink" data-tooltip = "Copy link to this element" href = "#start-plano" x-intersect . margin . 0 % . 0 % . -70 % . 0 % = " activeSection = '#start-plano' " > < svg height = "1em" viewbox = "0 0 24 24" width = "1em" xmlns = "http://www.w3.org/2000/svg" > < path d = "M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z" > < / path > < / svg > < / a > < / h3 >
< div class = "highlight-bash notranslate" > < div class = "highlight" > < pre > < span > < / span > < code > < span id = "line-1" > planoai< span class = "w" > < / span > up< span class = "w" > < / span > plano_config.yaml
< / span > < / code > < / pre > < / div >
< / div >
< p > Options:< / p >
< ul class = "simple" >
< li > < p > < code class = "docutils literal notranslate" > < span class = "pre" > --foreground< / span > < / code > — stay attached and stream logs (Ctrl+C to stop)< / p > < / li >
< li > < p > < code class = "docutils literal notranslate" > < span class = "pre" > --with-tracing< / span > < / code > — start a local OTLP trace collector< / p > < / li >
< / ul >
< p > Runtime files (rendered configs, logs, PID file) are stored in < code class = "docutils literal notranslate" > < span class = "pre" > ~/.plano/run/< / span > < / code > .< / p >
< / section >
< section id = "stop-plano" >
< h3 > Stop Plano< a @ click . prevent = "window.navigator.clipboard.writeText($el.href); $el.setAttribute('data-tooltip', 'Copied!'); setTimeout(() => $el.setAttribute('data-tooltip', 'Copy link to this element'), 2000)" aria-label = "Copy link to this element" class = "headerlink" data-tooltip = "Copy link to this element" href = "#stop-plano" x-intersect . margin . 0 % . 0 % . -70 % . 0 % = " activeSection = '#stop-plano' " > < svg height = "1em" viewbox = "0 0 24 24" width = "1em" xmlns = "http://www.w3.org/2000/svg" > < path d = "M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z" > < / path > < / svg > < / a > < / h3 >
< div class = "highlight-bash notranslate" > < div class = "highlight" > < pre > < span > < / span > < code > < span id = "line-1" > planoai< span class = "w" > < / span > down
< / span > < / code > < / pre > < / div >
< / div >
< / section >
< section id = "build-from-source-developer" >
< h3 > Build from Source (Developer)< a @ click . prevent = "window.navigator.clipboard.writeText($el.href); $el.setAttribute('data-tooltip', 'Copied!'); setTimeout(() => $el.setAttribute('data-tooltip', 'Copy link to this element'), 2000)" aria-label = "Copy link to this element" class = "headerlink" data-tooltip = "Copy link to this element" href = "#build-from-source-developer" x-intersect . margin . 0 % . 0 % . -70 % . 0 % = " activeSection = '#build-from-source-developer' " > < svg height = "1em" viewbox = "0 0 24 24" width = "1em" xmlns = "http://www.w3.org/2000/svg" > < path d = "M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z" > < / path > < / svg > < / a > < / h3 >
< p > If you want to build from source instead of using pre-compiled binaries, you need:< / p >
< ul class = "simple" >
< li > < p > < a class = "reference external" href = "https://rustup.rs" rel = "nofollow noopener" > Rust< svg fill = "currentColor" height = "1em" stroke = "none" viewbox = "0 96 960 960" width = "1em" xmlns = "http://www.w3.org/2000/svg" > < path d = "M188 868q-11-11-11-28t11-28l436-436H400q-17 0-28.5-11.5T360 336q0-17 11.5-28.5T400 296h320q17 0 28.5 11.5T760 336v320q0 17-11.5 28.5T720 696q-17 0-28.5-11.5T680 656V432L244 868q-11 11-28 11t-28-11Z" > < / path > < / svg > < / a > with the < code class = "docutils literal notranslate" > < span class = "pre" > wasm32-wasip1< / span > < / code > target< / p > < / li >
< li > < p > OpenSSL dev headers (< code class = "docutils literal notranslate" > < span class = "pre" > libssl-dev< / span > < / code > on Debian/Ubuntu, < code class = "docutils literal notranslate" > < span class = "pre" > openssl< / span > < / code > on macOS)< / p > < / li >
< / ul >
< div class = "highlight-bash notranslate" > < div class = "highlight" > < pre > < span > < / span > < code > < span id = "line-1" > planoai< span class = "w" > < / span > build< span class = "w" > < / span > --native
< / span > < / code > < / pre > < / div >
< / div >
< / section >
< / section >
2025-10-22 21:13:54 +00:00
< section id = "docker-deployment" >
< h2 > Docker Deployment< a @ click . prevent = "window.navigator.clipboard.writeText($el.href); $el.setAttribute('data-tooltip', 'Copied!'); setTimeout(() => $el.setAttribute('data-tooltip', 'Copy link to this element'), 2000)" aria-label = "Copy link to this element" class = "headerlink" data-tooltip = "Copy link to this element" href = "#docker-deployment" x-intersect . margin . 0 % . 0 % . -70 % . 0 % = " activeSection = '#docker-deployment' " > < svg height = "1em" viewbox = "0 0 24 24" width = "1em" xmlns = "http://www.w3.org/2000/svg" > < path d = "M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z" > < / path > < / svg > < / a > < / h2 >
2025-12-24 01:15:19 +00:00
< p > Below is a minimal, production-ready example showing how to deploy the Plano Docker image directly and run basic runtime checks. Adjust image names, tags, and the < code class = "docutils literal notranslate" > < span class = "pre" > plano_config.yaml< / span > < / code > path to match your environment.< / p >
2025-10-22 21:13:54 +00:00
< div class = "admonition note" >
< p class = "admonition-title" > Note< / p >
2025-12-24 01:15:19 +00:00
< p > You will need to pass all required environment variables that are referenced in your < code class = "docutils literal notranslate" > < span class = "pre" > plano_config.yaml< / span > < / code > file.< / p >
2025-10-22 21:13:54 +00:00
< / div >
2025-12-24 01:15:19 +00:00
< p > For < code class = "docutils literal notranslate" > < span class = "pre" > plano_config.yaml< / span > < / code > , you can use any sample configuration defined earlier in the documentation. For example, you can try the < a class = "reference internal" href = "../guides/llm_router.html#llm-router" > < span class = "std std-ref" > LLM Routing< / span > < / a > sample config.< / p >
2025-10-22 21:13:54 +00:00
< section id = "docker-compose-setup" >
< h3 > Docker Compose Setup< a @ click . prevent = "window.navigator.clipboard.writeText($el.href); $el.setAttribute('data-tooltip', 'Copied!'); setTimeout(() => $el.setAttribute('data-tooltip', 'Copy link to this element'), 2000)" aria-label = "Copy link to this element" class = "headerlink" data-tooltip = "Copy link to this element" href = "#docker-compose-setup" x-intersect . margin . 0 % . 0 % . -70 % . 0 % = " activeSection = '#docker-compose-setup' " > < svg height = "1em" viewbox = "0 0 24 24" width = "1em" xmlns = "http://www.w3.org/2000/svg" > < path d = "M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z" > < / path > < / svg > < / a > < / h3 >
< p > Create a < code class = "docutils literal notranslate" > < span class = "pre" > docker-compose.yml< / span > < / code > file with the following configuration:< / p >
< div class = "highlight-yaml notranslate" > < div class = "highlight" > < pre > < span > < / span > < code > < span id = "line-1" > < span class = "c1" > # docker-compose.yml< / span >
< / span > < span id = "line-2" > < span class = "nt" > services< / span > < span class = "p" > :< / span >
2025-12-24 01:15:19 +00:00
< / span > < span id = "line-3" > < span class = "w" > < / span > < span class = "nt" > plano< / span > < span class = "p" > :< / span >
2026-04-18 04:16:45 +00:00
< / span > < span id = "line-4" > < span class = "w" > < / span > < span class = "nt" > image< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > katanemo/plano:0.4.20< / span >
2025-12-24 01:15:19 +00:00
< / span > < span id = "line-5" > < span class = "w" > < / span > < span class = "nt" > container_name< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > plano< / span >
2025-10-22 21:13:54 +00:00
< / span > < span id = "line-6" > < span class = "w" > < / span > < span class = "nt" > ports< / span > < span class = "p" > :< / span >
2025-12-24 01:15:19 +00:00
< / span > < span id = "line-7" > < span class = "w" > < / span > < span class = "p p-Indicator" > -< / span > < span class = "w" > < / span > < span class = "s" > "10000:10000"< / span > < span class = "w" > < / span > < span class = "c1" > # ingress (client -> plano)< / span >
< / span > < span id = "line-8" > < span class = "w" > < / span > < span class = "p p-Indicator" > -< / span > < span class = "w" > < / span > < span class = "s" > "12000:12000"< / span > < span class = "w" > < / span > < span class = "c1" > # egress (plano -> upstream/llm proxy)< / span >
2025-10-22 21:13:54 +00:00
< / span > < span id = "line-9" > < span class = "w" > < / span > < span class = "nt" > volumes< / span > < span class = "p" > :< / span >
2025-12-24 01:15:19 +00:00
< / span > < span id = "line-10" > < span class = "w" > < / span > < span class = "p p-Indicator" > -< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > ./plano_config.yaml:/app/plano_config.yaml:ro< / span >
2025-10-22 21:13:54 +00:00
< / span > < span id = "line-11" > < span class = "w" > < / span > < span class = "nt" > environment< / span > < span class = "p" > :< / span >
< / span > < span id = "line-12" > < span class = "w" > < / span > < span class = "p p-Indicator" > -< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > OPENAI_API_KEY=${OPENAI_API_KEY:?error}< / span >
< / span > < span id = "line-13" > < span class = "w" > < / span > < span class = "p p-Indicator" > -< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:?error}< / span >
< / span > < / code > < / pre > < / div >
< / div >
< / section >
< section id = "starting-the-stack" >
< h3 > Starting the Stack< a @ click . prevent = "window.navigator.clipboard.writeText($el.href); $el.setAttribute('data-tooltip', 'Copied!'); setTimeout(() => $el.setAttribute('data-tooltip', 'Copy link to this element'), 2000)" aria-label = "Copy link to this element" class = "headerlink" data-tooltip = "Copy link to this element" href = "#starting-the-stack" x-intersect . margin . 0 % . 0 % . -70 % . 0 % = " activeSection = '#starting-the-stack' " > < svg height = "1em" viewbox = "0 0 24 24" width = "1em" xmlns = "http://www.w3.org/2000/svg" > < path d = "M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z" > < / path > < / svg > < / a > < / h3 >
2025-12-24 01:15:19 +00:00
< p > Start the services from the directory containing < code class = "docutils literal notranslate" > < span class = "pre" > docker-compose.yml< / span > < / code > and < code class = "docutils literal notranslate" > < span class = "pre" > plano_config.yaml< / span > < / code > :< / p >
2025-10-22 21:13:54 +00:00
< div class = "highlight-bash notranslate" > < div class = "highlight" > < pre > < span > < / span > < code > < span id = "line-1" > < span class = "c1" > # Set required environment variables and start services< / span >
< / span > < span id = "line-2" > < span class = "nv" > OPENAI_API_KEY< / span > < span class = "o" > =< / span > xxx< span class = "w" > < / span > < span class = "nv" > ANTHROPIC_API_KEY< / span > < span class = "o" > =< / span > yyy< span class = "w" > < / span > docker< span class = "w" > < / span > compose< span class = "w" > < / span > up< span class = "w" > < / span > -d
< / span > < / code > < / pre > < / div >
< / div >
< p > Check container health and logs:< / p >
< div class = "highlight-bash notranslate" > < div class = "highlight" > < pre > < span > < / span > < code > < span id = "line-1" > docker< span class = "w" > < / span > compose< span class = "w" > < / span > ps
2025-12-24 01:15:19 +00:00
< / span > < span id = "line-2" > docker< span class = "w" > < / span > compose< span class = "w" > < / span > logs< span class = "w" > < / span > -f< span class = "w" > < / span > plano
2025-10-22 21:13:54 +00:00
< / span > < / code > < / pre > < / div >
< / div >
2026-03-05 15:35:59 +00:00
< p > You can also use the CLI with Docker mode:< / p >
< div class = "highlight-bash notranslate" > < div class = "highlight" > < pre > < span > < / span > < code > < span id = "line-1" > planoai< span class = "w" > < / span > up< span class = "w" > < / span > plano_config.yaml< span class = "w" > < / span > --docker
< / span > < span id = "line-2" > planoai< span class = "w" > < / span > down< span class = "w" > < / span > --docker
< / span > < / code > < / pre > < / div >
< / div >
2025-10-22 21:13:54 +00:00
< / section >
< / section >
2026-03-10 19:28:03 +00:00
< section id = "kubernetes-deployment" >
< h2 > Kubernetes Deployment< a @ click . prevent = "window.navigator.clipboard.writeText($el.href); $el.setAttribute('data-tooltip', 'Copied!'); setTimeout(() => $el.setAttribute('data-tooltip', 'Copy link to this element'), 2000)" aria-label = "Copy link to this element" class = "headerlink" data-tooltip = "Copy link to this element" href = "#kubernetes-deployment" x-intersect . margin . 0 % . 0 % . -70 % . 0 % = " activeSection = '#kubernetes-deployment' " > < svg height = "1em" viewbox = "0 0 24 24" width = "1em" xmlns = "http://www.w3.org/2000/svg" > < path d = "M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z" > < / path > < / svg > < / a > < / h2 >
< p > Plano runs as a single container in Kubernetes. The container bundles Envoy, WASM plugins, and brightstaff, managed by supervisord internally. Deploy it as a standard Kubernetes Deployment with your < code class = "docutils literal notranslate" > < span class = "pre" > plano_config.yaml< / span > < / code > mounted via a ConfigMap and API keys injected via a Secret.< / p >
< div class = "admonition note" >
< p class = "admonition-title" > Note< / p >
< p > All environment variables referenced in your < code class = "docutils literal notranslate" > < span class = "pre" > plano_config.yaml< / span > < / code > (e.g. < code class = "docutils literal notranslate" > < span class = "pre" > $OPENAI_API_KEY< / span > < / code > ) must be set in the container environment. Use Kubernetes Secrets for API keys.< / p >
< / div >
< section id = "step-1-create-the-config" >
< h3 > Step 1: Create the Config< a @ click . prevent = "window.navigator.clipboard.writeText($el.href); $el.setAttribute('data-tooltip', 'Copied!'); setTimeout(() => $el.setAttribute('data-tooltip', 'Copy link to this element'), 2000)" aria-label = "Copy link to this element" class = "headerlink" data-tooltip = "Copy link to this element" href = "#step-1-create-the-config" x-intersect . margin . 0 % . 0 % . -70 % . 0 % = " activeSection = '#step-1-create-the-config' " > < svg height = "1em" viewbox = "0 0 24 24" width = "1em" xmlns = "http://www.w3.org/2000/svg" > < path d = "M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z" > < / path > < / svg > < / a > < / h3 >
< p > Store your < code class = "docutils literal notranslate" > < span class = "pre" > plano_config.yaml< / span > < / code > in a ConfigMap:< / p >
< div class = "highlight-bash notranslate" > < div class = "highlight" > < pre > < span > < / span > < code > < span id = "line-1" > kubectl< span class = "w" > < / span > create< span class = "w" > < / span > configmap< span class = "w" > < / span > plano-config< span class = "w" > < / span > --from-file< span class = "o" > =< / span > plano_config.yaml< span class = "o" > =< / span > ./plano_config.yaml
< / span > < / code > < / pre > < / div >
< / div >
< / section >
< section id = "step-2-create-api-key-secrets" >
< h3 > Step 2: Create API Key Secrets< a @ click . prevent = "window.navigator.clipboard.writeText($el.href); $el.setAttribute('data-tooltip', 'Copied!'); setTimeout(() => $el.setAttribute('data-tooltip', 'Copy link to this element'), 2000)" aria-label = "Copy link to this element" class = "headerlink" data-tooltip = "Copy link to this element" href = "#step-2-create-api-key-secrets" x-intersect . margin . 0 % . 0 % . -70 % . 0 % = " activeSection = '#step-2-create-api-key-secrets' " > < svg height = "1em" viewbox = "0 0 24 24" width = "1em" xmlns = "http://www.w3.org/2000/svg" > < path d = "M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z" > < / path > < / svg > < / a > < / h3 >
< p > Store your LLM provider API keys in a Secret:< / p >
< div class = "highlight-bash notranslate" > < div class = "highlight" > < pre > < span > < / span > < code > < span id = "line-1" > kubectl< span class = "w" > < / span > create< span class = "w" > < / span > secret< span class = "w" > < / span > generic< span class = "w" > < / span > plano-secrets< span class = "w" > < / span > < span class = "se" > \< / span >
< / span > < span id = "line-2" > < span class = "w" > < / span > --from-literal< span class = "o" > =< / span > < span class = "nv" > OPENAI_API_KEY< / span > < span class = "o" > =< / span > sk-...< span class = "w" > < / span > < span class = "se" > \< / span >
< / span > < span id = "line-3" > < span class = "w" > < / span > --from-literal< span class = "o" > =< / span > < span class = "nv" > ANTHROPIC_API_KEY< / span > < span class = "o" > =< / span > sk-ant-...
< / span > < / code > < / pre > < / div >
< / div >
< / section >
< section id = "step-3-deploy-plano" >
< h3 > Step 3: Deploy Plano< a @ click . prevent = "window.navigator.clipboard.writeText($el.href); $el.setAttribute('data-tooltip', 'Copied!'); setTimeout(() => $el.setAttribute('data-tooltip', 'Copy link to this element'), 2000)" aria-label = "Copy link to this element" class = "headerlink" data-tooltip = "Copy link to this element" href = "#step-3-deploy-plano" x-intersect . margin . 0 % . 0 % . -70 % . 0 % = " activeSection = '#step-3-deploy-plano' " > < svg height = "1em" viewbox = "0 0 24 24" width = "1em" xmlns = "http://www.w3.org/2000/svg" > < path d = "M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z" > < / path > < / svg > < / a > < / h3 >
< p > Create a < code class = "docutils literal notranslate" > < span class = "pre" > plano-deployment.yaml< / span > < / code > :< / p >
< div class = "highlight-yaml notranslate" > < div class = "highlight" > < pre > < span > < / span > < code > < span id = "line-1" > < span class = "nt" > apiVersion< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > apps/v1< / span >
< / span > < span id = "line-2" > < span class = "nt" > kind< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > Deployment< / span >
< / span > < span id = "line-3" > < span class = "nt" > metadata< / span > < span class = "p" > :< / span >
< / span > < span id = "line-4" > < span class = "w" > < / span > < span class = "nt" > name< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > plano< / span >
< / span > < span id = "line-5" > < span class = "w" > < / span > < span class = "nt" > labels< / span > < span class = "p" > :< / span >
< / span > < span id = "line-6" > < span class = "w" > < / span > < span class = "nt" > app< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > plano< / span >
< / span > < span id = "line-7" > < span class = "nt" > spec< / span > < span class = "p" > :< / span >
< / span > < span id = "line-8" > < span class = "w" > < / span > < span class = "nt" > replicas< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > 1< / span >
< / span > < span id = "line-9" > < span class = "w" > < / span > < span class = "nt" > selector< / span > < span class = "p" > :< / span >
< / span > < span id = "line-10" > < span class = "w" > < / span > < span class = "nt" > matchLabels< / span > < span class = "p" > :< / span >
< / span > < span id = "line-11" > < span class = "w" > < / span > < span class = "nt" > app< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > plano< / span >
< / span > < span id = "line-12" > < span class = "w" > < / span > < span class = "nt" > template< / span > < span class = "p" > :< / span >
< / span > < span id = "line-13" > < span class = "w" > < / span > < span class = "nt" > metadata< / span > < span class = "p" > :< / span >
< / span > < span id = "line-14" > < span class = "w" > < / span > < span class = "nt" > labels< / span > < span class = "p" > :< / span >
< / span > < span id = "line-15" > < span class = "w" > < / span > < span class = "nt" > app< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > plano< / span >
< / span > < span id = "line-16" > < span class = "w" > < / span > < span class = "nt" > spec< / span > < span class = "p" > :< / span >
< / span > < span id = "line-17" > < span class = "w" > < / span > < span class = "nt" > containers< / span > < span class = "p" > :< / span >
< / span > < span id = "line-18" > < span class = "w" > < / span > < span class = "p p-Indicator" > -< / span > < span class = "w" > < / span > < span class = "nt" > name< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > plano< / span >
2026-04-18 04:16:45 +00:00
< / span > < span id = "line-19" > < span class = "w" > < / span > < span class = "nt" > image< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > katanemo/plano:0.4.20< / span >
2026-03-10 19:28:03 +00:00
< / span > < span id = "line-20" > < span class = "w" > < / span > < span class = "nt" > ports< / span > < span class = "p" > :< / span >
< / span > < span id = "line-21" > < span class = "w" > < / span > < span class = "p p-Indicator" > -< / span > < span class = "w" > < / span > < span class = "nt" > containerPort< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > 12000< / span > < span class = "w" > < / span > < span class = "c1" > # LLM gateway (chat completions, model routing)< / span >
< / span > < span id = "line-22" > < span class = "w" > < / span > < span class = "nt" > name< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > llm-gateway< / span >
< / span > < span id = "line-23" > < span class = "w" > < / span > < span class = "nt" > envFrom< / span > < span class = "p" > :< / span >
< / span > < span id = "line-24" > < span class = "w" > < / span > < span class = "p p-Indicator" > -< / span > < span class = "w" > < / span > < span class = "nt" > secretRef< / span > < span class = "p" > :< / span >
< / span > < span id = "line-25" > < span class = "w" > < / span > < span class = "nt" > name< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > plano-secrets< / span >
< / span > < span id = "line-26" > < span class = "w" > < / span > < span class = "nt" > env< / span > < span class = "p" > :< / span >
< / span > < span id = "line-27" > < span class = "w" > < / span > < span class = "p p-Indicator" > -< / span > < span class = "w" > < / span > < span class = "nt" > name< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > LOG_LEVEL< / span >
< / span > < span id = "line-28" > < span class = "w" > < / span > < span class = "nt" > value< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "s" > "info"< / span >
< / span > < span id = "line-29" > < span class = "w" > < / span > < span class = "nt" > volumeMounts< / span > < span class = "p" > :< / span >
< / span > < span id = "line-30" > < span class = "w" > < / span > < span class = "p p-Indicator" > -< / span > < span class = "w" > < / span > < span class = "nt" > name< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > plano-config< / span >
< / span > < span id = "line-31" > < span class = "w" > < / span > < span class = "nt" > mountPath< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > /app/plano_config.yaml< / span >
< / span > < span id = "line-32" > < span class = "w" > < / span > < span class = "nt" > subPath< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > plano_config.yaml< / span >
< / span > < span id = "line-33" > < span class = "w" > < / span > < span class = "nt" > readOnly< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > true< / span >
< / span > < span id = "line-34" > < span class = "w" > < / span > < span class = "nt" > readinessProbe< / span > < span class = "p" > :< / span >
< / span > < span id = "line-35" > < span class = "w" > < / span > < span class = "nt" > httpGet< / span > < span class = "p" > :< / span >
< / span > < span id = "line-36" > < span class = "w" > < / span > < span class = "nt" > path< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > /healthz< / span >
< / span > < span id = "line-37" > < span class = "w" > < / span > < span class = "nt" > port< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > 12000< / span >
< / span > < span id = "line-38" > < span class = "w" > < / span > < span class = "nt" > initialDelaySeconds< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > 5< / span >
< / span > < span id = "line-39" > < span class = "w" > < / span > < span class = "nt" > periodSeconds< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > 10< / span >
< / span > < span id = "line-40" > < span class = "w" > < / span > < span class = "nt" > livenessProbe< / span > < span class = "p" > :< / span >
< / span > < span id = "line-41" > < span class = "w" > < / span > < span class = "nt" > httpGet< / span > < span class = "p" > :< / span >
< / span > < span id = "line-42" > < span class = "w" > < / span > < span class = "nt" > path< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > /healthz< / span >
< / span > < span id = "line-43" > < span class = "w" > < / span > < span class = "nt" > port< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > 12000< / span >
< / span > < span id = "line-44" > < span class = "w" > < / span > < span class = "nt" > initialDelaySeconds< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > 10< / span >
< / span > < span id = "line-45" > < span class = "w" > < / span > < span class = "nt" > periodSeconds< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > 30< / span >
< / span > < span id = "line-46" > < span class = "w" > < / span > < span class = "nt" > resources< / span > < span class = "p" > :< / span >
< / span > < span id = "line-47" > < span class = "w" > < / span > < span class = "nt" > requests< / span > < span class = "p" > :< / span >
< / span > < span id = "line-48" > < span class = "w" > < / span > < span class = "nt" > memory< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "s" > "256Mi"< / span >
< / span > < span id = "line-49" > < span class = "w" > < / span > < span class = "nt" > cpu< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "s" > "250m"< / span >
< / span > < span id = "line-50" > < span class = "w" > < / span > < span class = "nt" > limits< / span > < span class = "p" > :< / span >
< / span > < span id = "line-51" > < span class = "w" > < / span > < span class = "nt" > memory< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "s" > "512Mi"< / span >
< / span > < span id = "line-52" > < span class = "w" > < / span > < span class = "nt" > cpu< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "s" > "1000m"< / span >
< / span > < span id = "line-53" > < span class = "w" > < / span > < span class = "nt" > volumes< / span > < span class = "p" > :< / span >
< / span > < span id = "line-54" > < span class = "w" > < / span > < span class = "p p-Indicator" > -< / span > < span class = "w" > < / span > < span class = "nt" > name< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > plano-config< / span >
< / span > < span id = "line-55" > < span class = "w" > < / span > < span class = "nt" > configMap< / span > < span class = "p" > :< / span >
< / span > < span id = "line-56" > < span class = "w" > < / span > < span class = "nt" > name< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > plano-config< / span >
< / span > < span id = "line-57" > < span class = "nn" > ---< / span >
< / span > < span id = "line-58" > < span class = "nt" > apiVersion< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > v1< / span >
< / span > < span id = "line-59" > < span class = "nt" > kind< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > Service< / span >
< / span > < span id = "line-60" > < span class = "nt" > metadata< / span > < span class = "p" > :< / span >
< / span > < span id = "line-61" > < span class = "w" > < / span > < span class = "nt" > name< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > plano< / span >
< / span > < span id = "line-62" > < span class = "nt" > spec< / span > < span class = "p" > :< / span >
< / span > < span id = "line-63" > < span class = "w" > < / span > < span class = "nt" > selector< / span > < span class = "p" > :< / span >
< / span > < span id = "line-64" > < span class = "w" > < / span > < span class = "nt" > app< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > plano< / span >
< / span > < span id = "line-65" > < span class = "w" > < / span > < span class = "nt" > ports< / span > < span class = "p" > :< / span >
< / span > < span id = "line-66" > < span class = "w" > < / span > < span class = "p p-Indicator" > -< / span > < span class = "w" > < / span > < span class = "nt" > name< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > llm-gateway< / span >
< / span > < span id = "line-67" > < span class = "w" > < / span > < span class = "nt" > port< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > 12000< / span >
< / span > < span id = "line-68" > < span class = "w" > < / span > < span class = "nt" > targetPort< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > 12000< / span >
< / span > < / code > < / pre > < / div >
< / div >
< p > Apply it:< / p >
< div class = "highlight-bash notranslate" > < div class = "highlight" > < pre > < span > < / span > < code > < span id = "line-1" > kubectl< span class = "w" > < / span > apply< span class = "w" > < / span > -f< span class = "w" > < / span > plano-deployment.yaml
< / span > < / code > < / pre > < / div >
< / div >
< / section >
< section id = "step-4-verify" >
< h3 > Step 4: Verify< a @ click . prevent = "window.navigator.clipboard.writeText($el.href); $el.setAttribute('data-tooltip', 'Copied!'); setTimeout(() => $el.setAttribute('data-tooltip', 'Copy link to this element'), 2000)" aria-label = "Copy link to this element" class = "headerlink" data-tooltip = "Copy link to this element" href = "#step-4-verify" x-intersect . margin . 0 % . 0 % . -70 % . 0 % = " activeSection = '#step-4-verify' " > < svg height = "1em" viewbox = "0 0 24 24" width = "1em" xmlns = "http://www.w3.org/2000/svg" > < path d = "M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z" > < / path > < / svg > < / a > < / h3 >
< div class = "highlight-bash notranslate" > < div class = "highlight" > < pre > < span > < / span > < code > < span id = "line-1" > < span class = "c1" > # Check pod status< / span >
< / span > < span id = "line-2" > kubectl< span class = "w" > < / span > get< span class = "w" > < / span > pods< span class = "w" > < / span > -l< span class = "w" > < / span > < span class = "nv" > app< / span > < span class = "o" > =< / span > plano
< / span > < span id = "line-3" >
< / span > < span id = "line-4" > < span class = "c1" > # Check logs< / span >
< / span > < span id = "line-5" > kubectl< span class = "w" > < / span > logs< span class = "w" > < / span > -l< span class = "w" > < / span > < span class = "nv" > app< / span > < span class = "o" > =< / span > plano< span class = "w" > < / span > -f
< / span > < span id = "line-6" >
< / span > < span id = "line-7" > < span class = "c1" > # Test routing (port-forward for local testing)< / span >
< / span > < span id = "line-8" > kubectl< span class = "w" > < / span > port-forward< span class = "w" > < / span > svc/plano< span class = "w" > < / span > < span class = "m" > 12000< / span > :12000
< / span > < span id = "line-9" >
< / span > < span id = "line-10" > curl< span class = "w" > < / span > -s< span class = "w" > < / span > -H< span class = "w" > < / span > < span class = "s2" > "Content-Type: application/json"< / span > < span class = "w" > < / span > < span class = "se" > \< / span >
< / span > < span id = "line-11" > < span class = "w" > < / span > -d< span class = "w" > < / span > < span class = "s1" > '{"messages":[{"role":"user","content":"tell me a joke"}], "model":"none"}'< / span > < span class = "w" > < / span > < span class = "se" > \< / span >
< / span > < span id = "line-12" > < span class = "w" > < / span > http://localhost:12000/v1/chat/completions< span class = "w" > < / span > < span class = "p" > |< / span > < span class = "w" > < / span > jq< span class = "w" > < / span > .model
< / span > < / code > < / pre > < / div >
< / div >
< / section >
< section id = "updating-configuration" >
< h3 > Updating Configuration< a @ click . prevent = "window.navigator.clipboard.writeText($el.href); $el.setAttribute('data-tooltip', 'Copied!'); setTimeout(() => $el.setAttribute('data-tooltip', 'Copy link to this element'), 2000)" aria-label = "Copy link to this element" class = "headerlink" data-tooltip = "Copy link to this element" href = "#updating-configuration" x-intersect . margin . 0 % . 0 % . -70 % . 0 % = " activeSection = '#updating-configuration' " > < svg height = "1em" viewbox = "0 0 24 24" width = "1em" xmlns = "http://www.w3.org/2000/svg" > < path d = "M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z" > < / path > < / svg > < / a > < / h3 >
< p > To update < code class = "docutils literal notranslate" > < span class = "pre" > plano_config.yaml< / span > < / code > , replace the ConfigMap and restart the pod:< / p >
< div class = "highlight-bash notranslate" > < div class = "highlight" > < pre > < span > < / span > < code > < span id = "line-1" > kubectl< span class = "w" > < / span > create< span class = "w" > < / span > configmap< span class = "w" > < / span > plano-config< span class = "w" > < / span > < span class = "se" > \< / span >
< / span > < span id = "line-2" > < span class = "w" > < / span > --from-file< span class = "o" > =< / span > plano_config.yaml< span class = "o" > =< / span > ./plano_config.yaml< span class = "w" > < / span > < span class = "se" > \< / span >
< / span > < span id = "line-3" > < span class = "w" > < / span > --dry-run< span class = "o" > =< / span > client< span class = "w" > < / span > -o< span class = "w" > < / span > yaml< span class = "w" > < / span > < span class = "p" > |< / span > < span class = "w" > < / span > kubectl< span class = "w" > < / span > apply< span class = "w" > < / span > -f< span class = "w" > < / span > -
< / span > < span id = "line-4" >
< / span > < span id = "line-5" > kubectl< span class = "w" > < / span > rollout< span class = "w" > < / span > restart< span class = "w" > < / span > deployment/plano
< / span > < / code > < / pre > < / div >
< / div >
< / section >
< section id = "enabling-otel-tracing" >
< h3 > Enabling OTEL Tracing< a @ click . prevent = "window.navigator.clipboard.writeText($el.href); $el.setAttribute('data-tooltip', 'Copied!'); setTimeout(() => $el.setAttribute('data-tooltip', 'Copy link to this element'), 2000)" aria-label = "Copy link to this element" class = "headerlink" data-tooltip = "Copy link to this element" href = "#enabling-otel-tracing" x-intersect . margin . 0 % . 0 % . -70 % . 0 % = " activeSection = '#enabling-otel-tracing' " > < svg height = "1em" viewbox = "0 0 24 24" width = "1em" xmlns = "http://www.w3.org/2000/svg" > < path d = "M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z" > < / path > < / svg > < / a > < / h3 >
< p > Plano emits OpenTelemetry traces for every request — including routing decisions, model selection, and upstream latency. To export traces to an OTEL collector in your cluster, add the < code class = "docutils literal notranslate" > < span class = "pre" > tracing< / span > < / code > section to your < code class = "docutils literal notranslate" > < span class = "pre" > plano_config.yaml< / span > < / code > :< / p >
< div class = "highlight-yaml notranslate" > < div class = "highlight" > < pre > < span > < / span > < code > < span id = "line-1" > < span class = "nt" > tracing< / span > < span class = "p" > :< / span >
< / span > < span id = "line-2" > < span class = "w" > < / span > < span class = "nt" > opentracing_grpc_endpoint< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "s" > "http://otel-collector.monitoring:4317"< / span >
< / span > < span id = "line-3" > < span class = "w" > < / span > < span class = "nt" > random_sampling< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > 100< / span > < span class = "w" > < / span > < span class = "c1" > # percentage of requests to trace (1-100)< / span >
< / span > < span id = "line-4" > < span class = "w" > < / span > < span class = "nt" > trace_arch_internal< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "l l-Scalar l-Scalar-Plain" > true< / span > < span class = "w" > < / span > < span class = "c1" > # include internal Plano spans< / span >
< / span > < span id = "line-5" > < span class = "w" > < / span > < span class = "nt" > span_attributes< / span > < span class = "p" > :< / span >
< / span > < span id = "line-6" > < span class = "w" > < / span > < span class = "nt" > header_prefixes< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "c1" > # capture request headers as span attributes< / span >
< / span > < span id = "line-7" > < span class = "w" > < / span > < span class = "p p-Indicator" > -< / span > < span class = "w" > < / span > < span class = "s" > "x-"< / span >
< / span > < span id = "line-8" > < span class = "w" > < / span > < span class = "nt" > static< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "c1" > # add static attributes to all spans< / span >
< / span > < span id = "line-9" > < span class = "w" > < / span > < span class = "nt" > environment< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "s" > "production"< / span >
< / span > < span id = "line-10" > < span class = "w" > < / span > < span class = "nt" > service< / span > < span class = "p" > :< / span > < span class = "w" > < / span > < span class = "s" > "plano"< / span >
< / span > < / code > < / pre > < / div >
< / div >
< p > Set the < code class = "docutils literal notranslate" > < span class = "pre" > OTEL_TRACING_GRPC_ENDPOINT< / span > < / code > environment variable or configure it directly in the config. Plano propagates the < code class = "docutils literal notranslate" > < span class = "pre" > traceparent< / span > < / code > header end-to-end, so traces correlate across your upstream and downstream services.< / p >
< / section >
< section id = "environment-variables-reference" >
< h3 > Environment Variables Reference< a @ click . prevent = "window.navigator.clipboard.writeText($el.href); $el.setAttribute('data-tooltip', 'Copied!'); setTimeout(() => $el.setAttribute('data-tooltip', 'Copy link to this element'), 2000)" aria-label = "Copy link to this element" class = "headerlink" data-tooltip = "Copy link to this element" href = "#environment-variables-reference" x-intersect . margin . 0 % . 0 % . -70 % . 0 % = " activeSection = '#environment-variables-reference' " > < svg height = "1em" viewbox = "0 0 24 24" width = "1em" xmlns = "http://www.w3.org/2000/svg" > < path d = "M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z" > < / path > < / svg > < / a > < / h3 >
< p > The following environment variables can be set on the container:< / p >
< table class = "docutils align-default" >
< colgroup >
< col style = "width: 30.0%" / >
< col style = "width: 50.0%" / >
< col style = "width: 20.0%" / >
< / colgroup >
< thead >
< tr class = "row-odd" > < th class = "head" > < p > Variable< / p > < / th >
< th class = "head" > < p > Description< / p > < / th >
< th class = "head" > < p > Default< / p > < / th >
< / tr >
< / thead >
< tbody >
< tr class = "row-even" > < td > < p > < code class = "docutils literal notranslate" > < span class = "pre" > LOG_LEVEL< / span > < / code > < / p > < / td >
< td > < p > Log verbosity (< code class = "docutils literal notranslate" > < span class = "pre" > debug< / span > < / code > , < code class = "docutils literal notranslate" > < span class = "pre" > info< / span > < / code > , < code class = "docutils literal notranslate" > < span class = "pre" > warn< / span > < / code > , < code class = "docutils literal notranslate" > < span class = "pre" > error< / span > < / code > )< / p > < / td >
< td > < p > < code class = "docutils literal notranslate" > < span class = "pre" > info< / span > < / code > < / p > < / td >
< / tr >
< tr class = "row-odd" > < td > < p > < code class = "docutils literal notranslate" > < span class = "pre" > OPENAI_API_KEY< / span > < / code > < / p > < / td >
< td > < p > OpenAI API key (if referenced in config)< / p > < / td >
< td > < / td >
< / tr >
< tr class = "row-even" > < td > < p > < code class = "docutils literal notranslate" > < span class = "pre" > ANTHROPIC_API_KEY< / span > < / code > < / p > < / td >
< td > < p > Anthropic API key (if referenced in config)< / p > < / td >
< td > < / td >
< / tr >
< tr class = "row-odd" > < td > < p > < code class = "docutils literal notranslate" > < span class = "pre" > OTEL_TRACING_GRPC_ENDPOINT< / span > < / code > < / p > < / td >
< td > < p > OTEL collector endpoint for trace export< / p > < / td >
< td > < p > < code class = "docutils literal notranslate" > < span class = "pre" > http://localhost:4317< / span > < / code > < / p > < / td >
< / tr >
< / tbody >
< / table >
< p > Any environment variable referenced in < code class = "docutils literal notranslate" > < span class = "pre" > plano_config.yaml< / span > < / code > with < code class = "docutils literal notranslate" > < span class = "pre" > $VAR_NAME< / span > < / code > syntax will be substituted at startup. Use Kubernetes Secrets for sensitive values and ConfigMaps or < code class = "docutils literal notranslate" > < span class = "pre" > env< / span > < / code > entries for non-sensitive configuration.< / p >
< / section >
< / section >
2025-10-22 21:13:54 +00:00
< section id = "runtime-tests" >
< h2 > Runtime Tests< a @ click . prevent = "window.navigator.clipboard.writeText($el.href); $el.setAttribute('data-tooltip', 'Copied!'); setTimeout(() => $el.setAttribute('data-tooltip', 'Copy link to this element'), 2000)" aria-label = "Copy link to this element" class = "headerlink" data-tooltip = "Copy link to this element" href = "#runtime-tests" x-intersect . margin . 0 % . 0 % . -70 % . 0 % = " activeSection = '#runtime-tests' " > < svg height = "1em" viewbox = "0 0 24 24" width = "1em" xmlns = "http://www.w3.org/2000/svg" > < path d = "M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z" > < / path > < / svg > < / a > < / h2 >
< p > Perform basic runtime tests to verify routing and functionality.< / p >
< section id = "gateway-smoke-test" >
< h3 > Gateway Smoke Test< a @ click . prevent = "window.navigator.clipboard.writeText($el.href); $el.setAttribute('data-tooltip', 'Copied!'); setTimeout(() => $el.setAttribute('data-tooltip', 'Copy link to this element'), 2000)" aria-label = "Copy link to this element" class = "headerlink" data-tooltip = "Copy link to this element" href = "#gateway-smoke-test" x-intersect . margin . 0 % . 0 % . -70 % . 0 % = " activeSection = '#gateway-smoke-test' " > < svg height = "1em" viewbox = "0 0 24 24" width = "1em" xmlns = "http://www.w3.org/2000/svg" > < path d = "M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z" > < / path > < / svg > < / a > < / h3 >
< p > Test the chat completion endpoint with automatic routing:< / p >
2025-12-24 01:15:19 +00:00
< div class = "highlight-bash notranslate" > < div class = "highlight" > < pre > < span > < / span > < code > < span id = "line-1" > < span class = "c1" > # Request handled by the gateway. 'model: "none"' lets Plano decide routing< / span >
2025-10-22 21:13:54 +00:00
< / span > < span id = "line-2" > curl< span class = "w" > < / span > --header< span class = "w" > < / span > < span class = "s1" > 'Content-Type: application/json'< / span > < span class = "w" > < / span > < span class = "se" > \< / span >
< / span > < span id = "line-3" > < span class = "w" > < / span > --data< span class = "w" > < / span > < span class = "s1" > '{"messages":[{"role":"user","content":"tell me a joke"}], "model":"none"}'< / span > < span class = "w" > < / span > < span class = "se" > \< / span >
< / span > < span id = "line-4" > < span class = "w" > < / span > http://localhost:12000/v1/chat/completions< span class = "w" > < / span > < span class = "p" > |< / span > < span class = "w" > < / span > jq< span class = "w" > < / span > .model
< / span > < / code > < / pre > < / div >
< / div >
< p > Expected output:< / p >
2025-12-24 01:15:19 +00:00
< div class = "highlight-json notranslate" > < div class = "highlight" > < pre > < span > < / span > < code > < span id = "line-1" > < span class = "s2" > "gpt-5.2"< / span >
2025-10-22 21:13:54 +00:00
< / span > < / code > < / pre > < / div >
< / div >
< / section >
< section id = "model-based-routing" >
< h3 > Model-Based Routing< a @ click . prevent = "window.navigator.clipboard.writeText($el.href); $el.setAttribute('data-tooltip', 'Copied!'); setTimeout(() => $el.setAttribute('data-tooltip', 'Copy link to this element'), 2000)" aria-label = "Copy link to this element" class = "headerlink" data-tooltip = "Copy link to this element" href = "#model-based-routing" x-intersect . margin . 0 % . 0 % . -70 % . 0 % = " activeSection = '#model-based-routing' " > < svg height = "1em" viewbox = "0 0 24 24" width = "1em" xmlns = "http://www.w3.org/2000/svg" > < path d = "M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z" > < / path > < / svg > < / a > < / h3 >
< p > Test explicit provider and model routing:< / p >
< div class = "highlight-bash notranslate" > < div class = "highlight" > < pre > < span > < / span > < code > < span id = "line-1" > curl< span class = "w" > < / span > -s< span class = "w" > < / span > -H< span class = "w" > < / span > < span class = "s2" > "Content-Type: application/json"< / span > < span class = "w" > < / span > < span class = "se" > \< / span >
2025-12-24 01:15:19 +00:00
< / span > < span id = "line-2" > < span class = "w" > < / span > -d< span class = "w" > < / span > < span class = "s1" > '{"messages":[{"role":"user","content":"Explain quantum computing"}], "model":"anthropic/claude-sonnet-4-5"}'< / span > < span class = "w" > < / span > < span class = "se" > \< / span >
2025-10-22 21:13:54 +00:00
< / span > < span id = "line-3" > < span class = "w" > < / span > http://localhost:12000/v1/chat/completions< span class = "w" > < / span > < span class = "p" > |< / span > < span class = "w" > < / span > jq< span class = "w" > < / span > .model
< / span > < / code > < / pre > < / div >
< / div >
< p > Expected output:< / p >
2025-12-24 01:15:19 +00:00
< div class = "highlight-json notranslate" > < div class = "highlight" > < pre > < span > < / span > < code > < span id = "line-1" > < span class = "s2" > "claude-sonnet-4-5"< / span >
2025-10-22 21:13:54 +00:00
< / span > < / code > < / pre > < / div >
< / div >
< / section >
< / section >
< section id = "troubleshooting" >
< h2 > Troubleshooting< a @ click . prevent = "window.navigator.clipboard.writeText($el.href); $el.setAttribute('data-tooltip', 'Copied!'); setTimeout(() => $el.setAttribute('data-tooltip', 'Copy link to this element'), 2000)" aria-label = "Copy link to this element" class = "headerlink" data-tooltip = "Copy link to this element" href = "#troubleshooting" x-intersect . margin . 0 % . 0 % . -70 % . 0 % = " activeSection = '#troubleshooting' " > < svg height = "1em" viewbox = "0 0 24 24" width = "1em" xmlns = "http://www.w3.org/2000/svg" > < path d = "M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z" > < / path > < / svg > < / a > < / h2 >
< section id = "common-issues-and-solutions" >
< h3 > Common Issues and Solutions< a @ click . prevent = "window.navigator.clipboard.writeText($el.href); $el.setAttribute('data-tooltip', 'Copied!'); setTimeout(() => $el.setAttribute('data-tooltip', 'Copy link to this element'), 2000)" aria-label = "Copy link to this element" class = "headerlink" data-tooltip = "Copy link to this element" href = "#common-issues-and-solutions" x-intersect . margin . 0 % . 0 % . -70 % . 0 % = " activeSection = '#common-issues-and-solutions' " > < svg height = "1em" viewbox = "0 0 24 24" width = "1em" xmlns = "http://www.w3.org/2000/svg" > < path d = "M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z" > < / path > < / svg > < / a > < / h3 >
< dl class = "simple" >
2025-12-24 01:15:19 +00:00
< dt > < strong > Environment Variables< / strong > < / dt > < dd > < p > Ensure all environment variables (< code class = "docutils literal notranslate" > < span class = "pre" > OPENAI_API_KEY< / span > < / code > , < code class = "docutils literal notranslate" > < span class = "pre" > ANTHROPIC_API_KEY< / span > < / code > , etc.) used by < code class = "docutils literal notranslate" > < span class = "pre" > plano_config.yaml< / span > < / code > are set before starting services.< / p >
2025-10-22 21:13:54 +00:00
< / dd >
< dt > < strong > TLS/Connection Errors< / strong > < / dt > < dd > < p > If you encounter TLS or connection errors to upstream providers:< / p >
< ul class = "simple" >
< li > < p > Check DNS resolution< / p > < / li >
< li > < p > Verify proxy settings< / p > < / li >
2025-12-24 01:15:19 +00:00
< li > < p > Confirm correct protocol and port in your < code class = "docutils literal notranslate" > < span class = "pre" > plano_config< / span > < / code > endpoints< / p > < / li >
2025-10-22 21:13:54 +00:00
< / ul >
< / dd >
< dt > < strong > Verbose Logging< / strong > < / dt > < dd > < p > To enable more detailed logs for debugging:< / p >
< ul class = "simple" >
2025-12-24 01:15:19 +00:00
< li > < p > Run plano with a higher component log level< / p > < / li >
2025-10-22 21:13:54 +00:00
< li > < p > See the < a class = "reference internal" href = "../guides/observability/observability.html#observability" > < span class = "std std-ref" > Observability< / span > < / a > guide for logging and monitoring details< / p > < / li >
< li > < p > Rebuild the image if required with updated log configuration< / p > < / li >
< / ul >
< / dd >
< dt > < strong > CI/Automated Checks< / strong > < / dt > < dd > < p > For continuous integration or automated testing, you can use the curl commands above as health checks in your deployment pipeline.< / p >
< / dd >
< / dl >
< / section >
< / section >
< / section >
< / div > < div class = "flex justify-between items-center pt-6 mt-12 border-t border-border gap-4" >
< div class = "mr-auto" >
2025-12-24 01:15:19 +00:00
< a class = "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors border border-input hover:bg-accent hover:text-accent-foreground py-2 px-4" href = "tech_overview/threading_model.html" >
2025-10-22 21:13:54 +00:00
< svg class = "mr-2 h-4 w-4" fill = "none" height = "24" stroke = "currentColor" stroke-linecap = "round" stroke-linejoin = "round" stroke-width = "2" viewbox = "0 0 24 24" width = "24" xmlns = "http://www.w3.org/2000/svg" >
< polyline points = "15 18 9 12 15 6" > < / polyline >
< / svg >
2025-12-24 01:15:19 +00:00
Threading Model
2025-10-22 21:13:54 +00:00
< / a >
< / div >
< div class = "ml-auto" >
< a class = "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors border border-input hover:bg-accent hover:text-accent-foreground py-2 px-4" href = "configuration_reference.html" >
Configuration Reference
< svg class = "ml-2 h-4 w-4" fill = "none" height = "24" stroke = "currentColor" stroke-linecap = "round" stroke-linejoin = "round" stroke-width = "2" viewbox = "0 0 24 24" width = "24" xmlns = "http://www.w3.org/2000/svg" >
< polyline points = "9 18 15 12 9 6" > < / polyline >
< / svg >
< / a >
< / div >
< / div > < / div > < aside class = "hidden text-sm xl:block" id = "right-sidebar" >
2026-01-24 20:01:20 +00:00
< div class = "sticky top-16 -mt-10 max-h-[calc(100vh-5rem)] h-full overflow-y-auto pt-6 space-y-2" > < p class = "font-medium" > On this page< / p >
2025-10-22 21:13:54 +00:00
< ul >
2026-03-05 15:35:59 +00:00
< li > < a :data-current = "activeSection === '#native-deployment-default'" class = "reference internal" href = "#native-deployment-default" > Native Deployment (Default)< / a > < ul >
< li > < a :data-current = "activeSection === '#start-plano'" class = "reference internal" href = "#start-plano" > Start Plano< / a > < / li >
< li > < a :data-current = "activeSection === '#stop-plano'" class = "reference internal" href = "#stop-plano" > Stop Plano< / a > < / li >
< li > < a :data-current = "activeSection === '#build-from-source-developer'" class = "reference internal" href = "#build-from-source-developer" > Build from Source (Developer)< / a > < / li >
< / ul >
< / li >
2025-10-22 21:13:54 +00:00
< li > < a :data-current = "activeSection === '#docker-deployment'" class = "reference internal" href = "#docker-deployment" > Docker Deployment< / a > < ul >
< li > < a :data-current = "activeSection === '#docker-compose-setup'" class = "reference internal" href = "#docker-compose-setup" > Docker Compose Setup< / a > < / li >
< li > < a :data-current = "activeSection === '#starting-the-stack'" class = "reference internal" href = "#starting-the-stack" > Starting the Stack< / a > < / li >
< / ul >
< / li >
2026-03-10 19:28:03 +00:00
< li > < a :data-current = "activeSection === '#kubernetes-deployment'" class = "reference internal" href = "#kubernetes-deployment" > Kubernetes Deployment< / a > < ul >
< li > < a :data-current = "activeSection === '#step-1-create-the-config'" class = "reference internal" href = "#step-1-create-the-config" > Step 1: Create the Config< / a > < / li >
< li > < a :data-current = "activeSection === '#step-2-create-api-key-secrets'" class = "reference internal" href = "#step-2-create-api-key-secrets" > Step 2: Create API Key Secrets< / a > < / li >
< li > < a :data-current = "activeSection === '#step-3-deploy-plano'" class = "reference internal" href = "#step-3-deploy-plano" > Step 3: Deploy Plano< / a > < / li >
< li > < a :data-current = "activeSection === '#step-4-verify'" class = "reference internal" href = "#step-4-verify" > Step 4: Verify< / a > < / li >
< li > < a :data-current = "activeSection === '#updating-configuration'" class = "reference internal" href = "#updating-configuration" > Updating Configuration< / a > < / li >
< li > < a :data-current = "activeSection === '#enabling-otel-tracing'" class = "reference internal" href = "#enabling-otel-tracing" > Enabling OTEL Tracing< / a > < / li >
< li > < a :data-current = "activeSection === '#environment-variables-reference'" class = "reference internal" href = "#environment-variables-reference" > Environment Variables Reference< / a > < / li >
< / ul >
< / li >
2025-10-22 21:13:54 +00:00
< li > < a :data-current = "activeSection === '#runtime-tests'" class = "reference internal" href = "#runtime-tests" > Runtime Tests< / a > < ul >
< li > < a :data-current = "activeSection === '#gateway-smoke-test'" class = "reference internal" href = "#gateway-smoke-test" > Gateway Smoke Test< / a > < / li >
< li > < a :data-current = "activeSection === '#model-based-routing'" class = "reference internal" href = "#model-based-routing" > Model-Based Routing< / a > < / li >
< / ul >
< / li >
< li > < a :data-current = "activeSection === '#troubleshooting'" class = "reference internal" href = "#troubleshooting" > Troubleshooting< / a > < ul >
< li > < a :data-current = "activeSection === '#common-issues-and-solutions'" class = "reference internal" href = "#common-issues-and-solutions" > Common Issues and Solutions< / a > < / li >
< / ul >
< / li >
< / ul >
< / div >
< / aside >
< / main >
< / div >
< / div > < footer class = "py-6 border-t border-border md:py-0" >
< div class = "container flex flex-col items-center justify-between gap-4 md:h-24 md:flex-row" >
< div class = "flex flex-col items-center gap-4 px-8 md:flex-row md:gap-2 md:px-0" >
2026-04-23 18:39:06 +00:00
< p class = "text-sm leading-loose text-center text-muted-foreground md:text-left" > © 2026, Katanemo Labs, a DigitalOcean Company Last updated: Apr 23, 2026. < / p >
2025-10-22 21:13:54 +00:00
< / div >
< / div >
< / footer >
< / div >
2026-04-18 04:16:45 +00:00
< script src = "../_static/documentation_options.js?v=6df19ec7" > < / script >
2025-10-22 21:13:54 +00:00
< script src = "../_static/doctools.js?v=9bcbadda" > < / script >
< script src = "../_static/sphinx_highlight.js?v=dc90522c" > < / script >
2026-04-16 20:17:24 +00:00
< script defer = "defer" src = "../_static/theme.js?v=d6a9845b" > < / script >
2025-10-22 21:13:54 +00:00
< script src = "../_static/design-tabs.js?v=f930bc37" > < / script >
2026-02-27 21:12:00 +00:00
< script src = "../_static/js/fix-copy.js?v=2f5cab98" > < / script >
2025-10-22 21:13:54 +00:00
< / body >
< / html >