Skip to content

refactor(translation): use Dynamo Responses request schema#57

Closed
nachiketb-nvidia wants to merge 1 commit into
mainfrom
nachiketb/use-dynamo-protocols-translation
Closed

refactor(translation): use Dynamo Responses request schema#57
nachiketb-nvidia wants to merge 1 commit into
mainfrom
nachiketb/use-dynamo-protocols-translation

Conversation

@nachiketb-nvidia

@nachiketb-nvidia nachiketb-nvidia commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

What

  • Adds dynamo-protocols to the Rust translation crate.
  • Uses Dynamo types::responses::CreateResponse as the typed decode boundary for OpenAI Responses requests.
  • Keeps the existing Switchyard IR leaf decoders for input items, tools, tool choice, text format, and reasoning after Dynamo has parsed/defaulted the provider request shape.
  • Leaves OpenAI Chat and Anthropic codecs on their existing raw JSON paths; Dynamo is only used where it owns relaxed Responses request semantics.
  • Adds coverage for Anthropic/LiteLLM-style Responses tool_choice object modes surviving translation to OpenAI Chat.

Why

The earlier approach made Dynamo look like a generic provider-schema preprocessor. That added ceremony without removing provider-specific logic.

The useful boundary is narrower: Dynamo already carries the Responses API request schema and its real-world compatibility fixes, including object-form tool-choice modes and relaxed Responses input parsing. Switchyard should reuse that schema at the request boundary, then keep its current IR conversion logic rather than duplicate Dynamo or async-openai internals.

How

  • OpenAiResponsesCodec::decode_request first tries serde_json::from_value(...).
  • If Dynamo accepts the request, the codec reads the top-level typed fields directly and serializes only typed subfields into the existing, tested leaf decoders.
  • If Dynamo rejects the body, the codec falls back to the previous raw JSON decode path unchanged.
  • The broad provider_types shim from the earlier draft was removed; Chat/Anthropic are not routed through Dynamo.

What to review

  • Whether the Responses-only boundary is the right scope for introducing dynamo-protocols.
  • Whether the raw fallback is acceptable for legacy/odd payloads Dynamo rejects.
  • Whether the new tool_choice test captures the intended compatibility bug without overfitting.
  • Cargo dependency/lockfile impact from pulling in dynamo-protocols.

Tested

  • cargo test -p switchyard-translation
  • cargo fmt --all --check
  • cargo clippy --workspace --all-targets -- -D warnings
  • cargo test --workspace

@nachiketb-nvidia nachiketb-nvidia requested a review from a team as a code owner July 13, 2026 20:19
@nachiketb-nvidia nachiketb-nvidia force-pushed the nachiketb/use-dynamo-protocols-translation branch from e242703 to 90c1e74 Compare July 13, 2026 20:23
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Changes

Typed Provider Decoding

Layer / File(s) Summary
Provider schema foundation
crates/switchyard-translation/Cargo.toml, crates/switchyard-translation/src/lib.rs, crates/switchyard-translation/src/provider_types.rs
Adds the Dynamo protocols dependency, exposes provider_types, re-exports provider schemas, and provides lenient JSON encode/decode helpers.
Anthropic schema decoding
crates/switchyard-translation/src/codecs/anthropic/buffered.rs
Anthropic request and response decoding prefers typed schema fields while retaining raw JSON fallbacks.
OpenAI Chat schema decoding
crates/switchyard-translation/src/codecs/openai_chat/buffered.rs, crates/switchyard-translation/tests/request_translation.rs
OpenAI Chat decoding uses typed request and response fields, computes output limits, and tests object-shaped tool-choice translation.
OpenAI Responses schema decoding
crates/switchyard-translation/src/codecs/responses/buffered.rs
OpenAI Responses decoding uses typed input, output, tools, tool choice, metadata, and usage fields with fallback behavior.

Estimated code review effort: 4 (Complex) | ~45 minutes

Poem

I’m a rabbit with schemas tucked under my feet,
Typed fields hop forward, fallbacks keep beat.
Anthropic, Chat, Responses align,
Tools and tokens now travel fine.
Ears up high—tests pass in a line!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is related to the refactor, though it understates the broader schema-based translation changes across multiple codecs.

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
crates/switchyard-translation/src/codecs/openai_chat/buffered.rs (1)

460-466: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document the deprecated token-limit precedence.

Add a concise comment explaining why max_completion_tokens wins and why deprecated max_tokens remains supported.

As per coding guidelines, “Add concise comments/doc comments for public items and non-obvious helpers.”

🤖 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 `@crates/switchyard-translation/src/codecs/openai_chat/buffered.rs` around
lines 460 - 466, Add a concise comment above openai_chat_max_output_tokens
explaining that max_completion_tokens takes precedence while deprecated
max_tokens remains supported for backward compatibility. Keep the existing
fallback behavior unchanged.

Source: Coding guidelines

🤖 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 `@crates/switchyard-translation/src/codecs/anthropic/buffered.rs`:
- Around line 75-82: Read temperature and top_p directly from the raw body
instead of preferring decoded schema values, preserving precise JSON numbers as
f64. Apply this change in
crates/switchyard-translation/src/codecs/anthropic/buffered.rs lines 75-82,
crates/switchyard-translation/src/codecs/openai_chat/buffered.rs lines 69-76,
and crates/switchyard-translation/src/codecs/responses/buffered.rs lines 95-102;
update the corresponding request translation fields at each site and remove
schema-based fallbacks.

In `@crates/switchyard-translation/src/provider_types.rs`:
- Around line 10-25: Add concise /// doc comments to each public provider-type
re-export in provider_types.rs, including the OpenAI chat aliases, Anthropic
types, and OpenAI Responses aliases. Describe the exposed wire type and its
Switchyard-facing name without changing the re-exported symbols or behavior.
- Around line 32-45: Update the provider decoding flow around
maybe_decode_object() and field() so nested provider JSON retains the original
raw Value alongside the typed view, or configure the provider structs to
preserve unknown fields. Ensure field lookup does not replace raw messages,
content, tools, or input data with normalized typed serialization, and add a
regression test covering extra keys at those nested levels.

---

Nitpick comments:
In `@crates/switchyard-translation/src/codecs/openai_chat/buffered.rs`:
- Around line 460-466: Add a concise comment above openai_chat_max_output_tokens
explaining that max_completion_tokens takes precedence while deprecated
max_tokens remains supported for backward compatibility. Keep the existing
fallback behavior unchanged.
🪄 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: 2cd1c27e-e83a-4589-9ae2-67e7c8ba7e63

📥 Commits

Reviewing files that changed from the base of the PR and between a2a939d and e242703.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock, !Cargo.lock
📒 Files selected for processing (7)
  • crates/switchyard-translation/Cargo.toml
  • crates/switchyard-translation/src/codecs/anthropic/buffered.rs
  • crates/switchyard-translation/src/codecs/openai_chat/buffered.rs
  • crates/switchyard-translation/src/codecs/responses/buffered.rs
  • crates/switchyard-translation/src/lib.rs
  • crates/switchyard-translation/src/provider_types.rs
  • crates/switchyard-translation/tests/request_translation.rs

Comment on lines +75 to +82
temperature: schema
.as_ref()
.and_then(|request| request.temperature.map(f64::from))
.or_else(|| body.get("temperature").and_then(Value::as_f64)),
top_p: schema
.as_ref()
.and_then(|request| request.top_p.map(f64::from))
.or_else(|| body.get("top_p").and_then(Value::as_f64)),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n -C3 'temperature: Option<f32>|top_p: Option<f32>|struct SamplingParams' \
  crates/switchyard-translation Cargo.lock

Repository: NVIDIA-NeMo/Switchyard

Length of output: 722


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## outlines\n'
ast-grep outline crates/switchyard-translation/src/codecs/anthropic/buffered.rs --view expanded || true
ast-grep outline crates/switchyard-translation/src/codecs/openai_chat/buffered.rs --view expanded || true
ast-grep outline crates/switchyard-translation/src/codecs/responses/buffered.rs --view expanded || true
ast-grep outline crates/switchyard-translation/src/ir.rs --view expanded || true

printf '\n## relevant slices\n'
sed -n '1,220p' crates/switchyard-translation/src/codecs/anthropic/buffered.rs
printf '\n--- openai_chat ---\n'
sed -n '1,220p' crates/switchyard-translation/src/codecs/openai_chat/buffered.rs
printf '\n--- responses ---\n'
sed -n '1,240p' crates/switchyard-translation/src/codecs/responses/buffered.rs
printf '\n--- ir ---\n'
sed -n '180,215p' crates/switchyard-translation/src/ir.rs

Repository: NVIDIA-NeMo/Switchyard

Length of output: 38140


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## provider_types declarations\n'
rg -n -C3 'fn f64_field|fn field|struct OpenAiChatRequest|struct OpenAiResponsesRequest|struct AnthropicCreateMessageRequest|temperature|top_p' crates/switchyard-translation/src/provider_types.rs crates/switchyard-translation/src/provider_types -g '!**/target/**' || true

printf '\n## provider_types file slice\n'
sed -n '1,260p' crates/switchyard-translation/src/provider_types.rs

Repository: NVIDIA-NeMo/Switchyard

Length of output: 3605


🌐 Web query:

dynamo-protocols CreateChatCompletionRequest temperature top_p f32 OpenAiResponsesRequest OpenAI chat completions schema

💡 Result:

The dynamo-protocols crate (formerly dynamo-async-openai) provides request and response structures for OpenAI-compatible inference servers [1][2]. Within this schema, the CreateChatCompletionRequest structure includes the temperature and top_p fields, which are defined as Option types [3]. In the context of this API schema: - temperature: Defines the sampling temperature (a float between 0 and 2) used to control output randomness [3]. - top_p: Defines the nucleus sampling parameter (a float used to determine the cumulative probability mass for token consideration) [3]. The use of f32 for these parameters aligns with standard practices for representing single-precision floating-point numbers in Rust-based LLM protocol definitions to maintain compatibility with the underlying OpenAI API requirements while optimizing for memory and performance [3][4]. The library is designed as a protocol-schema crate that re-exports types from upstream sources (specifically async-openai) while introducing select extensions for specific inference engine needs [1][5].

Citations:


🌐 Web query:

AnthropicCreateMessageRequest temperature top_p Option<f32> dynamo-protocols

💡 Result:

AnthropicCreateMessageRequest is a Rust struct defined within the dynamo-protocols crate [1][2], which provides protocol type definitions for OpenAI-compatible and Anthropic-compatible inference APIs [2][3]. In the context of the dynamo-protocols library, AnthropicCreateMessageRequest represents the structure of requests sent to the Anthropic Messages API [1]. While the official Anthropic API supports temperature and top_p as floating-point parameters [4], the dynamo-protocols implementation specifically uses Option for these fields to accommodate their optional nature in the request body [1]. The dynamo-protocols crate (formerly dynamo-async-openai [5]) is designed to manage these types independently of upstream crates, allowing for custom inference-serving extensions [3][6]. As of the current development state in 2026, the crate has undergone significant refactoring to serve as a unified source for multi-protocol type definitions [1][5]. Developers working with this crate should ensure they are referencing the current types in dynamo_protocols::types::anthropic [1].

Citations:


🌐 Web query:

OpenAiResponsesRequest temperature top_p Option<f32> dynamo-protocols

💡 Result:

In technical contexts involving the OpenAiResponsesRequest structure, such as those found in the dynamo-protocols Rust crate [1][2] or similar OpenAI-compatible API implementations [3][4][5], the temperature and top_p fields are defined as optional parameters [3][4][6]. In Rust, these are typically represented using Option<f32> or Option<f64> to denote their optionality [3][4][6], allowing them to be omitted from the request body if not specified by the user. Key technical details include: 1. Dynamo-protocols: This Rust crate provides protocol type definitions for OpenAI-compatible inference APIs, including support for the Responses API [1][2]. It is built on async-openai with selective overrides for specific inference behaviors [2][7]. 2. Optionality: In implementations like new-api (Go) or various TypeScript provider definitions, these fields have been transitioned to optional (pointer types or ? optional modifiers) to ensure compatibility with requests that do not explicitly set sampling parameters [3][4][6]. 3. Usage: When constructing an OpenAiResponsesRequest, these fields allow the developer to pass None (or leave the field undefined in JSON), leaving the inference engine to use its default sampling settings [3][4][6]. If you are encountering this in a Rust codebase using dynamo-protocols or an agent-sdk-provider, the use of Option<f32> is the standard idiomatic way to handle these nullable/optional JSON fields [1][8].

Citations:


🌐 Web query:

docs.rs OpenAiResponsesRequest temperature top_p f32 dynamo-protocols create response struct

💡 Result:

The crate dynamo-protocols provides protocol type definitions for OpenAI-compatible inference APIs [1][2]. It is built on top of the async-openai crate (version 0.34) and re-exports many standard OpenAI types [1][3]. Regarding the request struct you mentioned, there is no single struct named OpenAiResponsesRequest in the dynamo-protocols crate [4]. The crate re-exports the OpenAI Responses API types from async-openai [1][3], where the relevant struct is named CreateResponse [5]. In async-openai's CreateResponse struct, the temperature and top_p fields are defined as Option [5]: pub struct CreateResponse { //... pub temperature: Option, pub top_p: Option, //... } If you are looking to create a request struct, you should use the types provided in dynamo-protocols::types [2][6]. For chat completions, for example, the crate uses CreateChatCompletionRequest [6][4], which mirrors the structure of the upstream async-openai type while incorporating local extensions like reasoning_content [1][3]. To use these types, you would typically import them from the dynamo_protocols::types module [6].

Citations:


Avoid routing temperature and top_p through the schema object

provider_types::f64_field prefers the decoded schema value, and these request types model both fields as f32, so precise JSON numbers can be rounded before they reach the IR's f64. Read these keys from the raw body here instead, in:

  • crates/switchyard-translation/src/codecs/anthropic/buffered.rs
  • crates/switchyard-translation/src/codecs/openai_chat/buffered.rs
  • crates/switchyard-translation/src/codecs/responses/buffered.rs
📍 Affects 3 files
  • crates/switchyard-translation/src/codecs/anthropic/buffered.rs#L75-L82 (this comment)
  • crates/switchyard-translation/src/codecs/openai_chat/buffered.rs#L69-L76
  • crates/switchyard-translation/src/codecs/responses/buffered.rs#L95-L102
🤖 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 `@crates/switchyard-translation/src/codecs/anthropic/buffered.rs` around lines
75 - 82, Read temperature and top_p directly from the raw body instead of
preferring decoded schema values, preserving precise JSON numbers as f64. Apply
this change in crates/switchyard-translation/src/codecs/anthropic/buffered.rs
lines 75-82, crates/switchyard-translation/src/codecs/openai_chat/buffered.rs
lines 69-76, and crates/switchyard-translation/src/codecs/responses/buffered.rs
lines 95-102; update the corresponding request translation fields at each site
and remove schema-based fallbacks.

Comment on lines +10 to +25
pub use dynamo_protocols::types::{
ChatCompletionRequestMessage as OpenAiChatRequestMessage,
ChatCompletionResponseMessage as OpenAiChatResponseMessage,
ChatCompletionTool as OpenAiChatTool, ChatCompletionToolChoiceOption as OpenAiChatToolChoice,
CreateChatCompletionRequest as OpenAiChatRequest,
CreateChatCompletionResponse as OpenAiChatResponse,
CreateChatCompletionStreamResponse as OpenAiChatStreamResponse,
};

pub use dynamo_protocols::types::anthropic::{
AnthropicCreateMessageRequest, AnthropicMessageResponse, AnthropicStreamEvent,
};

pub use dynamo_protocols::types::responses::{
CreateResponse as OpenAiResponsesRequest, Response as OpenAiResponsesResponse,
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Document the public provider-type re-exports.

Add concise /// documentation for the public aliases so their exposed wire types and Switchyard naming are clear in generated API docs.

As per coding guidelines, public items should have concise comments or doc comments.

🤖 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 `@crates/switchyard-translation/src/provider_types.rs` around lines 10 - 25,
Add concise /// doc comments to each public provider-type re-export in
provider_types.rs, including the OpenAI chat aliases, Anthropic types, and
OpenAI Responses aliases. Describe the exposed wire type and its
Switchyard-facing name without changing the re-exported symbols or behavior.

Source: Coding guidelines

Comment on lines +32 to +45
pub(crate) fn maybe_decode<T>(body: &Value) -> Option<T>
where
T: DeserializeOwned,
{
serde_json::from_value(body.clone()).ok()
}

/// Best-effort serialization used to feed existing IR mappers from provider
/// structs without making schema serialization itself a new failure mode.
pub(crate) fn maybe_encode<T>(value: &T) -> Option<Value>
where
T: Serialize,
{
serde_json::to_value(value).ok()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

set -euo pipefail

# Map the target file and nearby symbols
ast-grep outline crates/switchyard-translation/src/provider_types.rs --view expanded || true

echo '--- maybe_decode/maybe_encode usages ---'
rg -n "maybe_decode|maybe_encode|raw fallback|fallback" crates/switchyard-translation/src -S || true

echo '--- provider_types.rs with line numbers ---'
cat -n crates/switchyard-translation/src/provider_types.rs | sed -n '1,220p'

Repository: NVIDIA-NeMo/Switchyard

Length of output: 4810


🏁 Script executed:

set -euo pipefail

ast-grep outline crates/switchyard-translation/src/provider_types.rs --view expanded || true

echo '--- maybe_decode/maybe_encode usages ---'
rg -n "maybe_decode|maybe_encode|raw fallback|fallback" crates/switchyard-translation/src -S || true

echo '--- provider_types.rs with line numbers ---'
cat -n crates/switchyard-translation/src/provider_types.rs | sed -n '1,220p'

Repository: NVIDIA-NeMo/Switchyard

Length of output: 4810


🏁 Script executed:

set -euo pipefail

for file in \
  crates/switchyard-translation/src/codecs/openai_chat/buffered.rs \
  crates/switchyard-translation/src/codecs/anthropic/buffered.rs \
  crates/switchyard-translation/src/codecs/responses/buffered.rs
do
  echo "===== $file ====="
  # Show nearby regions around each maybe_decode_object call
  rg -n "maybe_decode_object|schema|raw" "$file" -n -S | head -n 80
  echo "--- snippets ---"
  # Print limited windows around the call sites
  while IFS=: read -r line _; do
    start=$((line-25))
    end=$((line+120))
    if [ "$start" -lt 1 ]; then start=1; fi
    sed -n "${start},${end}p" "$file" | cat -n | sed -n "1,180p"
    echo "----"
  done < <(rg -n "maybe_decode_object" "$file" -n -S)
done

Repository: NVIDIA-NeMo/Switchyard

Length of output: 2919


🏁 Script executed:

set -euo pipefail

for file in \
  crates/switchyard-translation/src/codecs/openai_chat/buffered.rs \
  crates/switchyard-translation/src/codecs/anthropic/buffered.rs \
  crates/switchyard-translation/src/codecs/responses/buffered.rs
do
  echo "===== $file ====="
  rg -n "maybe_decode_object" "$file" -S
  echo "--- around matches ---"
  while IFS=: read -r line _; do
    start=$((line-35))
    end=$((line+140))
    if [ "$start" -lt 1 ]; then start=1; fi
    echo ">>> lines ${start}-${end}"
    sed -n "${start},${end}p" "$file" | cat -n
    echo "----"
  done < <(rg -n "maybe_decode_object" "$file" -S)
done

Repository: NVIDIA-NeMo/Switchyard

Length of output: 490


🏁 Script executed:

set -euo pipefail

for file in \
  crates/switchyard-translation/src/codecs/openai_chat/buffered.rs \
  crates/switchyard-translation/src/codecs/anthropic/buffered.rs \
  crates/switchyard-translation/src/codecs/responses/buffered.rs
do
  echo "===== $file ====="
  rg -n "maybe_decode_object" "$file" -S
  while IFS=: read -r line _; do
    start=$((line-30))
    end=$((line+110))
    [ "$start" -lt 1 ] && start=1
    echo "--- lines ${start}-${end} ---"
    sed -n "${start},${end}p" "$file" | cat -n
  done < <(rg -n "maybe_decode_object" "$file" -S)
done

Repository: NVIDIA-NeMo/Switchyard

Length of output: 467


🏁 Script executed:

set -euo pipefail

# Inspect the exact mapping code around the schema/raw usage
sed -n '1,220p' crates/switchyard-translation/src/codecs/openai_chat/buffered.rs | cat -n | sed -n '1,220p'
echo '---'
sed -n '220,340p' crates/switchyard-translation/src/codecs/openai_chat/buffered.rs | cat -n | sed -n '1,180p'
echo '---'
sed -n '1,320p' crates/switchyard-translation/src/codecs/anthropic/buffered.rs | cat -n | sed -n '1,320p'
echo '---'
sed -n '1,260p' crates/switchyard-translation/src/codecs/responses/buffered.rs | cat -n | sed -n '1,260p'

echo '--- search for serde unknown-field retention in local source ---'
rg -n "flatten|deny_unknown_fields|extra|unknown fields|preserve" crates -S || true

Repository: NVIDIA-NeMo/Switchyard

Length of output: 50378


🏁 Script executed:

set -euo pipefail

echo '--- openai_chat request path ---'
sed -n '30,180p' crates/switchyard-translation/src/codecs/openai_chat/buffered.rs | cat -n

echo '--- openai_chat response path ---'
sed -n '240,340p' crates/switchyard-translation/src/codecs/openai_chat/buffered.rs | cat -n

echo '--- anthropic path ---'
sed -n '30,320p' crates/switchyard-translation/src/codecs/anthropic/buffered.rs | cat -n

echo '--- responses path ---'
sed -n '30,260p' crates/switchyard-translation/src/codecs/responses/buffered.rs | cat -n

echo '--- serde attrs in workspace source ---'
rg -n "deny_unknown_fields|flatten" crates -S || true

Repository: NVIDIA-NeMo/Switchyard

Length of output: 39688


Don't normalize nested provider JSON here. maybe_decode_object() round-trips through serde and field() prefers that map over raw, so unknown keys inside messages/content/tools/input disappear once the typed subtree is used. Keep the original nested Value alongside the typed view, or make the provider structs retain unknown fields, and add a regression test with extra nested keys.

🤖 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 `@crates/switchyard-translation/src/provider_types.rs` around lines 32 - 45,
Update the provider decoding flow around maybe_decode_object() and field() so
nested provider JSON retains the original raw Value alongside the typed view, or
configure the provider structs to preserve unknown fields. Ensure field lookup
does not replace raw messages, content, tools, or input data with normalized
typed serialization, and add a regression test covering extra keys at those
nested levels.

@nachiketb-nvidia nachiketb-nvidia marked this pull request as draft July 13, 2026 20:27
@nachiketb-nvidia nachiketb-nvidia force-pushed the nachiketb/use-dynamo-protocols-translation branch from 90c1e74 to 34f019c Compare July 13, 2026 20:35
@nachiketb-nvidia nachiketb-nvidia changed the title refactor(translation): use Dynamo protocol schemas refactor(translation): use Dynamo Responses request schema Jul 13, 2026
@nachiketb-nvidia nachiketb-nvidia deleted the nachiketb/use-dynamo-protocols-translation branch July 13, 2026 20:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant