Skip to content

fix(sdk): omit null/empty request fields so older instances accept them#2834

Merged
t0saki merged 1 commit into
volcengine:mainfrom
t0saki:fix/sdk-omit-null-request-fields
Jun 25, 2026
Merged

fix(sdk): omit null/empty request fields so older instances accept them#2834
t0saki merged 1 commit into
volcengine:mainfrom
t0saki:fix/sdk-omit-null-request-fields

Conversation

@t0saki

@t0saki t0saki commented Jun 25, 2026

Copy link
Copy Markdown
Collaborator

Description

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. Because OpenViking kernels declare model_config = ConfigDict(extra="forbid") on these routes, any instance that predates a given field rejects the entire request with body.<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 through ov.AsyncHTTPClient and therefore hits this against older instances on all three routes.

Related Issue

Follow-up to #2799 (same breakage, different client surface).

Type of Change

  • Bug fix (non-breaking change that fixes an issue)

Changes Made

  • Add AsyncHTTPClient._compact_request_body() and apply it in find / search / add_resource: drop null-valued keys and an empty args object right before sending. Scoped to these read/create routes only, where a missing optional field and an explicit null are equivalent — deliberately not applied globally, since null may carry "clear this field" semantics on a future update/PATCH route. Mirrors the CLI's compact_request_body from fix(cli): omit null/empty request fields so older instances accept them #2799.
  • The synchronous SyncHTTPClient delegates to the async methods, so it inherits the fix with no separate change.

Testing

  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • I have tested this on the following platforms:
    • macOS

New unit tests in tests/client/test_http_client_compact.py:

  • _compact_request_body drops null keys and an empty args, keeps False / non-empty objects / non-empty args.
  • find / search omit tags / score_threshold / filter / context_type / session_id when unset, and keep tags when explicitly provided.
  • add_resource omits an empty args and null to / parent / timeout / ignore_dirs / include / exclude, and keeps a non-empty args.

pytest tests/client/test_http_client_compact.py → 7 passed. The two pre-existing LocalClient errors in tests/client/test_search.py are unrelated (they reproduce on main with this patch stashed).

Checklist

  • My code follows the project's coding style
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • My changes generate no new warnings

Additional Notes

ruff check passes on the changed files. ruff format --check flags only one pre-existing formatting drift in an unrelated method (SyncHTTPClient.delete_skill), left untouched to keep the diff scoped to this fix.

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.
@t0saki t0saki merged commit 3d456ff into volcengine:main Jun 25, 2026
2 of 4 checks passed
@github-project-automation github-project-automation Bot moved this from Backlog to Done in OpenViking project Jun 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants