Skip to content

fix(skills): default FDv2SkillStore endpoints from LD_BASE_URI and LD_STREAM_URI - #207

Merged
XieX merged 2 commits into
mainfrom
xie/fdv2-endpoint-env
Oct 23, 2026
Merged

XieX merged 2 commits into
mainfrom
xie/fdv2-endpoint-env

Conversation

@XieX

@XieX XieX commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

init_client() reads LD_BASE_URI / LD_STREAM_URI for the base SDK, but FDv2SkillStore always defaulted to the production hosts. A process pointed at a staging or private instance by its environment resolved flags there, then sent skill delivery to production with a non-production key. That shows up as a fatal 401 in store.failed, not as a configuration error.

With neither base_uri nor stream_uri given, the constructor now reads both variables in their place, once:

  • A lone LD_BASE_URI moves both endpoints, under the store's existing rule for a lone base_uri. This differs on purpose from init_client(), where flag streaming stays on its default host.
  • Either option turns the environment off for both endpoints, so an explicit host is never mixed with one from the environment.
  • A blank value counts as unset.
  • A refused, non-https value is reported under the variable's name.
  • DEFAULT_BASE_URI / DEFAULT_STREAM_URI keep the production values as the fallback.

The client README and agents.md are updated.

From review: init_client() now strips whitespace from LD_BASE_URI, LD_STREAM_URI and LD_EVENTS_URI, through the existing _env helper, so a whitespace-only value counts as unset there too. That is a core change, so the override below lists it under client.

Spec: TESTING.md §3.25 and A.12, in launchdarkly/ai-sdks-monorepo#59. The TypeScript side is launchdarkly/js-ai-sdk#134.

Tests

  • TestEndpointsFromTheEnvironment adds a test for each bullet in §3.25.
  • test_skills_fdv2.py now clears both variables with an autouse fixture, so a developer shell can't move the default-host assertions.
  • TestTransportLayering's stdlib allowlist adds os.
  • TestInitClientSDKKeyPath adds whitespace and blank-value tests for the three init_client URI variables.

Checks:

  • uv run pytest packages/client/tests: 1648 passed.
  • make lint, make format-check and make typecheck are clean.

BEGIN_COMMIT_OVERRIDE
fix(skills): default FDv2SkillStore endpoints from LD_BASE_URI and LD_STREAM_URI
fix(client): strip whitespace from LD_BASE_URI, LD_STREAM_URI and LD_EVENTS_URI in init_client
END_COMMIT_OVERRIDE

🤖 Generated with Claude Code


Note

Overview
FDv2SkillStore now follows the same endpoint env vars as init_client() when you omit both base_uri and stream_uri. Staging/private setups that only set LD_BASE_URI / LD_STREAM_URI no longer resolve flags against one host while skill FDv2 traffic still hits production (often a fatal 401 on a non-prod key).

The constructor reads LD_BASE_URI and LD_STREAM_URI once via _endpoint_env() (whitespace-only counts as unset). A lone LD_BASE_URI drives poll and stream, matching a lone base_uri option—not init_client(), where streaming stays on the default host unless LD_STREAM_URI is set. Passing either URI option turns env off for both so hosts are never mixed. HTTPS validation errors name the env var when the value came from the environment.

Docs in README.md and agents.md describe this. Tests add clear_endpoint_env and TestEndpointsFromTheEnvironment.

Reviewed by Cursor Bugbot for commit 9deab92. Bugbot is set up for automated code reviews on this repo. Configure here.

…_STREAM_URI

init_client() reads LD_BASE_URI / LD_STREAM_URI for the base SDK, but
FDv2SkillStore always defaulted to the production hosts, so a process
pointed at a non-production instance sent skill delivery to production
with a non-production key.

With neither URI option given, the constructor now reads both variables
in their place, once. A lone LD_BASE_URI moves both endpoints, either
option turns the environment off for both, blank counts as unset, and a
refused value is reported under the variable's name.

Spec: TESTING.md §3.25 and A.12 (launchdarkly/ai-sdks-monorepo#59).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@XieX
XieX requested a review from jeffdupont October 23, 2026 17:57
@XieX
XieX marked this pull request as ready for review October 23, 2026 17:57

@jeffdupont jeffdupont 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.

Approved after the GA 1.0 PR audit. Lands together with js-ai-sdk#134. Nit for a follow-up: strip whitespace on the env values at lifecycle.py:293-294.

…EVENTS_URI in init_client

init_client read the three URI variables with os.environ.get, so a value
with stray whitespace reached ldclient.Config as-is, and a whitespace-only
value was passed as a URI rather than treated as unset. They now go
through _env, as LD_SDK_KEY and the other variables already do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@XieX

XieX commented Oct 23, 2026

Copy link
Copy Markdown
Contributor Author

Applied the nit in 01c1fee: init_client() now reads LD_BASE_URI, LD_STREAM_URI and LD_EVENTS_URI through the existing _env helper, so values are stripped and a whitespace-only value counts as unset. There are tests for both. It's a core change in a fix(skills) PR, so the description now has a BEGIN_COMMIT_OVERRIDE block that lists it under client.

🤖 Addressed by Claude Code

@XieX
XieX merged commit 1629123 into main Oct 23, 2026
10 checks passed
@XieX
XieX deleted the xie/fdv2-endpoint-env branch October 23, 2026 22:28
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.

2 participants