fix(sdk): omit null/empty request fields so older instances accept them#2834
Merged
Merged
Conversation
The Python SDK's find/search/add_resource unconditionally attach optional
fields to their request bodies — `args` as an empty `{}` and
`tags`/`score_threshold`/`filter`/`context_type`/`session_id` as `null` — even
when the caller never set them. OpenViking kernels use
`model_config = ConfigDict(extra="forbid")` on these routes, so any instance
that predates a field rejects the whole request with
`body.<field>: Extra inputs are not permitted`. This breaks the SDK (and every
SDK consumer, e.g. vikingbot via `ov.AsyncHTTPClient`) against older instances:
`add_resource` fails on `body.args` against a pre-volcengine#2549 instance, and `find`
fails on `body.tags` against a strict pre-volcengine#2706 instance.
This is the SDK-side counterpart of volcengine#2799, which fixed the same anti-pattern in
the Rust CLI but left the Python SDK untouched.
- Add `_compact_request_body()` and apply it in find/search/add_resource: drop
null-valued keys and an empty `args` object before sending. Scoped to these
read/create routes only, where a missing optional field and an explicit null
are equivalent — not applied globally, since null may mean "clear" on a future
update/PATCH route. Mirrors the CLI's `compact_request_body`.
Tests: unit tests for `_compact_request_body` and for find/search/add_resource
omitting unset optional fields while keeping explicitly-provided ones.
ZaynJarvis
approved these changes
Jun 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
The Python SDK's
find/search/add_resourceunconditionally attach optional fields to their request bodies —argsas an empty{}andtags/score_threshold/filter/context_type/session_idasnull— even when the caller never set them. Because OpenViking kernels declaremodel_config = ConfigDict(extra="forbid")on these routes, any instance that predates a given field rejects the entire request withbody.<field>: Extra inputs are not permitted. This patch stops sending those empty/null fields.This is the SDK-side counterpart of #2799, which fixed the exact same anti-pattern in the Rust CLI (
crates/ov_cli/src/client.rs) but left the Python SDK (sdk/python/openviking_sdk/client.py) untouched. The SDK is what every Python consumer uses — including vikingbot, which talks to OpenViking throughov.AsyncHTTPClientand therefore hits this against older instances on all three routes.Related Issue
Follow-up to #2799 (same breakage, different client surface).
Type of Change
Changes Made
AsyncHTTPClient._compact_request_body()and apply it infind/search/add_resource: drop null-valued keys and an emptyargsobject right before sending. Scoped to these read/create routes only, where a missing optional field and an explicitnullare equivalent — deliberately not applied globally, sincenullmay carry "clear this field" semantics on a future update/PATCH route. Mirrors the CLI'scompact_request_bodyfrom fix(cli): omit null/empty request fields so older instances accept them #2799.SyncHTTPClientdelegates to the async methods, so it inherits the fix with no separate change.Testing
New unit tests in
tests/client/test_http_client_compact.py:_compact_request_bodydrops null keys and an emptyargs, keepsFalse/ non-empty objects / non-emptyargs.find/searchomittags/score_threshold/filter/context_type/session_idwhen unset, and keeptagswhen explicitly provided.add_resourceomits an emptyargsand nullto/parent/timeout/ignore_dirs/include/exclude, and keeps a non-emptyargs.pytest tests/client/test_http_client_compact.py→ 7 passed. The two pre-existingLocalClienterrors intests/client/test_search.pyare unrelated (they reproduce onmainwith this patch stashed).Checklist
Additional Notes
ruff checkpasses on the changed files.ruff format --checkflags only one pre-existing formatting drift in an unrelated method (SyncHTTPClient.delete_skill), left untouched to keep the diff scoped to this fix.