Skip to content

fix(translation): map anthropic metadata.user_id to Chat user - #553

Open
bgrins wants to merge 1 commit into
NVIDIA-NeMo:mainfrom
bgrins:fix/anthropic-metadata-to-chat-user
Open

fix(translation): map anthropic metadata.user_id to Chat user#553
bgrins wants to merge 1 commit into
NVIDIA-NeMo:mainfrom
bgrins:fix/anthropic-metadata-to-chat-user

Conversation

@bgrins

@bgrins bgrins commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

What

Translates Anthropic metadata.user_id to Chat's user field in the openai_chat request codec instead of passing metadata through untouched. Anthropic metadata is a different shape than Chat metadata (a string map attached to stored completions), and some endpoints reject the unknown shape. Other metadata objects continue to pass through.

Why

Anthropic clients attach metadata.user_id to requests, so pointing one at certain Chat upstreams through Switchyard fails on the first call:

curl -s https://opencode.ai/zen/v1/chat/completions \
    -H "Authorization: Bearer $OPENCODE_API_KEY" -H "Content-Type: application/json" \
    -d '{"model":"big-pickle","max_tokens":16,
         "metadata":{"user_id":"user_abc123"},
         "messages":[{"role":"user","content":"hi"}]}'
{"error":{"type":"server_error","message":"Error from provider (Console): Upstream request failed: [1210] Invalid API parameter, please check the documentation."}}

How tested

  • uv run ruff check . clean
  • uv run mypy switchyard clean
  • uv run pytest tests/ green
  • cargo fmt --all --check clean; cargo clippy -p switchyard-translation --all-targets -- -D warnings clean
  • cargo test -p switchyard-translation green — 145 tests
  • Manual smoke: the failing curl above, re-sent as the translated shape ("user":"user_abc123", no metadata), returns a completion from big-pickle. Have also tested long Claude Agent SDK -> Switchyard -> opencode sessions on a wheel built from this branch (without the fix every session dies on its first request).

Checklist

  • One class per file; filename = snake_case of the primary class. (Rust-only change)
  • New public symbols exported from switchyard/__init__.py.__all__ if intended for downstream use. (n/a)
  • Unit tests added for new components / bug fixes. (anthropic_openai_compatible_extensions_are_preserved_for_openai_chat now asserts the mapping)
  • README / --help updated if customer-facing surface changed. (n/a)
  • Commits signed off (Signed-off-by: Your Name <email>) per the DCO.

Notes for reviewers

user is set with or_insert, so an explicit user already on the request wins.

Summary by CodeRabbit

  • Bug Fixes
    • Improved translation of chat request metadata.
    • When metadata contains only a user ID, it is now correctly represented in the request’s user field.
    • Other metadata continues to be preserved as metadata.

Signed-off-by: Brian Grinstead <briangrinstead@gmail.com>
@bgrins
bgrins requested a review from a team as a code owner August 26, 2026 16:14
@coderabbitai

coderabbitai Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: b1713851-8278-42e7-8678-2c61f82f8bb9

📥 Commits

Reviewing files that changed from the base of the PR and between 21f6951 and db77ee5.

📒 Files selected for processing (2)
  • crates/switchyard-translation/src/codecs/openai_chat/buffered.rs
  • crates/switchyard-translation/tests/request_translation.rs

Included review availability: Your plan provides up to 12 included reviews per hour; 11 remain after this review.


Walkthrough

The OpenAI Chat request translator now maps metadata containing only user_id to the top-level user field. Other metadata remains under metadata. The request translation test verifies this behavior.

Changes

Metadata translation

Layer / File(s) Summary
Conditional metadata mapping
crates/switchyard-translation/src/codecs/openai_chat/buffered.rs
The translator emits user for metadata containing only user_id and preserves other metadata under metadata.
Translation test update
crates/switchyard-translation/tests/request_translation.rs
The test verifies user: "u123" and the absence of metadata.

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

Merge Risk: ⚪ Minimal · up to db77e

This localized metadata mapping preserves explicit user values and is covered by passing checks and tests; no actionable merge-blocking risk remains.

Poem

A rabbit checks the fields with care
user_id hops to user there
Other metadata stays in line
The test confirms the mapping fine
Clean requests now cross the sign

🚥 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%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 2 files. 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 clearly and concisely describes the main change: mapping Anthropic metadata.user_id to the OpenAI Chat user field.
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.
  • Fix all pre-merge checks with AI

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

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