Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions docs/filters/http/ai/openai_responses_rehydrate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!-- Generated by: cargo xtask generate-filter-docs -->
<!-- Do not edit manually -->

# `openai_responses_rehydrate`

Validates `previous_response_id` by fetching the stored response, confirming its status is `"completed"`, and populating `ResponsesState` with the full conversation history (stored turns + current input).

Requires Cargo feature: `ai-inference`.

## Configuration Notes

The request body is **not** modified; downstream filters read from `ResponsesState.messages` instead.

## Example

```yaml
filter: openai_responses_rehydrate
```
1 change: 1 addition & 0 deletions docs/filters/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Built-in filters organized by protocol and category.
| [`openai_response_store`](http/ai/openai_response_store.md) | `ai-inference` | Persists non-streaming Responses API responses to the configured response store backend. |
| [`openai_responses_format`](http/ai/openai_responses_format.md) | `ai-inference` | Classifies AI API request bodies and promotes routing facts to headers, metadata, and filter results without mutating the body. |
| [`openai_responses_model_rewrite`](http/ai/openai_responses_model_rewrite.md) | `ai-inference` | Rewrites the `model` field in Responses API request bodies. |
| [`openai_responses_rehydrate`](http/ai/openai_responses_rehydrate.md) | `ai-inference` | Validates `previous_response_id` by fetching the stored response, confirming its status is `"completed"`, and populating `ResponsesState` with the full conversation history (stored turns + current input). |
| [`openai_responses_validate`](http/ai/openai_responses_validate.md) | `ai-inference` | Validates and enriches Responses API requests. |
| [`prompt_enrich`](http/ai/prompt_enrich.md) | `ai-inference` | Injects statically configured messages into the `messages` array of OpenAI-compatible chat completion request bodies. |
| [`token_usage_headers`](http/ai/token_usage_headers.md) | - | Injects `Praxis-Token-Input`, `Praxis-Token-Output`, and `Praxis-Token-Total` headers into downstream responses when token usage data is present in [`filter_metadata`]. |
Expand Down
1 change: 1 addition & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ page.
| [format-routing.yaml](configs/ai/openai/responses/format-routing.yaml) | Routes AI API traffic by detected body format |
| [full-flow.yaml](configs/ai/openai/responses/full-flow.yaml) | Combines format classification, request validation, and backend routing into a single pipeline |
| [model-rewrite.yaml](configs/ai/openai/responses/model-rewrite.yaml) | Rewrites or injects the top-level `model` field in Responses API request bodies before forwarding to the inference backend |
| [rehydrate.yaml](configs/ai/openai/responses/rehydrate.yaml) | Validates `previous_response_id` by fetching the stored response, confirming its status is completed, and promoting the ID to filter metadata |
| [request-validate.yaml](configs/ai/openai/responses/request-validate.yaml) | Validates Responses API requests and rejects invalid parameter combinations |
| [response-store.yaml](configs/ai/openai/responses/response-store.yaml) | Persists non-streaming Responses API responses to a database and serves stored data via GET endpoints and handles DELETE /v1/responses/{id} locally |
| [responses-routing.yaml](configs/ai/openai/responses/responses-routing.yaml) | Routes Responses API traffic by detected mode |
Expand Down
18 changes: 12 additions & 6 deletions examples/configs/ai/openai/responses/full-flow.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,19 @@
# and conversation IDs, and writes responses.* metadata for
# downstream filters. Skips non-Responses requests gracefully.
#
# 3. The router sends all valid Responses API create requests to
# 3. openai_response_store persists non-streaming responses to
# SQLite and registers the store backend so downstream filters
# (rehydrate, compact) can read from it.
#
# 4. openai_responses_rehydrate loads conversation context from
# previous_response_id by fetching stored responses and
# prepending their message history to the current request.
# Passthrough for requests without previous_response_id.
#
# 5. The router sends all valid Responses API create requests to
# the same inference backend. The promoted mode remains available
# as headers/metadata for downstream filters; it does not change
# backend selection in this example. Once #354 orchestration
# filters land, stateful requests could use a separate filter
# chain with response_store, rehydrate, tool_parse, etc. before
# reaching the same inference backend.
# backend selection in this example.
#
# A request is stateful when any of these hold:
# - previous_response_id is set
Expand Down Expand Up @@ -75,8 +81,8 @@ filter_chains:
database_url: "sqlite://responses.db?mode=rwc"
responses_table: openai_responses
conversations_table: openai_conversations
- filter: openai_responses_rehydrate
# Future #354 orchestration filters would follow here:
# - filter: rehydrate
# - filter: compact
# - filter: tool_parse
# - filter: responses_proxy
Expand Down
63 changes: 63 additions & 0 deletions examples/configs/ai/openai/responses/rehydrate.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Rehydrate
#
# Validates `previous_response_id` by fetching the stored
# response, confirming its status is completed, and
# promoting the ID to filter metadata. Body construction
# from the resolved conversation is handled downstream by
# the `responses_proxy` filter.
#
# Pipeline ordering:
# 1. openai_responses_format — classifies body, promotes metadata
# 2. openai_responses_validate — validates parameters, generates IDs
# 3. openai_response_store — initializes store, registers in ctx
# 4. openai_responses_rehydrate — validates previous response, sets metadata
#
# The response_store filter must appear before openai_responses_rehydrate so its
# store backend is registered in `ctx.response_stores` during
# `on_request`.
#
# Example requests:
#
# # First turn (stored)
# curl -X POST http://localhost:8080/v1/responses \
# -H "Content-Type: application/json" \
# -d '{"model":"gpt-4.1","input":"Hello"}'
#
# # Second turn (rehydrated — uses previous_response_id)
# curl -X POST http://localhost:8080/v1/responses \
# -H "Content-Type: application/json" \
# -d '{"model":"gpt-4.1","input":"What next?","previous_response_id":"resp_abc"}'
#
# Requires the ai-inference feature:
# cargo build -p praxis --features ai-inference

listeners:
- name: ai-gateway
address: "127.0.0.1:8080"
filter_chains: [responses-pipeline]

filter_chains:
- name: responses-pipeline
filters:
- filter: openai_responses_format

- filter: openai_responses_validate

- filter: openai_response_store
backend: sqlite
database_url: "sqlite://responses.db?mode=rwc"
responses_table: openai_responses
conversations_table: openai_conversations

- filter: openai_responses_rehydrate

- filter: router
routes:
- path: "/v1/responses"
cluster: "inference-backend"

- filter: load_balancer
clusters:
- name: "inference-backend"
endpoints:
- "127.0.0.1:8000"
2 changes: 2 additions & 0 deletions filter/src/builtins/http/ai/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ pub use openai::ModelRewriteFilter;
#[cfg(feature = "ai-inference")]
pub use openai::OpenaiResponsesValidateFilter;
#[cfg(feature = "ai-inference")]
pub use openai::RehydrateFilter;
#[cfg(feature = "ai-inference")]
pub use openai::ResponseStoreFilter;
#[cfg(feature = "ai-inference")]
pub use openai::ResponsesFormatFilter;
Expand Down
2 changes: 2 additions & 0 deletions filter/src/builtins/http/ai/openai/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ pub(crate) mod responses;
pub use responses::ModelRewriteFilter;
#[cfg(feature = "ai-inference")]
pub use responses::OpenaiResponsesValidateFilter;
#[cfg(feature = "ai-inference")]
pub use responses::RehydrateFilter;
pub use responses::{ResponseStoreFilter, ResponsesFormatFilter};
4 changes: 4 additions & 0 deletions filter/src/builtins/http/ai/openai/responses/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -421,8 +421,12 @@ fn promote_boolean_results(
Ok(())
}

#[cfg(feature = "ai-inference")]
pub(crate) mod rehydrate;
#[cfg(feature = "ai-inference")]
pub(crate) mod validate;

#[cfg(feature = "ai-inference")]
pub use rehydrate::RehydrateFilter;
#[cfg(feature = "ai-inference")]
pub use validate::OpenaiResponsesValidateFilter;
Loading
Loading