Skip to content

feat: support session IDs in request bodies#1137

Draft
ishandhanani wants to merge 1 commit into
ai-dynamo:mainfrom
ishandhanani:idhanani/dyn-3268-session-body
Draft

feat: support session IDs in request bodies#1137
ishandhanani wants to merge 1 commit into
ai-dynamo:mainfrom
ishandhanani:idhanani/dyn-3268-session-body

Conversation

@ishandhanani

@ishandhanani ishandhanani commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Exgentic replay added in #1064 carries each recorded session ID in x-dynamo-session-id, while SGLang's session-aware cache expects the same ID in the request body's top-level session_id field. This adds an opt-in --session-body-field that copies the resolved per-request session header value into a configured body field, avoiding a dataset-specific adapter.

What changed

  • Added --session-body-field and threaded it through endpoint configuration and generated docs/schema.
  • Copied the final resolved session header value into the configured body field immediately before HTTP serialization.
  • Documented the SGLang + Exgentic usage and added config/transport coverage.
flowchart LR
    A["Exgentic source session"] --> B["Resolved session header"]
    B --> C["x-dynamo-session-id header"]
    B --> D["session_id request field"]
Loading

Usage

aiperf profile ... \
  --session-header x-dynamo-session-id \
  --session-body-field session_id

Validation

  • Full unit suite: 14,454 passed, 96 skipped, 1 expected xfail.
  • pre-commit run --all-files: passed.
  • Live Exgentic fixed-schedule replay against SGLang session-aware HiCache: 9/9 HTTP 200, up to 2,668 cached prefix tokens, and closing the source session dereferenced 18 radix nodes.

Summary by CodeRabbit

  • New Features

    • Added support for copying a session identifier into a request body field during replay or request sending.
    • Introduced a new --session-body-field option in the CLI and corresponding configuration support.
  • Documentation

    • Updated the CLI and replay guides with examples for session-aware requests, including endpoints that require the session ID in the request body.
  • Bug Fixes

    • Requests now include the expected session value in both headers and the configured body field for supported endpoints.

Signed-off-by: Ishan Dhanani <ishandhanani@gmail.com>
@github-actions github-actions Bot added the feat label Jul 9, 2026
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

Try out this PR

Quick install:

pip install --upgrade --force-reinstall git+https://github.com/ai-dynamo/aiperf.git@63ee21b6ecf485df6de23b788c9aeca68c6b4b97

Recommended with virtual environment (using uv):

uv venv --python 3.12 && source .venv/bin/activate
uv pip install --upgrade --force-reinstall git+https://github.com/ai-dynamo/aiperf.git@63ee21b6ecf485df6de23b788c9aeca68c6b4b97

Last updated for commit: 63ee21bBrowse code

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Adds a new optional session_body_field configuration option across CLI flags, config schema, EndpointConfig/CLIConfig/EndpointInfo models, and endpoint field mapping. AioHttpTransport.send_request copies the resolved session header value into this request body field when configured. Documentation and unit tests are added accordingly.

Changes

Session Body Field Feature

Layer / File(s) Summary
Config and model field definitions
src/aiperf/config/endpoint.py, src/aiperf/config/flags/cli_config.py, src/aiperf/config/schema/aiperf-config.schema.json, src/aiperf/config/flags/_section_fields.py, src/aiperf/config/flags/_converter_endpoint.py, src/aiperf/common/models/model_endpoint_info.py
Adds session_body_field to EndpointConfig, CLIConfig (with --session-body-field CLI flag), JSON schema (sessionBodyField), ENDPOINT_FIELDS, endpoint field mapping, and EndpointInfo/from_run population.
Transport logic and tests
src/aiperf/transports/aiohttp_transport.py, tests/unit/config/test_converter_endpoint_session.py, tests/unit/transports/test_aiohttp_transport.py
send_request copies the resolved session header value into the configured body field before serialization; unit tests verify endpoint config conversion and body-field copy behavior.
Documentation updates
docs/cli-options.md, docs/benchmark-datasets.md
Documents the new --session-body-field option for both aiperf profile and aiperf service, and adds a replay note for SGLang-style endpoints.

Estimated code review effort: 2 (Simple) | ~15 minutes

Poem

A header hops, a field takes flight,
Session IDs copied just right,
From headers deep into the body's core,
SGLang and friends ask nothing more,
This bunny thumps in pure delight! 🐇✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: optional session IDs can now be written into request bodies during replay.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
tests/unit/config/test_converter_endpoint_session.py (1)

8-17: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Test name doesn't follow the test_<function>_<scenario>_<expected> convention.

test_session_affinity_fields_are_added_to_endpoint is descriptive but doesn't name the function under test (build_endpoint) or a clear expected outcome. Consider test_build_endpoint_session_fields_set_included_in_output.

