ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Plano 开发指南:基于 Envoy 的 AI 原生代理数据面——架构、WASM 插件构建与 Provider 扩展实战

Plano 开发指南:基于 Envoy 的 AI 原生代理数据面——架构、WASM 插件构建与 Provider 扩展实战 Plano 开发指南基于 Envoy 的 AI 原生代理数据面——架构、WASM 插件构建与 Provider 扩展实战【免费下载链接】planoPlano is an AI-native proxy server and data plane for agentic apps. Smart LLM routing, observability, agent orchestration, and guardrails so you stay focused on your agents core logic.项目地址: https://gitcode.com/GitHub_Trending/ar/planoPlano 是一个构建在 Envoy proxy 之上的 AI 原生代理服务器proxy server与数据面data plane面向 Agentic 应用将智能 LLM 路由、可观测性、Agent 编排与安全护栏集中到进程外的数据面中。本篇指南以仓库根目录的 CLAUDE.md 为骨架系统讲解 Plano 的构建与测试命令、整体架构、WASM 插件开发约束、新增 LLM Provider 的完整流程以及版本发布与工程规范并结合crates/、cli/、config/中的真实源码逐层佐证。读完后你将能够独立完成 Plano 的构建、测试、插件扩展与 Provider 接入。一、项目定位进程外数据面的设计初衷Plano 的核心定位是Agentic 应用所需的横切能力LLM 路由、编排、可观测性、护栏不应该写死在 Agent 业务代码里而应该下沉到一个独立运行的代理数据面。这一点从仓库根目录的 CLAUDE.md 与 README.md 的项目描述中可以确认Plano is an AI-native proxy server and data plane for agentic applications, built on Envoy proxy. It centralizes agent orchestration, LLM routing, observability, and safety guardrails as an out-of-process dataplane.“out-of-process dataplane” 意味着 Agent 的流量首先进入 Plano运行中的 Envoy 实例由 Envoy 上的 WASM 过滤器完成提示词处理、护栏与 LLM 路由再由原生侧车进程 brightstaff 承担有状态的路由决策、信号分析、会话存储与链路追踪。这样Agent 团队可以专注于核心业务逻辑而不必重复实现这些基础设施能力。二、构建与测试命令全解CLAUDE.md 的 Build Test Commands 一节是仓库的标准开发入口下面逐条展开并结合源码说明每条命令的用途与适用场景。2.1 Rust——WASM 插件必须指定 wasm32-wasip1 目标cd crates cargo build --release --targetwasm32-wasip1 -p llm_gateway -p prompt_gatewayllm_gateway与prompt_gateway是两个会被加载进 Envoy WASM 沙箱的过滤器其 Crate 类型为cdylib产物是.wasm文件见 crates/llm_gateway/Cargo.toml 与 crates/prompt_gateway/Cargo.toml。之所以必须使用--targetwasm32-wasip1是因为 Proxy-WASM 规范基于 WASI Preview1 接口编译目标是独立的wasm32-wasip1而非宿主原生目标。从 crates/prompt_gateway/src/lib.rs 与 crates/llm_gateway/src/lib.rs 可以看到两者都通过proxy_wasm::main!宏注册根上下文并调用proxy_wasm::set_log_level(LogLevel::Trace)与proxy_wasm::set_root_context(|_| Box::new(FilterContext::new()))启动过滤器生命周期。2.2 Rust——brightstaff 原生二进制cd crates cargo build --release -p brightstaffbrightstaff是运行在原生目标上的核心服务状态、路由、信号、追踪编译目标为主机架构而非 WASM。其入口在 crates/brightstaff/src/main.rs监听地址为0.0.0.0:9091常量BIND_ADDRESS并注册了/v1/chat/completions、/v1/messages、OpenAI Responses API/v1/responses等路径以及routing_decision、agent_chat、function_calling_chat_handler等处理器从 crates/brightstaff/src/main.rs 的导入可见一斑。2.3 Rust——测试、格式化与 lintcd crates cargo test --lib cd crates cargo fmt --all -- --check cd crates cargo clippy --locked --all-targets --all-features -- -D warningscargo test --lib运行各 crate 的单元测试不要求 Docker 与外部 API Key适合日常开发循环。cargo clippy --locked --all-targets --all-features -- -D warnings是 CI 的硬性门槛任何 lint 警告都会被提升为错误保证合并前代码质量。单元测试示例可见 crates/brightstaff/src/handlers/integration_tests.rs、crates/brightstaff/src/router/stress_tests.rs 等文件。2.4 Python CLIcd cli uv sync uv run pytest -vCLI 使用uv管理依赖与虚拟环境测试套件位于 cli/test/覆盖配置生成、默认值、init、观测采集、定价渲染、trace命令与版本检查等模块见 cli/test/test_config_generator.py、cli/test/test_obs_collector.py 等。2.5 JS/TSTurbo 单体仓库npm run build npm run lint npm run typecheckapps/与packages/构成 Turbo monorepoNext.js 16 / React 19属于站点与 UI 层不属于核心代理CLAUDE.md 明确标注 Not part of the core proxy。2.6 Pre-commit 与 Dockerpre-commit run --all-files docker build -t katanemo/plano:latest .pre-commit一次性执行 fmt、clippy、cargo test、blackPython 格式化、yaml 校验等钩子。Dockerfile 位于仓库根目录配合 config/supervisord.conf 在容器内用 supervisord 同时拉起 config_generator、brightstaff 与 envoy 三个进程。注意E2E 测试需要 Docker 镜像与 API Key通过tests/e2e/run_e2e_tests.sh触发对应仓库路径 tests/e2e/run_e2e_tests.sh不属于默认开发循环。三、整体架构Envoy WASM 过滤器 原生侧车CLAUDE.md 用一段精简的 ASCII 图概括了运行时数据流Client → Envoy (prompt_gateway.wasm → llm_gateway.wasm) → Agents/LLM Providers ↕ brightstaff (native binary: state, routing, signals, tracing)展开来看一次 Agent 请求的生命周期是这样的Client将请求发送到 Envoy 的入口监听器ingress_traffic。prompt_gateway.wasmProxy-WASM 过滤器先处理提示词加载系统提示词、Prompt Target、Endpoint 与 Prompt Guards执行护栏与过滤链。llm_gateway.wasm处理 LLM 请求/响应与路由决策将流量转发给下游 Agents 或 LLM Providers。brightstaff原生二进制与 Envoy 双向通信承担有状态的路由routing_decision、会话状态存储、Agent 编排agent_chat、信号分析signals与链路追踪tracing。3.1 各 Crate 的职责边界crates/Crate类型职责prompt_gatewayWASMProxy-WASM 过滤器提示词处理、护栏、过滤链llm_gatewayWASMProxy-WASM 过滤器LLM 请求/响应处理与路由brightstaff原生核心服务器handlers、router、signals、state、tracingcommon库共享基础配置、HTTP、路由、限流、tokenizer、PII、tracinghermesllm库各 LLM Provider 间的请求/响应翻译关键类型ProviderId、ProviderRequest、ProviderResponse、ProviderStreamResponsecommon的共享能力从 crates/common/src/ 的模块布局可见configuration.rs配置解析、ratelimit.rs限流、tokenizer.rs分词、pii.rs敏感信息识别、llm_providers.rsProvider 能力建模等。hermesllm定义了ProviderId枚举与TryFromstr转换见 crates/hermesllm/src/providers/id.rs并维护各 Provider 的模型清单provider_models.yaml实际路径为 crates/hermesllm/src/bin/provider_models.yaml通过include_str!编译进二进制。3.2 Python CLIcli/planoai/入口为 cli/planoai/main.py基于rich-click构建命令包括up、down、build、logs、trace、init、cli_agent从 cli/planoai/main.py 的导入还能看到chatgpt与obs子命令以及默认的 OpenTelemetry gRPC 追踪端点等常量。CLI 还承担配置生成planoai.config_generator、Docker 编排docker_cli.py与本地原生模式启动core.py中的start_plano、start_cli_agent。3.3 配置体系config/文件作用plano_config_schema.yaml用户配置的 JSON Schema用于校验envoy.template.yamlJinja2 模板渲染为最终 Envoy 配置supervisord.conf进程管理器同时拉起 Envoy 与 brightstaff从 config/envoy.template.yaml 可以看到模板中的关键细节Admin 监听0.0.0.0:9901wasmcustom.time_to_first_token直方图桶从 100ms 到 180s 逐级配置当plano_tracing.random_sampling 0时启用 OpenTelemetry tracing provider 并注入service_name: plano(inbound)。而 config/supervisord.conf 定义了三个 programconfig_generator先生成配置并envsubst替换环境变量输出/tmp/config_ready就绪标记、brightstaff等待配置就绪后以RUST_LOG环境变量控制日志级别启动、envoy以渲染后的/etc/envoy.env_sub.yaml启动并设置--component-log-level wasm:控制 WASM 日志。3.4 JS Appsapps/、packages/apps/www官网与apps/katanemo-www等属于 Turbo monorepo 的前端站点层与核心代理数据面解耦本文不再展开。四、WASM 插件开发规则在 Envoy 沙箱里写 RustCLAUDE.md 专门用一节强调prompt_gateway与llm_gateway的代码运行在 Envoy 的 WASM 沙箱中因此有一系列硬性约束。这一节我们结合源码逐条验证。4.1 无 std 网络/文件系统只用 proxy-wasm 宿主调用WASM 沙箱内无法直接做 socket 或文件读写所有跨边界操作必须通过 Proxy-WASM 提供的宿主函数host call完成。例如 HTTP 外部调用走dispatch_http_call()配置读取走get_plugin_configuration()。4.2 无 tokio/async同步回调驱动沙箱内没有异步运行时逻辑是同步、回调驱动的。流控通过Action::Pause/Action::Continue表达暂停处理等待外部调用返回或继续放行。这意味着过滤器的状态机完全由 Envoy 的回调序列驱动。4.3 生命周期RootContext → HttpContext生命周期清晰固定RootContext::on_configure()在插件初始化时被调用一次负责解析配置RootContext::create_http_context()为每个 HTTP 流创建HttpContextHttpContext上的on_http_request_headers/body、on_http_response_headers/body处理请求/响应各个阶段。以 crates/prompt_gateway/src/filter_context.rs 的on_configure实现为例它通过self.get_plugin_configuration()拿到 Envoy 注入的插件配置字节流再用serde_yaml::from_slice::Configuration()反序列化随后把overrides、system_prompt、prompt_targets按名称建 HashMap、endpoints、prompt_guards、tracing分别存入结构体字段。配置解析失败会直接panic!(Invalid arch config ...)——在 WASM 沙箱里panic 会转化为插件加载失败以此快速暴露配置错误。4.4 HTTP 外部调用callouts 映射表外部调用如调用护栏服务、端点代理遵循固定模式dispatch_http_call()发起调用并返回一个 tokenu32过滤器把 token 与请求上下文存入callouts: RefCellHashMapu32, CallContext随后在on_http_call_response()回调里按 token 匹配并恢复上下文。这正是 crates/prompt_gateway/src/filter_context.rs 注释所描述的callouts stores token_id to request mapping that we use during #on_http_call_response to match the response to the request。common中的 crates/common/src/http.rs 抽象了这套Clienttrait提供callouts()与active_http_calls()仪表两个 gateway 分别实现该 trait。4.5 配置Rc 包装启动时一次性加载由于 WASM 上下文是单线程的配置用Rc包装而非Arc在on_configure()中加载一次后通过Rc::clone共享给每个流的StreamContext见 crates/prompt_gateway/src/filter_context.rs。llm_gateway的 crates/llm_gateway/src/filter_context.rs 结构类似。4.6 依赖必须 no_std 兼容凡是被 WASM 插件引用的第三方依赖都必须支持no_std。CLAUDE.md 给出的例子是限流库governor需启用features [no_std]——这也是 crates/common/src/ratelimit.rs 实现限流时能编译进 WASM 的前提。4.7 Crate 类型cdylib产出 .wasmprompt_gateway与llm_gateway的Cargo.toml中crate-type声明为cdylib因此cargo build --targetwasm32-wasip1的产物是可直接由 Envoyenvoy.filters.http.wasm加载的.wasm文件。五、添加一个新的 LLM Provider五步接入法CLAUDE.md 给出了一条清晰的 Provider 接入路径我们结合hermesllm源码逐条展开。第 1 步扩展 ProviderId 枚举在 crates/hermesllm/src/providers/id.rs 中添加新变体并实现TryFromstr字符串匹配统一小写化还支持别名例如google→Gemini、together→TogetherAI见 crates/hermesllm/src/providers/id.rs。这决定了用户配置里 provider 名称如何被解析。第 2 步创建请求/响应类型如果新 Provider 不是 OpenAI 兼容格式需要在 crates/hermesllm/src/apis/ 下新增对应 API 模块现有实现包括openai.rs、anthropic.rs、amazon_bedrock.rs、openai_responses.rs及流式缓冲模块streaming_shapes/。第 3 步扩展分发枚举并补齐 match 分支向ProviderRequestType/ProviderResponseType枚举添加新变体并更新所有 match 分支。分发的核心是ProviderRequest/ProviderResponsetrait 与这两个枚举的组合见 crates/hermesllm/src/providers/request.rs 与 crates/hermesllm/src/providers/response.rsRust 编译器会以穷尽性检查强制你更新所有分支这是接入过程最可靠的自检手段。第 4 步登记模型清单把新 Provider 支持的模型写入 crates/hermesllm/src/bin/provider_models.yaml注意实际路径是src/bin/下通过include_str!编译进二进制见 crates/hermesllm/src/providers/id.rs。该文件以providers: HashMapString, VecString的结构组织 Provider → 模型列表。第 5 步更新上游 API 映射如有必要更新SupportedUpstreamAPIs映射定义于 crates/hermesllm/src/clients/endpoints.rs确保新的 Provider 能正确路由到对应的上游端点。六、版本发布流程CLAUDE.md 规定版本号例如0.4.11→0.4.12必须同步更新在以下文件中.github/workflows/ci.yml、build_filter_image.sh、config/validate_plano_config.shcli/planoai/__init__.py、cli/planoai/consts.py、cli/pyproject.tomldocs/source/conf.py、docs/source/get_started/quickstart.rst、docs/source/resources/deployment.rstapps/www/src/components/Hero.tsx、demos/llm_routing/preference_based_routing/README.md同时有两条硬性规定不要改动*.lock文件或Cargo.lock中的版本字符串uv.lock、package-lock.json、bun.lock、Cargo.lock均属此列。提交信息固定为release X.Y.Z。这条规范的价值在于CLI 版本、Docker 镜像标签、文档版本号、官网展示版本与 demo 说明全部同源避免出现CLI 显示 0.4.12 而文档还是 0.4.11的漂移。从 cli/planoai/versioning.py 的实现可以看出 CLI 自身会执行版本检查版本一致性直接影响到运行时行为。七、工程规范与协作约定7.1 工作流偏好提交Commits不允许Co-Authored-By尾注单行简短信息禁止直接 push 到main一律特性分支 PR。分支Branches采用adil/feature_name命名格式。Issue 处理粘贴 GitHub Issue 链接时先抓取全部上下文目标始终是带通过测试的 PR。7.2 关键约定Rust 使用 edition 2021格式化走cargo fmt静态检查要求cargo clippy -D warningslint 警告视为错误。Python 使用 Black 格式化Rust 错误处理使用thiserror与#[from]自动生成 From 转换错误传播更简洁。API Key 一律来自环境变量或.env绝不硬编码。Provider 分发统一走ProviderRequestType/ProviderResponseType枚举实现ProviderRequest/ProviderResponsetrait 的模式。八、开发者快速上手路径综合以上内容一个新开发者进入仓库的推荐路径是阅读 CLAUDE.md 与 README.md 理解定位用cd crates cargo build --release --targetwasm32-wasip1 -p llm_gateway -p prompt_gateway构建两个 WASM 过滤器再用cargo build --release -p brightstaff构建原生侧车通过cd cli uv sync uv run pytest -v跑通 CLI 测试用cd cli uv run planoai init生成初始配置对应 cli/planoai/init_cmd.py 的init命令对照 config/plano_config_schema.yaml 与 config/envoy.template.yaml 理解配置如何驱动 Envoy 与 WASM 过滤器如需扩展 Provider严格按第五节五步流程操作用编译器的穷尽性检查兜底提交前跑cargo fmt --all -- --check、cargo clippy --locked --all-targets --all-features -- -D warnings与pre-commit run --all-files。至此你已掌握 Plano 从构建、架构理解到二次开发WASM 插件与 Provider 扩展的完整链路可以基于这套进程外数据面模式把 LLM 路由、编排与护栏从 Agent 业务代码中剥离出来。【免费下载链接】planoPlano is an AI-native proxy server and data plane for agentic apps. Smart LLM routing, observability, agent orchestration, and guardrails so you stay focused on your agents core logic.项目地址: https://gitcode.com/GitHub_Trending/ar/plano创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表