Releases: praxis-proxy/ai
Release list
v0.3.0
Highlights
- 🔑 License migrated from MIT to Apache-2.0 (#848)
- 🔐 New upstream authentication filters: Azure AD (#815), GCP ADC — experimental (#828), and AWS SigV4 request signing (#802)
- ⚖️ Routing: provider load balancing (#731) and a secure provider gateway boundary (#386)
- 🧩 Extensibility:
http_calloutfilter (#760); llm-dext_proccompatibility moved into AI (#334) - 📊 Observability: OpenTelemetry routing spans (#729) and provider backend route tracing (#834)
Features
- feat(routing): add provider load balancing (#731) — @nerdalert
- feat(routing): add secure provider gateway boundary (#386) — @nerdalert
- feat(token_rate_limit): sliding-window / token-bucket rate limiting (#796) — @jordigilh
- feat(azure): add
azure_adupstream authentication filter (#815) — @szedan-rh - feat: add experimental
gcp_adcupstream authentication filter (#828) — @szedan-rh - aws: add
aws_sigv4_signfilter for signing upstream AWS requests (#802) — @szedan-rh - feat(callout): add
http_calloutfilter — supersedes #727 (#760) — @usize - feat(llm-d): move
ext_proccompatibility into AI (#334) — @nerdalert - feat(filters): add OpenTelemetry routing spans (#729) — @nerdalert
- feat(observability): trace provider backend routes (#834) — @nerdalert
- feat(openai): generalize the operation registry and matcher (#772) — @cdoern
- feat(token-count): report prompt cache token breakdown (#582) — @noyitz
- feat(file_search): full-flow-agentic example with IRR file search callout (#737) — @leseb
Security
- fix(web_search): validate
base_urlagainst SSRF and credential disclosure (#851) — @leseb - fix(mcp_tool_resolve): strip credentials and honor
tool_choiceon empty resolve (#852) — @leseb - fix(a2a): defer route commit until EOS to prevent prefix-poisoning (#733) — @mkoushni
- fix(a2a): reject oversized task-routing TTLs before
Instantoverflow (#823) — @mkoushni - fix(deps): update
h2for security audit (#764) — @nerdalert
Bug Fixes
- fix(web_search): don't forward hosted
web_search_callto inference backend (#853) — @leseb - fix(token_count): add OpenAI Responses API usage extraction (#714) — @yossiovadia
- fix(token_count): preserve OpenAI Responses cache writes and parse once (#858) — @leseb
- fix(token_usage): recover from SSE overflow instead of silently dropping usage (#782) — @mkoushni
- fix(mcp_dispatch): preserve non-text MCP result content (#807) (#850) — @leseb
- fix(mcp): bound dynamic session and protocol values (#655) — @skamenan7
- fix(subrequest): honor
runtime.subrequest_circuit_breakeron the shared client (#830) — @mkoushni - fix(azure_ad): schedule token refresh within skewed validity window (#829) — @szedan-rh
- fix(responses): support the
includequery parameter on store retrieval (#822) — @r-papso - fix(responses): disable parallel tools on first inference (#711) — @skamenan7
- fix(conversations): percent-decode conversation ID path segments (#824) — @mkoushni
- fix(conversations): align create and update request contracts (#625) — @leseb
- fix(guardrails): align NeMo status with
/v1/guardrail/checksendpoint (#792) — @liavweiss - fix(openai): preserve non-2xx OGX responses in file resolution (#799) — @skamenan7
Refactors
- refactor(responses): centralize usage accumulation (#702) — @rkaplan-hub
- refactor(filters): rename
agentic_looptoopenai_agentic_loop(#748) — @leseb
Praxis core compatibility
- fix(compat): align AI with Praxis main body and branch routing (#787) — @nerdalert
- fix: keep Praxis main compatibility fixtures current (#757) — @nerdalert
- fix: adapt to
praxis-proxy-filter0.5.3 API changes - chore(deps): switch Praxis crates from git tags to crates.io (#725) — @leseb
Tests & CI
- test(integration): cover IRR delivery of agentic-loop 400/508 rejections (#847) — @leseb
- Document and test provider fallback via the Iterative Request Router (#730) — @usize
- test: opt loopback fixtures into
allow_private_endpoints(#800) — @usize - fix(test): init new praxis-main context fields (#816) — @aslakknutsen
- ci(store): add PostgreSQL CI coverage for the response store (#739) — @leseb
- ci: add job timeouts, persist-credentials, and CodeQL on PRs / merge queue
Docs & Governance
- chore(license): complete migration from MIT to Apache-2.0 (#848) — @leseb
- docs: add attribution rules; correct architecture Key Files paths; fix stale version/image/module references
- docs: migrate proposals to the centralized enhancements repo; update governance docs
Dependencies
- chore(deps): bump
rust1.97-alpine → 1.98-alpine (#817) - chore(deps): update Cargo.lock dependencies (#738) — @leseb
- chore(deps): routine dependabot bumps (codeql-action #819/#820/#776/#777, setup-buildx #818, setup-uv #775) and
cargo upgraderefreshes
Reverts
- Revert "fix(guardrails): fail closed on NeMo redact verdict until body replacement" (#821, reverting #721) — @szedan-rh
New Contributors
- @noyitz, @rkaplan-hub, @yossiovadia, @liavweiss, @jordigilh, @szedan-rh, and @r-papso made their first contributions in this release 🎉
Full Changelog: https://github.com/praxis-proxy/ai/commits/v0.3.0
v0.2.0
Features
Agentic & MCP
- feat(filter): add agentic_loop controller for Responses API by @leseb in #623
- feat(mcp): route stateless tools/call through static broker catalog by @nerdalert in #340
- feat(mcp_tool_resolve): resolve MCP servers concurrently by @leseb in #575
- feat(openai): resolve connector_id through configured MCP connectors by @leseb in #704
- feat(web_search): wire openai_web_search into IRR agentic loop by @leseb in #635
OpenAI API
- feat(openai): support finite chat continuations by @franciscojavierarceo in #728
- feat(openai): add Responses-to-Chat Completions filter by @franciscojavierarceo in #644
- feat(openai): add file_search_callout filter for hosted vector store search by @leseb in #493
- feat(openai): route /v1/embeddings to a dedicated Embeddings API backend by @leseb in #490
- Support OpenAI Responses WebSocket passthrough by @franciscojavierarceo in #474
- feat: OpenAI Conversations conformance suite by @leseb in #531
Anthropic API
- feat(anthropic): add Messages web search loop by @franciscojavierarceo in #647
Inference & Routing
- feat(filters): add intelligent_route by @nerdalert in #339
- feat(routing): hot reload intelligent routing overlays by @nerdalert in #540
- feat(compact): automatic compaction via context_management (#598) by @crstrn13 in #403
Guardrails & Observability
- feat(guardrails): add NeMo Provider by @christinaexyou in #285
- feat(filters): add time_to_first_token filter for TTFT metrics by @eoinfennessy in #587
Store
- feat(store): add schema validation and version tracking at init by @leseb in #631
- feat(store): expose connection pool tuning options by @leseb in #632
- feat(store): validate query params on GET /v1/responses/{id} by @leseb in #687
Server & Internals
- feat(server): wire SubRequestClient into pipeline resolution by @leseb in #622
- feat(filters): export AI filter registration API by @aslakknutsen in #612
- feat(file_resolve): resolve file_url references with SSRF protection by @leseb in #460
Bug Fixes
OpenAI / Responses
- fix(openai_responses): enforce max_body_bytes after MCP tool expansion by @leseb in #690
- fix(openai_responses): place web-search sources inside action object by @leseb in #686
- fix(openai_responses): avoid double-encoding MCP approval arguments by @leseb in #688
- fix(openai_responses): make input_items pagination usable for ID-less input arrays by @mkoushni in #619
- fix(openai_mcp_tool_resolve): rewrite type:mcp tools to type:function by @leseb in #488
- fix(classifier): treat POST /v1/responses as authoritative for no-discriminator bodies by @cdoern in #594
- fix(openai_conversations): stream by default, buffer only matched routes by @leseb in #615
- fix: reject invalid query params in conversation item listing by @leseb in #689
- fix(validate): remove obsolete background parameter rejections by @leseb in #535
- fix: oversized model values by @harrisonstropkay in #645
MCP
- fix(mcp): align stateless profile with final 2026 spec by @nerdalert in #614
- fix(mcp_tool_resolve): reject duplicate server_label before callout by @leseb in #580
- fix(mcp_dispatch): match tool calls by encoded function name by @leseb in #579
- fix(mcp_client): redact credentials from CallTool error messages by @leseb in #578
Store & Security
- fix(store): default PostgreSQL connections to verify-full TLS by @leseb in #576
- fix(store): fail closed when response store is unavailable by @leseb in #588
- fix(store): reject invalid input_items query parameters by @leseb in #616
- fix(postgres_url): unify SSRF validation with shared is_non_public_ip policy by @leseb in #617
Other
- fix(server): use AI-branded default config instead of core's by @leseb in #537
- fix(server): thread shared SubRequestClient into filter construction by @leseb in #634
- fix(file_resolve): reject file_url failures regardless of on_missing by @mkoushni in #620
- fix(filters): remove redundant Content-Length updates from body-mutating filters by @leseb in #609
- fix(filter): reject unknown fields in no-config filters by @eoinfennessy in #602
- fix: emit schema-complete Anthropic responses by @franciscojavierarceo in #618
- fix(conversations): honor include projections by @leseb in #574
- Fix/external filter discovery 478 by @mkoushni in #592
Refactors
- refactor(apis): replace CalloutClient with Pingora-native SubRequest by @leseb in #599
- refactor(subrequest): delegate execution to praxis-core SubRequestClient by @leseb in #610
- refactor(token_usage): move token usage module from apis to filters by @leseb in #536
- refactor(validate): make openai_responses_validate request-only by @leseb in #621
- Json body mutation helper by @usize in #624
Testing & CI
- test(inference): add Rust-native recording and replay fixtures by @franciscojavierarceo in #653
- test(mcp_dispatch): add resolve-to-dispatch roundtrip tests by @leseb in #589
- feat(ci): add OGX file_id integration tests to vLLM workflow by @leseb in #491
- ci: migrate workflows to conventions shared actions
- ci: validate GitHub Actions workflows by @leseb in #563
- build: enforce dependency hygiene by @leseb in #571
Dependencies
New Contributors
- @eoinfennessy made their first contribution in #602
- @christinaexyou made their first contribution in #285
- @usize made their first contribution in #624
- @shaneutt made their first contribution in #648
- @harrisonstropkay made their first contribution in #645
- @cdoern made their first contribution in #594
Full Changelog: v0.1.0...v0.2.0
v0.1.0
Praxis AI v0.1.0
The first release of Praxis AI — AI features and capabilities for Praxis.
Praxis AI extends the Praxis proxy framework with AI-specific filters for inference routing, provider APIs, agentic protocols, token counting, guardrails, response storage, and prompt enrichment.
Highlights
OpenAI Responses API (partial)
Proxy foundation for the OpenAI Responses API: request classification, validation, model rewrite, response storage (SQLite/PostgreSQL), conversation rehydration, streaming SSE accumulation, and conversation management endpoints and vLLM backend compatibility (including input_file document conversion). The full agentic loop (tool call detection → tool execution → re-inference) is not yet implemented.
Anthropic Messages API
Request classification, protocol normalization, streaming SSE translation between OpenAI and Anthropic formats, request body translation, and validation.
Agentic Protocols
- MCP (Model Context Protocol): broker with tool discovery, tool resolution, and tool dispatch via the filter pipeline
- A2A (Agent-to-Agent): task routing with context-based ownership and SSE support
AI Inference Routing
Model-based routing via header promotion, per-cluster credential injection, and prompt enrichment at the proxy layer.
Web Search
Model-driven web search dispatch with pluggable providers (OpenAI built-in, You.com).
Security & Observability
- AI guardrails filter for external content safety evaluation (NeMo)
- Token usage header injection across multiple providers (OpenAI, Anthropic, Bedrock)
- MCP metadata endpoint blocking and credential redaction
API Routing
Dedicated backend routing for /v1/files, /v1/prompts, and /v1/vector_stores endpoints.
Not Yet Supported
- Agentic loop orchestration (tool call → execute → re-inference loop)
- Responses API file inputs resolution
- Provider abstraction / unified types
- Multi-tenancy
- Mixture-of-models / intelligent routing
- Multi-provider guardrails
- llm-d integration
See the Responses API & Agentic Loop epic for the full roadmap.
What's Changed
Dependencies
- chore(deps): bump actions/cache from 6.0.0 to 6.1.0 by @dependabot[bot] in #222
- chore(deps): bump docker/build-push-action from 7.2.0 to 7.3.0 by @dependabot[bot] in #223
- chore(deps): bump actions/github-script from 7.0.1 to 9.0.0 by @dependabot[bot] in #306
- chore(deps): bump jsonwebtoken from 9.3.1 to 10.4.0 in the rust-dependencies group by @dependabot[bot] in #307
- chore(deps): bump github/codeql-action/analyze from 4.36.2 to 4.36.3 by @dependabot[bot] in #303
- chore(deps): bump docker/metadata-action from 6.1.0 to 6.2.0 by @dependabot[bot] in #304
- chore(deps): bump github/codeql-action/init from 4.36.2 to 4.36.3 by @dependabot[bot] in #305
- chore(deps): bump docker/login-action from 4.2.0 to 4.4.0 by @dependabot[bot] in #302
- chore(deps): bump github/codeql-action/analyze from 4.36.3 to 4.37.0 by @dependabot[bot] in #341
- chore(deps): bump github/codeql-action/init from 4.36.3 to 4.37.0 by @dependabot[bot] in #342
- chore(deps): bump the rust-dependencies group across 1 directory with 5 updates by @dependabot[bot] in #343
- chore(deps): bump actions/checkout from 7.0.0 to 7.0.1 by @dependabot[bot] in #465
- chore(deps): bump alpine from 3.23 to 3.24 by @dependabot[bot] in #467
- chore(deps): bump rust from 1.96-alpine to 1.97-alpine by @dependabot[bot] in #468
- chore(deps): bump github/codeql-action/init from 4.37.0 to 4.37.3 by @dependabot[bot] in #469
- chore(deps): bump astral-sh/setup-uv from 8.3.2 to 9.0.0 by @dependabot[bot] in #470
- chore(deps): bump github/codeql-action/analyze from 4.37.0 to 4.37.3 by @dependabot[bot] in #466
- chore(deps): bump the rust-dependencies group with 11 updates by @dependabot[bot] in #471
- chore(deps): bump Praxis crates to 0.4.1 by @nerdalert in #486
Other
- fix(build): print actual coverage percentage before failing gate by @leseb in #228
- docs(mcp): restore static catalog example by @nerdalert in #227
- fix(ai): map Anthropic max_tokens to OpenAI max_completion_tokens by @dimakis in #225
- fix(xtask): restore filter doc generation for AI repo by @leseb in #238
- chore: remove stale ai-inference feature flag by @leseb in #245
- SSE optimizations by @alexsnaps in #250
- fix: correct README links to point to ai repo by @leseb in #251
- test(store): add unit tests for SQLite backend and storage traits by @leseb in #237
- test: add unit tests for Response Store filter and config by @leseb in #236
- fix(apis): match OpenAI JSON field ordering in conversation responses by @leseb in #241
- refactor(headers): Do no clone when not needed, rely on laziness by @alexsnaps in #253
- ci(integration): add integration test workflow and enable test crates by @leseb in #244
- test(conversations): add unit tests for handlers, config, and filter by @leseb in #235
- test: add unit tests for chat_completions translation module by @leseb in #234
- lint(xtask): add separator width lint rule by @leseb in #256
- ci(coverage): bump line coverage threshold to 93% by @leseb in #255
- test(store): add scoping, pool, migration, and concurrency tests by @leseb in #254
- feat(filter): add streaming persistence support to response store by @leseb in #242
- feat(mcp): add configurable 2026-07-28 stateless profile by @nerdalert in #247
- feat(a2a): promote context IDs for classifier routing by @nerdalert in #226
- test(xtask): fix example lint assertion message by @nerdalert in #265
- ci: add unicode safety check for PR context poisoning by @aslakknutsen in #257
- refactor: remove ai-inference feature gate by @leseb in #259
- docs: fix stale local documentation links by @nerdalert in #264
- fix(apis): percent-decode SQLite path before traversal check in response-store by @leseb in #271
- fix: point issue template discussions link to ai repo by @leseb in #269
- fix(responses): case-insensitive SSE content-type detection by @leseb in #272
- ci: add aggregate CI status check for merge queue by @leseb in #258
- docs(a2a): add agent-card routing example by @nerdalert in #263
- refactor(apis): extract shared is_event_stream_content_type helper by @leseb in #274
- fix anthropic parallel tool call streaming by @franciscojavierarceo in #273
- chore(deps): update crossbeam-epoch 0.9.18 -> 0.9.20 (RUSTSEC-2026-0204) by @leseb in #290
- feat(filter): add openai_stream_events SSE accumulator filter by @leseb in #270
- docs(config): add openai_stream_events to full-flow example by @leseb in #293
- docs(filters): add missing openai_stream_events doc and CI lint by @leseb in #299
- fix(xtask): resolve praxis shared types from cargo registry in CI by @leseb in #308
- Add agent Rust data ownership guidance by @franciscojavierarceo in #295
- feat(conversations): rehydrate and append via conversation.id by @leseb in #248
- test(mcp): add unit tests for broker config validation by @leseb in #291
- test: replay sanitized agent sessions by @franciscojavierarceo in #289
- ci(fmt): include test crates in rustfmt checks by @nerdalert in #310
- test(a2a): add unit tests for envelope parsing by @leseb in #311
- feat(filter): add tool_parse filter for Responses API tool classification by @leseb in #309
- feat(apis): add Deserialize to TokenUsageProvider...