As per path instructions, tests/**/*.{py,pyi}: "Name tests as test_<function>_<scenario>_<expected>."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/config/test_converter_endpoint_session.py` around lines 8 - 17,
Rename the test to follow the required `test_<function>_<scenario>_<expected>`
pattern by including the function under test and the outcome; update
`test_session_affinity_fields_are_added_to_endpoint` in the `build_endpoint`
test to a name like `test_build_endpoint_session_fields_included_in_output`,
keeping the assertions unchanged.

Source: Path instructions

tests/unit/transports/test_aiohttp_transport.py (1)

302-321: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider adding a negative-path test for a missing session header.

Once headers[session_header] in aiohttp_transport.py is guarded (see companion comment on that file), add a test where session_body_field is set but the configured session_header is absent from the outgoing headers, to lock in the non-crashing/skip behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/transports/test_aiohttp_transport.py` around lines 302 - 321, Add
a negative-path test alongside
test_send_request_copies_resolved_session_header_to_body in
test_aiohttp_transport.py to cover AioHttpTransport.send_request when
session_body_field is configured but the session_header key is missing from the
outgoing headers. Verify the request still succeeds without crashing and that
the body does not get a copied session field when the header is absent, matching
the guarded behavior in aiohttp_transport.py.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/aiperf/transports/aiohttp_transport.py`:
- Around line 322-328: The session-body injection in
aiohttp_transport.send_request currently does a direct headers[session_header]
lookup, which can raise KeyError and get swallowed by the broad exception
handling. Update the session_body_field block to use a safe header lookup with
an explicit fallback/diagnostic when
request_info.model_endpoint.endpoint.session_header (or default
X-Correlation-ID) is missing, and surface a clear error before payload
assignment. Keep the fix localized around send_request and the
session_header/session_body_field handling so misconfigured headers fail with a
useful message instead of silently breaking every request.

---

Nitpick comments:
In `@tests/unit/config/test_converter_endpoint_session.py`:
- Around line 8-17: Rename the test to follow the required
`test_<function>_<scenario>_<expected>` pattern by including the function under
test and the outcome; update
`test_session_affinity_fields_are_added_to_endpoint` in the `build_endpoint`
test to a name like `test_build_endpoint_session_fields_included_in_output`,
keeping the assertions unchanged.

In `@tests/unit/transports/test_aiohttp_transport.py`:
- Around line 302-321: Add a negative-path test alongside
test_send_request_copies_resolved_session_header_to_body in
test_aiohttp_transport.py to cover AioHttpTransport.send_request when
session_body_field is configured but the session_header key is missing from the
outgoing headers. Verify the request still succeeds without crashing and that
the body does not get a copied session field when the header is absent, matching
the guarded behavior in aiohttp_transport.py.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: f7a1c7ad-556a-4f0e-bee5-058fba2f83e6

📥 Commits

Reviewing files that changed from the base of the PR and between d41bd50 and 63ee21b.

📒 Files selected for processing (11)
  • docs/benchmark-datasets.md
  • docs/cli-options.md
  • src/aiperf/common/models/model_endpoint_info.py
  • src/aiperf/config/endpoint.py
  • src/aiperf/config/flags/_converter_endpoint.py
  • src/aiperf/config/flags/_section_fields.py
  • src/aiperf/config/flags/cli_config.py
  • src/aiperf/config/schema/aiperf-config.schema.json
  • src/aiperf/transports/aiohttp_transport.py
  • tests/unit/config/test_converter_endpoint_session.py
  • tests/unit/transports/test_aiohttp_transport.py

Comment on lines +322 to +328
session_body_field = request_info.model_endpoint.endpoint.session_body_field
if session_body_field:
session_header = (
request_info.model_endpoint.endpoint.session_header
or "X-Correlation-ID"
)
payload[session_body_field] = headers[session_header]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Guard the header lookup to avoid silent per-request failures.

headers[session_header] will raise KeyError whenever the configured (or default X-Correlation-ID) header isn't present in the built headers for a given request/turn. Because send_request's broad except Exception swallows this, a misconfigured --session-header/--session-body-field pair — or a turn missing the expected header — silently fails every request with an opaque error instead of a clear diagnostic.

🐛 Proposed fix using a safe lookup
-            session_body_field = request_info.model_endpoint.endpoint.session_body_field
-            if session_body_field:
-                session_header = (
-                    request_info.model_endpoint.endpoint.session_header
-                    or "X-Correlation-ID"
-                )
-                payload[session_body_field] = headers[session_header]
+            session_body_field = request_info.model_endpoint.endpoint.session_body_field
+            if session_body_field:
+                session_header = (
+                    request_info.model_endpoint.endpoint.session_header
+                    or "X-Correlation-ID"
+                )
+                session_value = headers.get(session_header)
+                if session_value is not None:
+                    payload[session_body_field] = session_value
+                else:
+                    self.warning(
+                        f"session_body_field={session_body_field!r} configured but "
+                        f"header {session_header!r} not found in request headers; "
+                        "skipping body-field passthrough for this request."
+                    )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
session_body_field = request_info.model_endpoint.endpoint.session_body_field
if session_body_field:
session_header = (
request_info.model_endpoint.endpoint.session_header
or "X-Correlation-ID"
)
payload[session_body_field] = headers[session_header]
session_body_field = request_info.model_endpoint.endpoint.session_body_field
if session_body_field:
session_header = (
request_info.model_endpoint.endpoint.session_header
or "X-Correlation-ID"
)
session_value = headers.get(session_header)
if session_value is not None:
payload[session_body_field] = session_value
else:
self.warning(
f"session_body_field={session_body_field!r} configured but "
f"header {session_header!r} not found in request headers; "
"skipping body-field passthrough for this request."
)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/aiperf/transports/aiohttp_transport.py` around lines 322 - 328, The
session-body injection in aiohttp_transport.send_request currently does a direct
headers[session_header] lookup, which can raise KeyError and get swallowed by
the broad exception handling. Update the session_body_field block to use a safe
header lookup with an explicit fallback/diagnostic when
request_info.model_endpoint.endpoint.session_header (or default
X-Correlation-ID) is missing, and surface a clear error before payload
assignment. Keep the fix localized around send_request and the
session_header/session_body_field handling so misconfigured headers fail with a
useful message instead of silently breaking every request.

@codecov

codecov Bot commented Jul 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant