Skip to content

fix(migrate): roll forward to the new AI SDK - #218

Open
sattensil wants to merge 7 commits into
mainfrom
scarlett/sdk-roll-forward/migrate
Open

sattensil wants to merge 7 commits into
mainfrom
scarlett/sdk-roll-forward/migrate

Conversation

@sattensil

@sattensil sattensil commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Rewrite the five-stage migration around config().invoke() with handler packages or a custom handler, keeping the original provider call as the fallback when invoke() raises RuntimeError.
  • Remove tracker wiring: the SDK records duration, tokens, success/error, and tool calls. Stage 4 becomes "Verify metrics" plus manual feedback events.
  • Placeholders are {{name}} with no spaces; ldctx → ldContext. Tools move to tool_handlers.
  • Rewrite every reference: audit checklist, fallback patterns, before/after examples, metrics patterns, agent-mode frameworks (LangGraph, custom StateGraph, CrewAI, Strands, ReAct), and agent graphs (graph(), resolve_graph, to_lang_graph).

Jira: DEVREL-1644

Testing

  • Not applicable
  • Manual (describe below)

Ran before/after Example 1 against a live config: the served path and the no-SDK-key fallback path both returned. Checked every API name, signature, and package against the installed SDKs; all links return 200.

Notes

  • Targets launchdarkly-ai-server 0.3.0 (Python) and @launchdarkly/ai-node 0.3.0 (Node.js).
  • Part of a set of six roll-forward PRs (migrate, built-in-metrics, projects, tools, online-evals, custom-metrics). Each regenerates skills.json, so later merges may need python3 scripts/generate_catalog.py re-run.
  • The matching notebook in launchdarkly-labs/agentcontrol-cookbooks mirrors this skill's code; that update lands separately.

Note

Overview
Rolls the AgentControl migrate skill forward (v0.2.0) from the legacy ldai / @launchdarkly/server-sdk-ai flow to the current launchdarkly-ai-server / @launchdarkly/ai-node model where provider calls run through config().invoke() and handler packages (or custom handlers), with metrics recorded automatically instead of manual tracker wiring.

The five-stage workflow is reframed: Stage 4 is verify metrics (Monitoring tab, feedback via track_data) rather than instrument create_tracker() / track_metrics_of; tools move to tool_handlers; fallbacks keep the original hardcoded call behind RuntimeError + inspect_config(); placeholders become {{name}} (no spaces). Catalog metadata, README, and reference docs (SKILL.md, agent frameworks, before/after examples, agent graphs, audit checklist) are rewritten accordingly, including routing existing legacy SDK apps to legacy-sdk-migrate.

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

Rewrite the migration around config().invoke() with handler packages or custom handlers, keeping the original call as the fallback. Remove tracker wiring (the SDK records metrics), switch placeholders to {{name}} without spaces, pass tools as tool_handlers, and update the agent-mode, agent-graph, fallback, audit, and before/after references for launchdarkly-ai-server 0.3.0 and @launchdarkly/ai-node 0.3.0.

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread skills/agentcontrol/migrate/SKILL.md Resolved
@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Skill eval results

Skill Before After Δ
agentcontrol/configs-create 100/100 (4/4) 75/100 (3/4) -25
agentcontrol/configs-update 80/100 (4/5) 80/100 (4/5) no change
agentcontrol/configs-variations 80/100 (4/5) 80/100 (4/5) no change
agentcontrol/tools 75/100 (3/4) 75/100 (3/4) no change
feature-flags/flag-and-release-change - 100/100 (4/4) new
feature-flags/flag-release - 100/100 (5/5) new
feature-flags/launchdarkly-flag-command - 100/100 (3/3) new
feature-flags/launchdarkly-flag-create 100/100 (3/3) 100/100 (4/4) no change
feature-flags/launchdarkly-flag-drift - 100/100 (4/4) new
feature-flags/should-flag-change - 100/100 (17/17) new
onboarding - 100/100 (4/4) new

Only suites whose source actually changed since their last recorded score were re-run. Soft-failing while we stabilise the baseline.

Raise a dedicated exception at the ReAct step limit so the RuntimeError fallback doesn't swallow it, accept sync or async tool functions in the StateGraph example, and drop tools from parameters in the LangChain factory example.
@sattensil
sattensil requested a review from jeffdupont October 23, 2026 20:17

@jeffdupont jeffdupont left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its core fallback, except RuntimeError, also catches failures from the SDK's own handlers after they have already run tools. Its install step leaves out launchdarkly-server-sdk, so every request silently takes the fallback.


skills/agentcontrol/migrate/references/phase-1-analysis-checklist.md:143 — launchdarkly-ai-server doesn't bundle the server SDK. On PyPI its only required dependency is opentelemetry-api, and none of the handler packages pull it in either. Without launchdarkly-server-sdk, init_client() raises RuntimeError("LaunchDarkly server SDK not installed...") (python-ai-sdk lifecycle.py:271-280). In this skill that error lands in the except RuntimeError fallback, so a migrated app silently runs the hardcoded path on every request and the Monitoring tab stays empty. Suggest: launchdarkly-ai-server + launchdarkly-server-sdk (required peer). Same fix for the install list at SKILL.md:160. The ai-node row is correct as written.


skills/agentcontrol/migrate/SKILL.md:406 — "Catch RuntimeError specifically; provider errors are different exception types" doesn't hold for the handler packages this skill recommends. They raise RuntimeError themselves after the run has started:

  • Tool loop exceeded the maximum number of steps (10) in openai-messages, claude-messages and langchain-messages
  • Claude agent run ended with ... in claude-agents

The SDK re-raises these unchanged. So an agent that hits the step cap after calling a side-effecting tool falls into this fallback, which re-runs the hardcoded agent and calls the tool again. The AgentStepLimitError fix in 71ce24e covers only the custom-loop example.

Smallest fix, on the error path only: inspect_config never raises, so re-raise when the config was actually served:

except RuntimeError:
    if (await inspect_config("chat-assistant", context))["enabled"]:
        raise
    return answer_hardcoded(user_input)

The same pattern applies at SKILL.md:24, SKILL.md:234, references/fallback-defaults-pattern.md:9,42, references/before-after-examples.md:75,221 and references/agent-graph-reference.md (the graph except (RuntimeError, ValueError)). For Node.js (fallback-defaults-pattern.md:60, before-after-examples.md:155), "anything that isn't a provider error" also catches Error('Tool loop exceeded...') and tool-handler errors. The same inspectConfig check works there.


skills/agentcontrol/migrate/SKILL.md:267 — On launchdarkly-ai-server 0.4.0, a list works too: handler_key() normalizes list and tuple tags (python-ai-sdk #152). Only 0.3.0 needed a tuple. Every handler package on PyPI requires launchdarkly-ai-server>=0.3.1, so anyone who installs a handler today gets 0.4.0. Suggest dropping this sentence, keeping the tuple in the example, and bumping the compatibility line to 0.4.0+.


skills/agentcontrol/migrate/SKILL.md:421 — This contradicts the caveat at :241. On 0.2.5, openai-messages forwards no parameters and claude-messages forwards only max_tokens, so neither can crash on max_search_results. Only the LangChain handler or a custom handler passes raw params through. python-ai-sdk #107 (merged, unreleased) and js-ai-sdk #118 change every handler to forward a fixed allowlist and drop other keys. The advice to use model.custom stays right, but the reason should be "handlers won't pass it to your code, and custom/LangChain handlers would send it to the provider." Suggest tying the :241 caveat to versions: "openai-messages ≤ 0.2.5 / claude-messages ≤ 0.2.5; fixed by python-ai-sdk #107 in the next release." The same rewording applies at agent-mode-frameworks.md:86, phase-1-analysis-checklist.md:108 and before-after-examples.md:88.

Comment thread skills/agentcontrol/migrate/SKILL.md Outdated
messages = [
{**m, "content": parse_template(m["content"], variables)} for m in ld_config.get("messages", [])
]
response = openai_client.chat.completions.create(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should fix. call_openai is async, but it calls the sync openai_client.chat.completions.create(...). Every request holds the event loop for the whole model call, so concurrent requests in an async server run one at a time. before-after-examples.md:59 already uses AsyncOpenAI with await. Use the same here: response = await async_openai.chat.completions.create(...).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 31e10a3. The example creates an AsyncOpenAI client and awaits the call.

3. **Build a `Context` per request.** The context carries targeting inputs — user ID, plan tier, region, whatever the rollout is keyed on. Reuse the same context the app already uses for feature flag evaluation if one exists.
4. **Always check `config.enabled`.** Even a successful `completion_config` call can return a disabled config (if the variation is turned off in LaunchDarkly). The disabled path should not call the provider.
5. **Do not cache the config object across requests.** Call `completion_config` / `agent_config` inside the request handler so LaunchDarkly can re-evaluate targeting per call. One `LDAIClient` instance, many `completion_config` calls.
1. **The request handler's signature and return shape stay the same.** Only where the model, prompt, and parameters come from changes, plus the `try` / `except RuntimeError` around `invoke()`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should fix. Rule 1 says the request handler's signature stays the same, and SKILL.md:92 says the same. But every example turns a sync answer(user_question) into async def answer(user_id, user_question) (:18 → :71, and SKILL.md:210 → :230). Every existing caller breaks: a sync caller now gets a coroutine back, and every caller has to supply user_id. An agent following the rule won't update the callers. Suggest saying it plainly: "The call site becomes async and needs a context source (user id); update every caller, or keep a sync wrapper with asyncio.run for scripts."

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 31e10a3. Core principle 2 and rule 1 now say the call site becomes async and needs a context source, and to update every caller or keep an asyncio.run() wrapper for scripts.

Comment thread skills/agentcontrol/migrate/SKILL.md Outdated
tracker.track_judge_result(result)
result = await config(key="chat-assistant", handler=handlers, skip_judges=True).invoke(user_input, context)
for task in result.judge_tasks or []:
asyncio.create_task(run_judge_worker(task))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should fix. The event loop keeps only a weak reference to tasks, so a fire-and-forget create_task(run_judge_worker(task)) can be garbage-collected before it finishes, and that judge score is lost. The asyncio docs carry this warning for create_task. Smallest fix: keep the tasks in a set, as in the docs: t = asyncio.create_task(...); _bg.add(t); t.add_done_callback(_bg.discard). Or point at the online-evals worker instead of inlining this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 31e10a3. The tasks go into a set with add_done_callback(discard), as in the asyncio docs.

Comment thread skills/agentcontrol/migrate/SKILL.md Outdated
4. **Wire feedback tracking if the app has thumbs-up/down UI.** Both SDKs expose `trackFeedback` with a `{kind}` argument.
1. **Check the Monitoring tab.** Hit the wrapped endpoint in staging, then open the config in LaunchDarkly → **Monitoring**. Duration, token, and generation counts should appear within 1–2 minutes. Force an error (bad provider key) and confirm the error count increments; the SDK records the error and re-raises.
2. **If tokens are missing**, the handler isn't returning usage. Custom handlers must return `{"output": ..., "usage": {"input": n, "output": n}}`. For streaming, enable usage on the final chunk (`stream_options={"include_usage": True}` for OpenAI).
3. **Wire feedback if the app has thumbs-up/down UI.** The SDK doesn't record feedback. Store the result's `track_data` with the message and send the event when the user responds:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice to have. Neither SDK's stream() done event carries track_data today: Python yields response, usage and judge_results (client.py:272-277), and JS yields response, usage and judgeResults. A streaming app with thumbs-up/down has nothing to attribute feedback with. Worth one sentence saying so, since the coverage table sends streaming apps to stream().

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in 31e10a3. The feedback step now says stream() doesn't return track_data yet.

…judges

Use AsyncOpenAI in the custom handler, say plainly that call sites become async and need a context source, keep references to background judge tasks, note that stream() has no track_data, and set custom knobs with the MCP variation tool instead of curl.
sattensil added a commit that referenced this pull request Oct 26, 2026
#218 and #219 rewrite these files and already use the new tool names, so renaming them here only conflicts.

@jeffdupont jeffdupont left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up on my 2026-10-26 review. Thanks for 31e10a3: the AsyncOpenAI handler, the async call-site wording and the stream() / track_data note are all fixed.

Still open: the four points in the review body itself had no reply, and none of them changed. Two of them block:

  • Install step leaves out the server SDK (SKILL.md:160, phase-1-analysis-checklist.md:143). Without it every request silently takes the fallback.
  • except RuntimeError also catches the SDK's own handler errors (SKILL.md:414, fallback-defaults-pattern.md:9). A step-limit error after a side-effecting tool re-runs the hardcoded agent and calls the tool again.

Two SDK releases landed after my review (0.5.0 on 10-26 for JS and 10-27 for Python, then 1.0.0 on 10-30 for both), so a couple of fixes are now simpler. Details are inline. Two new small issues from 31e10a3 are also inline: the background-task set is function-local, and the MCP tool name doesn't match the rest of the repo.

Comment thread skills/agentcontrol/migrate/SKILL.md Outdated

Commit the deletion separately from the SDK install if the repo's review process benefits from it — otherwise bundle with sub-step 2.
2. **Install the AI SDK.** Detect the package manager from Step 1, then install the core package plus one handler package per provider and mode:
- Python: `launchdarkly-ai-server` + `launchdarkly-ai-openai-messages`, `-openai-agents`, `-claude-messages`, `-claude-agents`, `-langchain-messages`, or `-langchain-agents`

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still open (from my review body). launchdarkly-ai-server still lists only opentelemetry-api as a required dependency. launchdarkly-server-sdk is the optional [ld] extra (python-ai-sdk packages/client/pyproject.toml:31). Without it init_client() raises RuntimeError, this skill's fallback catches it, and every request quietly runs the hardcoded path. The SDK README now documents the fix as one install line: pip install "launchdarkly-ai-server[ld]" (packages/client/README.md:14). Suggest launchdarkly-ai-server[ld] here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in fdf9516: Stage 2 now installs "launchdarkly-ai-server[ld]", noting that the [ld] extra installs launchdarkly-server-sdk.

| .NET | `LaunchDarkly.ServerSdk` | `LaunchDarkly.ServerSdk.Ai` | https://docs.launchdarkly.com/sdk/ai/dotnet |
| Language | Core package | Docs |
|----------|--------------|------|
| Python | `launchdarkly-ai-server` (bundles `launchdarkly-server-sdk`) | https://launchdarkly.com/docs/sdk/ai/python |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still open. It doesn't bundle it. It's the [ld] extra (see SKILL.md:160). Suggest: `launchdarkly-ai-server[ld]` (the `[ld]` extra installs `launchdarkly-server-sdk`).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in fdf9516: updated the Python row in the SDK routing table to "launchdarkly-ai-server[ld]" (the [ld] extra installs launchdarkly-server-sdk).

Comment thread skills/agentcontrol/migrate/SKILL.md Outdated
### Fallback and config lifetime (most common failure mode)

### Tracker and config lifetime (most common failure mode)
- **Don't call `invoke()` without a fallback.** It raises `RuntimeError` for a disabled variation, a missing config key, a missing SDK key, or an unreachable LaunchDarkly. Catch `RuntimeError` specifically; provider errors are different exception types and should keep propagating.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still open (from my review body). "Provider errors are different exception types" still doesn't hold on 1.0.0. The handler packages this skill recommends raise RuntimeError themselves after tools have run: Tool loop exceeded the maximum number of steps (openai-messages handler.py:502, claude-messages :492, langchain-messages :1047) and Claude agent run ended with ... (claude-agents handler.py:603). The new agent-mode-frameworks.md:81 rule covers only custom handlers. A step-limit hit after a side-effecting tool lands in this fallback, and the hardcoded agent calls the tool again.

Smallest fix, error path only (inspect_config never raises):

except RuntimeError:
    if (await inspect_config("chat-assistant", context))["enabled"]:
        raise
    return answer_hardcoded(user_input)

Same change at SKILL.md:24, :234, fallback-defaults-pattern.md:9,42, before-after-examples.md:75,221, the graph except (RuntimeError, ValueError) in agent-graph-reference.md:100, and the Node.js examples with inspectConfig.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in fdf9516: updated all fallback examples across SKILL.md, fallback-defaults-pattern.md, before-after-examples.md, and agent-graph-reference.md to check inspect_config / inspectConfig (or resolve_graph(...).enabled for graphs) and re-raise when enabled is true.

- no SDK key is set, or LaunchDarkly is unreachable

## Pattern 1: Inline fallback (start here)
The application owns the fallback. Provider errors (`openai.APIError`, `anthropic.APIStatusError`, and so on) are different exception types, so catching `RuntimeError` separates "LaunchDarkly can't serve this config" from "the model call failed."

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still open. Same claim as SKILL.md:414. The SDK's own handlers raise RuntimeError (step limit, Claude agent run failure), so this doesn't separate "LaunchDarkly can't serve" from "the run failed". See the inspect_config re-raise there.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in fdf9516: updated fallback-defaults-pattern.md to check inspect_config / inspectConfig and re-raise when enabled is true.

Comment thread skills/agentcontrol/migrate/SKILL.md Outdated
```

See [before-after-examples.md](references/before-after-examples.md) for full Python OpenAI, Node Anthropic, and LangGraph agent-mode paired snippets.
Custom handlers get the raw prompt, so render placeholders with `parse_template` / `parseTemplate`. The provider name in `create_handler` must match the config's provider exactly (`"OpenAI"`, `"Anthropic"`, `"Bedrock"`, `"Gemini"`), and in Python the first argument must be a tuple.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still open (from my review body). handler_key() accepts a list the same as a tuple (python-ai-sdk utils.py:219-225), since 0.4.0. Suggest dropping "the first argument must be a tuple", keeping the tuple in the example, and raising the compatibility line at :5 from 0.3.0+ to the version this was tested on. 1.0.0 is current for both SDKs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in fdf9516: removed the tuple-only statement and updated compatibility to 1.0.0+.

Comment thread skills/agentcontrol/migrate/SKILL.md Outdated
**Python — after (agent mode)** — for LangGraph, CrewAI, or any framework that takes a goal/instructions string:
The context is a plain dict (`{"kind": "user", "key": ..., "name": ...}`), not an `ldclient` `Context`. Reuse the attributes the app already uses for feature-flag targeting.

> **⚠️ Python handlers don't forward every model parameter.** In `launchdarkly-ai-openai-messages` 0.2.x, the handler sends no variation parameters to OpenAI, so `temperature`, `max_tokens`, and the rest are ignored. `launchdarkly-ai-claude-messages` forwards only `max_tokens`. The Node.js handlers and the Python LangChain handlers forward them all. If the hardcoded call depends on its parameters, use a custom handler (below) or the LangChain handler in Python until this changes, and confirm the behavior against the CHANGELOG.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still open, and now out of date. 0.5.0 (both SDKs, launchdarkly/python-ai-sdk#107, launchdarkly/js-ai-sdk#118) changed every handler to forward a fixed list of keys per handler and drop the rest. So openai-messages now forwards temperature and the like, and "Node.js handlers forward them all" is no longer true either. Suggest: "Before 0.5.0, openai-messages forwarded no parameters and claude-messages only max_tokens. From 0.5.0 every handler forwards its own fixed list and drops other keys." Then before-after-examples.md:88 can drop its 0.2.x note.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in fdf9516: updated the parameter-forwarding note to reflect 0.5.0+/1.0.0 behavior and removed the outdated 0.2.x note in before-after-examples.md.

Comment thread skills/agentcontrol/migrate/SKILL.md Outdated
- Don't attempt a multi-agent graph migration in one pass. Migrate a single agent first; use [agent-graph-reference.md](references/agent-graph-reference.md) as the next-step read.
- **If the repo contains a `load_chat_model(f"{provider}/{name}")` helper, delete it — don't just avoid using it.** It drops every variation parameter. The LangChain handler packages build the model with the served parameters.
- **Same rule for hand-rolled `resolve_tools` / `TOOL_REGISTRY` / `ALL_TOOLS` helpers.** Replace them with `tool_handlers`.
- **Don't put app-scoped knobs in `model.parameters`.** The handlers forward every parameter to the provider SDK, so `max_search_results` crashes the provider call. Use `model.custom`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still open. On 0.5.0+ the handlers drop unknown keys, so max_search_results no longer crashes the call. The variation just quietly never reaches your code. model.custom is still the right advice. Suggest the reason: "handlers won't pass it to your code, and a custom or older handler would send it to the provider." Same wording at agent-mode-frameworks.md:86 and phase-1-analysis-checklist.md:108.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in fdf9516: updated the reason for model.custom here, in agent-mode-frameworks.md, and in phase-1-analysis-checklist.md.

tracker.track_judge_result(result)
result = await config(key="chat-assistant", handler=handlers, skip_judges=True).invoke(user_input, context)
# The event loop holds only weak references to tasks, so keep them until they finish
_background = set()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partly fixed (new in 31e10a3). _background = set() sits inside the request code, so each request makes a new set and drops it when the function returns. After that nothing holds the tasks, which is the same as before the fix. In the asyncio docs example the set is module-level. Fix: move _background = set() to module scope, above the handler, and keep the three loop lines as they are.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in fdf9516: moved _background = set() to module scope above the request handler.

Code outside a handler can read knobs with `(await inspect_config(key, context))["config"]["model"]["custom"]`, at the cost of a second evaluation per turn. Keep the current values as code defaults so the fallback behaves the same.

### CrewAI `Agent`
Set the knobs with the `update-agentcontrol-config-variation` MCP tool. `custom` replaces the whole object, so send every knob, not only the one you're changing:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New in 31e10a3. Every other skill in this repo names this tool update-ai-config-variation (13 references, including configs-update/SKILL.md:23,60), and none of them lists custom as a field it sets. If the hosted MCP tool really is update-agentcontrol-config-variation and takes custom, those other references are stale. If not, an agent following this calls a tool that doesn't exist, and the curl fallback that used to cover that case is gone. Can you confirm the name and the custom field against the live MCP tool list? Same for "custom replaces the whole object".

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in fdf9516: replaced update-agentcontrol-config-variation with the MCP caveat noting that update-agent-config (resource: "variation") does not expose top-level custom, and restored the REST PATCH snippet.

…cy SDK upgrades to legacy-sdk-migrate

Co-authored-by: Cursor <cursoragent@cursor.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 5 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 0dcc6db. Configure here.

Comment thread skills/agentcontrol/migrate/SKILL.md Resolved
Comment thread skills/agentcontrol/migrate/SKILL.md Resolved
Comment thread skills/agentcontrol/migrate/SKILL.md Resolved
Comment thread skills/agentcontrol/migrate/SKILL.md Resolved
… inspect_config fallback, factory renames, and MCP caveat)

Co-authored-by: Cursor <cursoragent@cursor.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.

2 participants