Skip to content

fix(AIC-3573): never send a NativeTool to the model as a function tool - #248

Merged
andrewklatzke merged 3 commits into
mainfrom
jdupont/aic-3573-native-tools
Oct 30, 2026
Merged

andrewklatzke merged 3 commits into
mainfrom
jdupont/aic-3573-native-tools

Conversation

@jeffdupont

@jeffdupont jeffdupont commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Jira: AIC-3573

Problem

wrap_tool_handlers turns every NativeTool into a callable tracking stub, so Claude Agents and OpenCode can wire it to their built-in tools. Every other handler sent it to the model as a function tool. The openai, claude and langchain messages handlers and the openai and langchain agents handlers offer every config.tools entry. litellm and vercel keep any callable, and the stub is callable. So a configured built-in tool (such as web search) never turned on, and the model saw a made-up function that returns nothing.

Change

  • is_function_tool(handler, name) in launchdarkly_ai_server (utils.py). It returns False for a NativeTool or its stub (NATIVE_TOOL_KEY) and logs one warning per tool key. Otherwise it returns callable(handler), as a TypeGuard. It is exported like end_span_once (handler plumbing).
  • Every handler and native graph that builds a tool list now skips native tools with it: 9 handler builders and the openai and langchain agents native graphs. The litellm and vercel graphs reuse their handler's builder. Claude Agents and OpenCode are unchanged.
  • Unchanged on purpose: the openai, claude and langchain messages handlers and the openai and langchain agents handlers still offer a tool that has no handler, and so do the openai and langchain agents native graphs (they return "" when it is called). TypeScript drops these. That gap predates this PR. This PR removes only native tools.
  • There are no provider built-in mappings yet. A handler with no built-in skips the tool with a warning and never raises.

Tests

  • tests/test_native_tools.py in each affected package: the builder drops a NativeTool and its stub, keeps the function tool, and warns once per key.
  • Unit tests for is_function_tool with the real wrap_tool_handlers stub, plus the public-surface snapshot.
  • langchain-agents test_native_tool_is_not_called becomes test_native_tool_is_not_registered.
  • Control: with the handler sources reverted to main, all 12 new builder tests fail.

Checks run locally: ruff check, ruff format --check, mypy packages/*/src, make api-report-check, pytest (all pass except test_lifecycle.py::TestInitClientSDKKeyPath's two tests, which also fail on main in a whole-repo run and pass on their own).

TypeScript: launchdarkly/js-ai-sdk#194

🤖 Generated with Claude Code


Note

Overview
Fixes a bug where NativeTool entries (and the callable tracking stubs from wrap_tool_handlers) were exposed to the model as custom function tools instead of provider built-ins, so configured native tools like web search never activated and the model saw no-op functions.

Adds shared is_function_tool(handler, name) on launchdarkly_ai_server: it rejects NativeTool / stub handlers, logs one warning per tool key, and otherwise treats only real callables as function tools. Nine handler tool builders (Claude/OpenAI/LangChain/LiteLLM/Vercel messages and agents) plus OpenAI and LangChain native graph node tool builders now filter through it; _build_tools in messages handlers also takes tool_handlers so filtering can run at catalog build time.

Unchanged: configs can still advertise tools with no registered handler on several paths (predates this PR). Tests cover is_function_tool, public exports, and per-package builders dropping native tools while keeping ordinary function tools.

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

@jeffdupont
jeffdupont marked this pull request as ready for review October 29, 2026 18:25
@jeffdupont
jeffdupont requested a review from a team as a code owner October 29, 2026 18:25
jeffdupont added a commit that referenced this pull request Oct 30, 2026
…#251)

Fixes [AIC-3716](https://launchdarkly.atlassian.net/browse/AIC-3716), a
1.0 blocker. JS parity test: launchdarkly/js-ai-sdk#196.

## Problem

`to_openai_agents` crashes on every graph node that has a tool:

```
File ".../launchdarkly_ai_openai_agents/native_graph.py", line 92, in _build_node_tools
TypeError: 'module' object is not callable
```

`_build_node_tools` called `agents.tool`, which is a submodule in
openai-agents, not a function. This happens in 0.17.7 (locked) and in
0.24.0 (latest). Nodes without tools were unaffected. CI was green
because every test replaced the whole `agents` module with a
`MagicMock`, and a mock accepts any call.

## Change

- Node tools are built with `agents.FunctionTool`, the class
`handler.py` already uses. `agents.function_tool` is not usable here
because it reads the schema from the Python function signature and has
no `params_json_schema` argument.
- The tool name, description, schema and handler wiring are unchanged.
`on_invoke_tool` decodes the JSON arguments the same way `handler.py`
does. A missing handler or a `NativeTool` still returns `""`, and sync
or async handlers still go through `tool_result_string`.
- `strict_json_schema=False`, so the config schema reaches the model as
given. This matches the TypeScript graph's `strict: false`. Strict mode
would make every property required, add `additionalProperties: false`,
and reject `additionalProperties: true`.
- Handler errors propagate, matching the TypeScript graph's
`errorFunction: null`. A directly built `FunctionTool` does not wrap
`on_invoke_tool`.
- `openai-agents>=0.17,<0.25`. openai-agents makes breaking changes in
minor (`0.Y`) releases (its `docs/release.md`), and 0.24.0 is the
latest, so the bound stops at 0.25. `uv lock --check` passes; the
lockfile changes only the specifier.

## Tests

- `TestBuildNodeToolsSyncHandlers` now builds tools with the real
`FunctionTool` instead of patching `importlib.import_module`.
- New `TestNativeGraphRunsANodeWithAToolOnTheRealSdk` runs
`to_openai_agents` with the real `agents` package and fakes only the
model (`MultiProvider.get_model`). It asserts that the tool call reaches
the handler with the parsed arguments, that the run returns the model's
final answer, and that the model receives a `FunctionTool` with the
config's name, description and schema unchanged. The schema has an
optional property, so a strict-mode rewrite would fail the test.
- **On `main` 8218626, all 4 of these tests fail** with the ticket's
`TypeError`. With this change they pass on 0.17.7, and the native graph
suite passes on 0.24.0 (`uv run --with openai-agents==0.24.0`).
- The stale `agents_mock.tool` stubs are removed.
- The real-SDK test turns off the SDK's trace export for its run, so a
developer with `OPENAI_API_KEY` set sends nothing to OpenAI. I checked
this with `OPENAI_API_KEY=sk-fake`: without the patch the run logs a 401
from the trace exporter, and with it there is no request.

## Spec

No change needed. TESTING.md §2.2 "Tool forwarding" already requires
node tools "in that provider's native tool format". Python broke that
rule, and this PR fixes it.

## Checks

`make lint format-check typecheck api-report` pass and `uv lock --check`
passes. `make test`: 3714 passed, 18 skipped, and 2 failed in
`packages/client/tests/test_lifecycle.py::TestInitClientSDKKeyPath`.
Those 2 fail the same way locally on clean `main` 8218626, pass when
that file runs alone, and this PR does not touch the client package.

## Notes

- **Known difference from JS, kept on purpose:** tool arguments that are
not valid JSON become `{}` and the handler still runs, as in Python's
`handler.py`. JS `tool()` raises `InvalidToolInputError` and fails the
run. Changing this would make Python's handler and native graph behave
differently, so it is left for a follow-up that aligns both Python paths
with JS.

- #248 (AIC-3573) edits the same loop in `_build_node_tools`, adding an
`is_function_tool` skip. Whichever merges second gets a small conflict.
- On openai-agents 0.24.0,
`test_parameter_forwarding.py::test_every_field_is_classified_exactly_once`
fails because `ModelSettings` gained `preserve_raw_usage`,
`prompt_cache_options` and `timeout`. This is not caused by this PR, and
CI is locked to 0.17.7. It needs a separate ticket if the lock moves.

🤖 Generated with [Claude Code](https://claude.com/claude-code)


[AIC-3716]:
https://launchdarkly.atlassian.net/browse/AIC-3716?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Overview**
> Fixes a **1.0 blocker** where `to_openai_agents` crashed on any graph
node that declared tools: `_build_node_tools` called `agents.tool`,
which is a **submodule**, not a decorator—raising `TypeError: 'module'
object is not callable`.
> 
> Node tools are now built with **`agents.FunctionTool`**, matching the
single-node handler. Tool callbacks use **`on_invoke_tool`** with JSON
argument decoding, default empty-object schemas when missing, and
**`strict_json_schema=False`** so LaunchDarkly config schemas reach the
model unchanged (TypeScript `strict: false` parity).
> 
> The **`openai-agents`** dependency is capped at **`>=0.17,<0.25`**
because the SDK ships breaking changes in minor releases.
> 
> Tests stop mocking a fake `agents.tool` and instead exercise the real
**`FunctionTool`**; a new integration test runs the native graph through
the real Agents SDK with only the model faked, asserting tool calls
reach handlers and schemas are not strict-rewritten.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
1969deb. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
jeffdupont and others added 3 commits October 30, 2026 08:04
The tool wrapper turns every NativeTool into a callable tracking stub, so
every handler but Claude Agents (and OpenCode in Python) sent it to the
model as a function tool that returns nothing. Add an isFunctionTool /
is_function_tool helper that rejects a NativeTool or its stub and warns
once per tool key, and use it wherever a handler or native graph builds
its tool list. No provider built-in mappings yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The native graph now builds node tools with agents.FunctionTool (#251), so the
agents.tool stub in this test no longer covers anything.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jeffdupont
jeffdupont force-pushed the jdupont/aic-3573-native-tools branch from cb0e208 to 21d6150 Compare October 30, 2026 15:07
jeffdupont added a commit to launchdarkly/js-ai-sdk that referenced this pull request Oct 30, 2026
#194)

Jira: [AIC-3573](https://launchdarkly.atlassian.net/browse/AIC-3573)

## Problem

`wrapToolHandlers` turns every `NativeTool` into a callable tracking
stub, so Claude Agents can wire it to the built-in tool. Every other
handler keeps any callable. So openai, claude, langchain, litellm and
vercel messages, the openai, langchain, litellm and vercel agents
handlers, and their native graphs all sent a configured built-in tool
(such as web search) to the model as a function tool:

- the provider's built-in tool never turned on;
- the model saw a made-up function that returns nothing;
- a model call to it was still recorded as a tool call.

## Change

- **`isFunctionTool(name, handler)`** in `@launchdarkly/ai-server`
(`utils.ts`). It returns `false` for a `NativeTool` or its stub
(`NATIVE_TOOL_KEY`) and logs one warning per tool key, then for anything
that is not a function. It is listed as `- isFunctionTool` (handler
plumbing) in `api-surface/ai-server.txt`, like `endSpanOnce`.
- **Every handler and native graph that builds a tool list** uses it in
place of `typeof handler === 'function'`: 9 handlers and 4 native
graphs. Claude Agents is unchanged: it already wires native tools.
- **openai-agents and langchain-agents native graphs** used to offer
every `config.tools` entry and return `''` for a native or missing
handler. They now filter on `Object.hasOwn` plus `isFunctionTool`. A
tool with no handler is no longer offered, like the litellm and vercel
graphs. Neither is a name such as `constructor` inherited from the
object; the litellm and vercel graphs and the agents handlers still lack
that `hasOwn` guard, which predates this PR.
- There are no provider built-in mappings (OpenAI `web_search` and so
on) yet. A handler with no built-in skips the tool with a warning and
never throws, so adding a mapping later is non-breaking.

## Tests

- One test per handler and native graph: a config attaches a function
tool and a `NativeTool`. The provider receives only the function tool,
for both the stub and the raw `NativeTool`, and the second call logs no
second warning.
- The openai-agents and langchain-agents native graphs: a node tool with
no handler, or named `constructor`, is not registered.
- Unit tests for `isFunctionTool`, using the real `wrapToolHandlers`
stub.
- The `toLangGraph` test that asserted an empty-string tool now asserts
that the tool is not registered.
- Control: with the handler sources reverted to `main`, every new test
fails.

Checks run locally: `code:check`, `build`, `typecheck`, `api:check`,
`api:surface`, `test:api-surface`, `test`, `lint:pkg`.

Python: launchdarkly/python-ai-sdk#248

🤖 Generated with [Claude Code](https://claude.com/claude-code)


[AIC-3573]:
https://launchdarkly.atlassian.net/browse/AIC-3573?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Overview**
> Fixes a bug where **`wrapToolHandlers`** makes **`NativeTool`**
handlers look callable, so most provider handlers were advertising
configured built-ins (e.g. web search) as **function tools** instead of
using provider natives—leading to useless tool calls and misleading
telemetry.
> 
> Adds **`isFunctionTool(name, handler)`** in
**`@launchdarkly/ai-server`**: it returns false for a **`NativeTool`**
or its tracking stub (**`NATIVE_TOOL_KEY`**), logs **one console warning
per tool key**, and otherwise requires a real function. **Nine
message/agent handlers** and **four native graphs** now filter tool
lists through this helper instead of **`typeof handler === 'function'`**
(Claude Agents is unchanged).
> 
> **OpenAI Agents** and **LangChain Agents** native graphs no longer
register every **`config.tools`** entry and return **`''`** for
native/missing handlers; they only register tools with an own handler
that passes **`isFunctionTool`**, including skipping names like
**`constructor`** inherited from the tools object.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
e7dd8c0. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@andrewklatzke
andrewklatzke merged commit 73caeae into main Oct 30, 2026
10 checks passed
@andrewklatzke
andrewklatzke deleted the jdupont/aic-3573-native-tools branch October 30, 2026 16:43
@github-actions github-actions Bot mentioned this pull request Oct 30, 2026
jeffdupont added a commit that referenced this pull request Oct 30, 2026
Steps 1 and 2 of
[AIC-3672](https://launchdarkly.atlassian.net/browse/AIC-3672). The JS
half is AIC-3673.

## What this does

- **`release-as: 1.0.0`** on all 14 packages in
`release-please-config.json`. Without it, release-please keeps bumping
0.x minors, so the next release PR would ship `launchdarkly-ai-server`
0.6.0 instead of 1.0.0.
- **Internal pins.** Every package that depends on
`launchdarkly-ai-server` now requires `>=1.0.0,<2`. release-please
doesn't update these for Python. #218 (merged) set them to `>=0.6,<2` so
either release order resolves; this tightens them to the 1.0 line.
- **`uv.lock`** needs no change: uv records workspace dependencies
without a version specifier. `uv lock --check` passes.

`changelog-sections` is left alone. #235 removes the evaluations
Experimental rows when it promotes Evaluations from Code to core.

## Merge this last

Merge this after the PRs below. Anything merged before the release PR
(#231) merges ships in 1.0.0, and a `!` change merged after 1.0 forces
2.0.

- [x] #218 fix(AIC-3598)!: packaging and public types (merged 29 Oct)
- [x] #235 feat(evaluations)!: promote Evaluations from Code to core
(merged 29 Oct). After it merges, nothing in
`launchdarkly_ai_server.experimental` is public.
- [x] #237 fix(claude-agents)!: honour max_tokens and disable thinking
by default (merged 29 Oct)
- [ ] #136 feat(AIC-3439): wildcard handlers accept only named providers
(approved; conflicts with main, needs a merge of main)
- [x] #234 fix(AIC-3568)!: give the barrel core's `__all__` (merged 29
Oct)
- [ ] #246 fix(AIC-3592): make native LangGraph hand-offs complete (spec
launchdarkly/ai-sdks-monorepo#118)
- [ ] #248 fix(AIC-3573): never send a NativeTool to the model as a
function tool (spec launchdarkly/ai-sdks-monorepo#116)
- [ ] #240 feat(client): add result variant and value to the
feature_flag span event (approved, mergeable)
- [ ] #251 fix(AIC-3716): build OpenAI native graph node tools with
FunctionTool (review required; touches the same loop as #248)

#241 (Shadow Requests) is closed; 1.0 ships with nothing experimental.

## After merging

1. Confirm the regenerated #231 lists 1.0.0 for all 14 packages, then
merge it.
2. Install each package from PyPI into an empty venv and import its
public entry points (AIC-3672 step 5).
3. Open a PR removing `release-as` straight away, or every later release
PR proposes 1.0.0 again.

## Checks

- `release-please-config.json` parses as JSON, with `release-as: 1.0.0`
on all 14 packages. The first push wrote the lines with literal
backslashes; fixed in d720896.

- `make test`: 3,711 passed, 18 skipped (before #175 and #236 merged; CI
is the current check) (with the parent checkout's `.env` LD URIs
blanked; see AIC-3593)
- `uv lock --check` passes

🤖 Generated with [Claude Code](https://claude.com/claude-code)


[AIC-3672]:
https://launchdarkly.atlassian.net/browse/AIC-3672?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ




<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Overview**
> Prepares the **1.0.0 GA** cut for all 14 Python packages by teaching
release-please to release **1.0.0** instead of another **0.x** bump.
> 
> Adds **`release-as: "1.0.0"`** on every entry in
`release-please-config.json` (core `launchdarkly-ai-server`, barrel, and
all handler packages).
> 
> Tightens **internal PyPI pins** from `launchdarkly-ai-server>=0.6,<2`
to **`>=1.0.0,<2`** in each handler `pyproject.toml` and in
`packages/ai` (including **`otel`** / **`ld`** extras). Published wheels
will require the 1.0 server line once those versions ship.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
ae9f2cc. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: andrewklatzke <aklatzke@launchdarkly.com>
jeffdupont pushed a commit that referenced this pull request Oct 30, 2026
🤖 I have created a release *beep* *boop*
---


<details><summary>launchdarkly-ai-server: 1.0.0</summary>

##
[1.0.0](launchdarkly-ai-server-0.5.0...launchdarkly-ai-server-1.0.0)
(2026-10-30)


### ⚠ BREAKING CHANGES

* **client:** init_client raises when the LaunchDarkly client did not
initialize
([#254](#254))
* **evaluations:** route generation and judges to a scoped wildcard
handler only for its named providers, and accept two scoped wildcards of
one mode when their lists differ
* **AIC-3439:** let wildcard handlers accept only named providers
* **AIC-3598:** make Python packaging and public types GA-ready
([#218](#218))
* **AIC-3568:** give the barrel core's __all__, and drop private-spec
references
([#234](#234))
* **evaluations:** promote Evaluations from Code to core
([#235](#235))
* **client:** capture conversation content by default
([#213](#213))
* **evaluations:** remove default pass rate threshold
([#238](#238))
* **evaluations:** set default pass rate threshold
([#226](#226))
* **client:** spans carry launchdarkly.project_id instead of
highlight.project_id
* **AIC-3687:** rename create_openai_agent_handler to
create_openai_agents_handler
([#225](#225))
* **skills:** rename FDv2SkillStore to LaunchDarklySkillStore
([#223](#223))

### Features

* **AIC-3439:** let wildcard handlers accept only named providers
([454a4de](454a4de))
* **AIC-3687:** rename create_openai_agent_handler to
create_openai_agents_handler
([#225](#225))
([a7cdbc0](a7cdbc0))
* **client:** add result variant and value to the feature_flag span
event ([#240](#240))
([040d487](040d487))
* **client:** capture conversation content by default
([#213](#213))
([77a7cf5](77a7cf5))
* **client:** point judge spans at the run they graded
([#253](#253))
([863d423](863d423))
* **evaluations:** promote Evaluations from Code to core
([#235](#235))
([0bc43a5](0bc43a5))
* **evaluations:** remove default pass rate threshold
([#238](#238))
([882d099](882d099))
* **evaluations:** route generation and judges to a scoped wildcard
handler only for its named providers, and accept two scoped wildcards of
one mode when their lists differ
([454a4de](454a4de))
* **evaluations:** set default pass rate threshold
([#226](#226))
([7ee368c](7ee368c))
* **skills:** rename FDv2SkillStore to LaunchDarklySkillStore
([#223](#223))
([11f2c0b](11f2c0b))


### Bug Fixes

* **AIC-3568:** give the barrel core's __all__, and drop private-spec
references
([#234](#234))
([88e57e6](88e57e6))
* **AIC-3573:** never send a NativeTool to the model as a function tool
([#248](#248))
([73caeae](73caeae))
* **AIC-3598:** make Python packaging and public types GA-ready
([#218](#218))
([5860b40](5860b40))
* **AIC-3601:** stop graph routing text inviting a router to answer for
its target
([#230](#230))
([27b8d09](27b8d09))
* **client:** init_client raises when the LaunchDarkly client did not
initialize
([#254](#254))
([6e66c00](6e66c00))
* **client:** stamp launchdarkly.project_id on the telemetry resource
([#229](#229))
([5347558](5347558))
* **evaluations:** copy inline tool schemas and name both sources on a
key collision
([#227](#227))
([bfbdd4c](bfbdd4c))
* **evaluations:** send criterion errors as errorMessage and skip
criteria for rows that did not generate
([#228](#228))
([8b05b56](8b05b56))
* **graph:** report a node's own judge scores on its node_done stream
event ([#236](#236))
([2f3f9ee](2f3f9ee))


### Documentation

* **AIC-3692:** say which project id attribute the telemetry resource
carries
([#239](#239))
([64eff43](64eff43))
* state that Agent Skills and Evaluations from Code need 1.0.0
([#191](#191))
([fe3ef08](fe3ef08))
</details>

<details><summary>launchdarkly-ai-python: 1.0.0</summary>

##
[1.0.0](launchdarkly-ai-python-0.4.0...launchdarkly-ai-python-1.0.0)
(2026-10-30)


### ⚠ BREAKING CHANGES

* **AIC-3598:** make Python packaging and public types GA-ready
([#218](#218))
* **AIC-3568:** give the barrel core's __all__, and drop private-spec
references
([#234](#234))
* **evaluations:** promote Evaluations from Code to core
([#235](#235))

### Features

* **evaluations:** promote Evaluations from Code to core
([#235](#235))
([0bc43a5](0bc43a5))


### Bug Fixes

* **AIC-3568:** give the barrel core's __all__, and drop private-spec
references
([#234](#234))
([88e57e6](88e57e6))
* **AIC-3598:** make Python packaging and public types GA-ready
([#218](#218))
([5860b40](5860b40))


### Documentation

* state that Agent Skills and Evaluations from Code need 1.0.0
([#191](#191))
([fe3ef08](fe3ef08))
</details>

<details><summary>launchdarkly-ai-claude-agents: 1.0.0</summary>

##
[1.0.0](launchdarkly-ai-claude-agents-0.3.0...launchdarkly-ai-claude-agents-1.0.0)
(2026-10-30)


### ⚠ BREAKING CHANGES

* **AIC-3598:** make Python packaging and public types GA-ready
([#218](#218))
* **AIC-3568:** give the barrel core's __all__, and drop private-spec
references
([#234](#234))
* **claude-agents:** honour the config's max_tokens and disable thinking
unless the config asks
([#237](#237))
* **client:** capture conversation content by default
([#213](#213))
* **AIC-3685:** make the internal provider helpers private
([#224](#224))
* **skills:** rename FDv2SkillStore to LaunchDarklySkillStore
([#223](#223))

### Features

* **AIC-3685:** make the internal provider helpers private
([#224](#224))
([9afdb94](9afdb94))
* **client:** add result variant and value to the feature_flag span
event ([#240](#240))
([040d487](040d487))
* **client:** capture conversation content by default
([#213](#213))
([77a7cf5](77a7cf5))
* **skills:** rename FDv2SkillStore to LaunchDarklySkillStore
([#223](#223))
([11f2c0b](11f2c0b))


### Bug Fixes

* **AIC-3568:** give the barrel core's __all__, and drop private-spec
references
([#234](#234))
([88e57e6](88e57e6))
* **AIC-3598:** make Python packaging and public types GA-ready
([#218](#218))
([5860b40](5860b40))
* **claude-agents:** honour the config's max_tokens and disable thinking
unless the config asks
([#237](#237))
([a7ded1b](a7ded1b))
</details>

<details><summary>launchdarkly-ai-claude-messages: 1.0.0</summary>

##
[1.0.0](launchdarkly-ai-claude-messages-0.3.0...launchdarkly-ai-claude-messages-1.0.0)
(2026-10-30)


### ⚠ BREAKING CHANGES

* **AIC-3598:** make Python packaging and public types GA-ready
([#218](#218))
* **AIC-3568:** give the barrel core's __all__, and drop private-spec
references
([#234](#234))
* **client:** capture conversation content by default
([#213](#213))

### Features

* **client:** add result variant and value to the feature_flag span
event ([#240](#240))
([040d487](040d487))
* **client:** capture conversation content by default
([#213](#213))
([77a7cf5](77a7cf5))


### Bug Fixes

* **AIC-3568:** give the barrel core's __all__, and drop private-spec
references
([#234](#234))
([88e57e6](88e57e6))
* **AIC-3573:** never send a NativeTool to the model as a function tool
([#248](#248))
([73caeae](73caeae))
* **AIC-3598:** make Python packaging and public types GA-ready
([#218](#218))
([5860b40](5860b40))
* **AIC-3735:** send Claude Messages sampling parameters through
extra_body
([#256](#256))
([c6d0376](c6d0376))
</details>

<details><summary>launchdarkly-ai-openai-agents: 1.0.0</summary>

##
[1.0.0](launchdarkly-ai-openai-agents-0.3.0...launchdarkly-ai-openai-agents-1.0.0)
(2026-10-30)


### ⚠ BREAKING CHANGES

* **AIC-3598:** make Python packaging and public types GA-ready
([#218](#218))
* **AIC-3568:** give the barrel core's __all__, and drop private-spec
references
([#234](#234))
* **client:** capture conversation content by default
([#213](#213))
* **AIC-3685:** make the internal provider helpers private
([#224](#224))
* **AIC-3687:** rename create_openai_agent_handler to
create_openai_agents_handler
([#225](#225))

### Features

* **AIC-3685:** make the internal provider helpers private
([#224](#224))
([9afdb94](9afdb94))
* **AIC-3687:** rename create_openai_agent_handler to
create_openai_agents_handler
([#225](#225))
([a7cdbc0](a7cdbc0))
* **client:** add result variant and value to the feature_flag span
event ([#240](#240))
([040d487](040d487))
* **client:** capture conversation content by default
([#213](#213))
([77a7cf5](77a7cf5))


### Bug Fixes

* **AIC-3568:** give the barrel core's __all__, and drop private-spec
references
([#234](#234))
([88e57e6](88e57e6))
* **AIC-3573:** never send a NativeTool to the model as a function tool
([#248](#248))
([73caeae](73caeae))
* **AIC-3598:** make Python packaging and public types GA-ready
([#218](#218))
([5860b40](5860b40))
* **AIC-3716:** build OpenAI native graph node tools with FunctionTool
([#251](#251))
([b859b67](b859b67))
* **AIC-3726:** realign three usage IDs with the 1.0 factory names
([#252](#252))
([1c4d904](1c4d904))
</details>

<details><summary>launchdarkly-ai-vercel-agents: 1.0.0</summary>

##
[1.0.0](launchdarkly-ai-vercel-agents-0.2.0...launchdarkly-ai-vercel-agents-1.0.0)
(2026-10-30)


### ⚠ BREAKING CHANGES

* **AIC-3598:** make Python packaging and public types GA-ready
([#218](#218))
* **AIC-3568:** give the barrel core's __all__, and drop private-spec
references
([#234](#234))

### Features

* **client:** add result variant and value to the feature_flag span
event ([#240](#240))
([040d487](040d487))


### Bug Fixes

* **AIC-3568:** give the barrel core's __all__, and drop private-spec
references
([#234](#234))
([88e57e6](88e57e6))
* **AIC-3573:** never send a NativeTool to the model as a function tool
([#248](#248))
([73caeae](73caeae))
* **AIC-3598:** make Python packaging and public types GA-ready
([#218](#218))
([5860b40](5860b40))
</details>

<details><summary>launchdarkly-ai-litellm-agents: 1.0.0</summary>

##
[1.0.0](launchdarkly-ai-litellm-agents-0.2.0...launchdarkly-ai-litellm-agents-1.0.0)
(2026-10-30)


### ⚠ BREAKING CHANGES

* **AIC-3598:** make Python packaging and public types GA-ready
([#218](#218))
* **AIC-3568:** give the barrel core's __all__, and drop private-spec
references
([#234](#234))
* **client:** capture conversation content by default
([#213](#213))

### Features

* **client:** add result variant and value to the feature_flag span
event ([#240](#240))
([040d487](040d487))
* **client:** capture conversation content by default
([#213](#213))
([77a7cf5](77a7cf5))


### Bug Fixes

* **AIC-3568:** give the barrel core's __all__, and drop private-spec
references
([#234](#234))
([88e57e6](88e57e6))
* **AIC-3573:** never send a NativeTool to the model as a function tool
([#248](#248))
([73caeae](73caeae))
* **AIC-3598:** make Python packaging and public types GA-ready
([#218](#218))
([5860b40](5860b40))
</details>

<details><summary>launchdarkly-ai-openai-messages: 1.0.0</summary>

##
[1.0.0](launchdarkly-ai-openai-messages-0.3.0...launchdarkly-ai-openai-messages-1.0.0)
(2026-10-30)


### ⚠ BREAKING CHANGES

* **AIC-3598:** make Python packaging and public types GA-ready
([#218](#218))
* **AIC-3568:** give the barrel core's __all__, and drop private-spec
references
([#234](#234))
* **client:** capture conversation content by default
([#213](#213))

### Features

* **client:** add result variant and value to the feature_flag span
event ([#240](#240))
([040d487](040d487))
* **client:** capture conversation content by default
([#213](#213))
([77a7cf5](77a7cf5))


### Bug Fixes

* **AIC-3568:** give the barrel core's __all__, and drop private-spec
references
([#234](#234))
([88e57e6](88e57e6))
* **AIC-3573:** never send a NativeTool to the model as a function tool
([#248](#248))
([73caeae](73caeae))
* **AIC-3598:** make Python packaging and public types GA-ready
([#218](#218))
([5860b40](5860b40))
* **AIC-3726:** realign three usage IDs with the 1.0 factory names
([#252](#252))
([1c4d904](1c4d904))
</details>

<details><summary>launchdarkly-ai-vercel-messages: 1.0.0</summary>

##
[1.0.0](launchdarkly-ai-vercel-messages-0.2.0...launchdarkly-ai-vercel-messages-1.0.0)
(2026-10-30)


### ⚠ BREAKING CHANGES

* **AIC-3598:** make Python packaging and public types GA-ready
([#218](#218))
* **AIC-3568:** give the barrel core's __all__, and drop private-spec
references
([#234](#234))

### Features

* **client:** add result variant and value to the feature_flag span
event ([#240](#240))
([040d487](040d487))


### Bug Fixes

* **AIC-3568:** give the barrel core's __all__, and drop private-spec
references
([#234](#234))
([88e57e6](88e57e6))
* **AIC-3573:** never send a NativeTool to the model as a function tool
([#248](#248))
([73caeae](73caeae))
* **AIC-3598:** make Python packaging and public types GA-ready
([#218](#218))
([5860b40](5860b40))
</details>

<details><summary>launchdarkly-ai-litellm-messages: 1.0.0</summary>

##
[1.0.0](launchdarkly-ai-litellm-messages-0.2.0...launchdarkly-ai-litellm-messages-1.0.0)
(2026-10-30)


### ⚠ BREAKING CHANGES

* **AIC-3598:** make Python packaging and public types GA-ready
([#218](#218))
* **AIC-3568:** give the barrel core's __all__, and drop private-spec
references
([#234](#234))
* **client:** capture conversation content by default
([#213](#213))

### Features

* **client:** add result variant and value to the feature_flag span
event ([#240](#240))
([040d487](040d487))
* **client:** capture conversation content by default
([#213](#213))
([77a7cf5](77a7cf5))


### Bug Fixes

* **AIC-3568:** give the barrel core's __all__, and drop private-spec
references
([#234](#234))
([88e57e6](88e57e6))
* **AIC-3573:** never send a NativeTool to the model as a function tool
([#248](#248))
([73caeae](73caeae))
* **AIC-3598:** make Python packaging and public types GA-ready
([#218](#218))
([5860b40](5860b40))
</details>

<details><summary>launchdarkly-ai-langchain-agents: 1.0.0</summary>

##
[1.0.0](launchdarkly-ai-langchain-agents-0.3.0...launchdarkly-ai-langchain-agents-1.0.0)
(2026-10-30)


### ⚠ BREAKING CHANGES

* **evaluations:** route generation and judges to a scoped wildcard
handler only for its named providers, and accept two scoped wildcards of
one mode when their lists differ
* **AIC-3439:** let wildcard handlers accept only named providers
* **AIC-3598:** make Python packaging and public types GA-ready
([#218](#218))
* **AIC-3568:** give the barrel core's __all__, and drop private-spec
references
([#234](#234))
* **client:** capture conversation content by default
([#213](#213))

### Features

* **AIC-3439:** let wildcard handlers accept only named providers
([454a4de](454a4de))
* **client:** add result variant and value to the feature_flag span
event ([#240](#240))
([040d487](040d487))
* **client:** capture conversation content by default
([#213](#213))
([77a7cf5](77a7cf5))
* **evaluations:** route generation and judges to a scoped wildcard
handler only for its named providers, and accept two scoped wildcards of
one mode when their lists differ
([454a4de](454a4de))


### Bug Fixes

* **AIC-3568:** give the barrel core's __all__, and drop private-spec
references
([#234](#234))
([88e57e6](88e57e6))
* **AIC-3573:** never send a NativeTool to the model as a function tool
([#248](#248))
([73caeae](73caeae))
* **AIC-3590:** build Python langchain-agents with
langchain.agents.create_agent
([#175](#175))
([8218626](8218626))
* **AIC-3592:** make native LangGraph hand-offs complete
([#246](#246))
([bfb738f](bfb738f))
* **AIC-3598:** make Python packaging and public types GA-ready
([#218](#218))
([5860b40](5860b40))
</details>

<details><summary>launchdarkly-ai-langchain-messages: 1.0.0</summary>

##
[1.0.0](launchdarkly-ai-langchain-messages-0.3.0...launchdarkly-ai-langchain-messages-1.0.0)
(2026-10-30)


### ⚠ BREAKING CHANGES

* **evaluations:** route generation and judges to a scoped wildcard
handler only for its named providers, and accept two scoped wildcards of
one mode when their lists differ
* **AIC-3439:** let wildcard handlers accept only named providers
* **AIC-3598:** make Python packaging and public types GA-ready
([#218](#218))
* **AIC-3568:** give the barrel core's __all__, and drop private-spec
references
([#234](#234))
* **client:** capture conversation content by default
([#213](#213))

### Features

* **AIC-3439:** let wildcard handlers accept only named providers
([454a4de](454a4de))
* **client:** add result variant and value to the feature_flag span
event ([#240](#240))
([040d487](040d487))
* **client:** capture conversation content by default
([#213](#213))
([77a7cf5](77a7cf5))
* **evaluations:** route generation and judges to a scoped wildcard
handler only for its named providers, and accept two scoped wildcards of
one mode when their lists differ
([454a4de](454a4de))


### Bug Fixes

* **AIC-3568:** give the barrel core's __all__, and drop private-spec
references
([#234](#234))
([88e57e6](88e57e6))
* **AIC-3573:** never send a NativeTool to the model as a function tool
([#248](#248))
([73caeae](73caeae))
* **AIC-3598:** make Python packaging and public types GA-ready
([#218](#218))
([5860b40](5860b40))
* **AIC-3726:** realign three usage IDs with the 1.0 factory names
([#252](#252))
([1c4d904](1c4d904))
</details>

<details><summary>launchdarkly-ai-opencode-agents: 1.0.0</summary>

##
[1.0.0](launchdarkly-ai-opencode-agents-0.3.0...launchdarkly-ai-opencode-agents-1.0.0)
(2026-10-30)


### ⚠ BREAKING CHANGES

* **AIC-3598:** make Python packaging and public types GA-ready
([#218](#218))
* **AIC-3568:** give the barrel core's __all__, and drop private-spec
references
([#234](#234))

### Features

* **client:** add result variant and value to the feature_flag span
event ([#240](#240))
([040d487](040d487))


### Bug Fixes

* **AIC-3568:** give the barrel core's __all__, and drop private-spec
references
([#234](#234))
([88e57e6](88e57e6))
* **AIC-3598:** make Python packaging and public types GA-ready
([#218](#218))
([5860b40](5860b40))
</details>

<details><summary>launchdarkly-ai-typesafe: 1.0.0</summary>

##
[1.0.0](launchdarkly-ai-typesafe-0.2.0...launchdarkly-ai-typesafe-1.0.0)
(2026-10-30)


### ⚠ BREAKING CHANGES

* **AIC-3598:** make Python packaging and public types GA-ready
([#218](#218))
* **AIC-3568:** give the barrel core's __all__, and drop private-spec
references
([#234](#234))
* **client:** capture conversation content by default
([#213](#213))

### Features

* **client:** add result variant and value to the feature_flag span
event ([#240](#240))
([040d487](040d487))
* **client:** capture conversation content by default
([#213](#213))
([77a7cf5](77a7cf5))


### Bug Fixes

* **AIC-3568:** give the barrel core's __all__, and drop private-spec
references
([#234](#234))
([88e57e6](88e57e6))
* **AIC-3598:** make Python packaging and public types GA-ready
([#218](#218))
([5860b40](5860b40))
</details>

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Overview**
> This is a **Release Please** cut that moves every monorepo package to
**1.0.0** and records the GA release in changelogs. It updates
`.release-please-manifest.json`, each package’s `pyproject.toml` /
`__version__`, and prepends **1.0.0** notes to every `CHANGELOG.md`.
> 
> Handler and barrel packages now require
**`launchdarkly-ai-server>=1.0.0,<2`**, so installs must upgrade the
core client in lockstep with adapters.
> 
> There is **no new application logic** in this diff—only release
metadata. The changelog text still matters for reviewers: it summarizes
breaking work already on `main`, including **Evaluations from Code
promoted to core**, **conversation content captured by default**,
**`init_client` failing when LD init fails**, telemetry
**`launchdarkly.project_id`**, renames like **`LaunchDarklySkillStore`**
and **`create_openai_agents_handler`**, tightened **wildcard handler
routing**, and **GA packaging / public `__all__`** cleanup.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
2e904f7. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
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.

3 participants