fix(sdk): remove title from LocalConversation.fork() — store it on StoredConversation instead - #4814
fix(sdk): remove title from LocalConversation.fork() — store it on StoredConversation instead#4814BSmick6 wants to merge 8 commits into
Conversation
…oredConversation instead The previous workaround injected the fork title into `state.tags["title"]`, polluting the user-defined tag map. Since `ConversationState` has no title field (title lives on `StoredConversation` in the agent-server layer), the `title` parameter is removed from `LocalConversation.fork()` entirely. The agent server already applies the title via `fork_overrides` on `StoredConversation` independent of what `fork()` does, so server-side behaviour is unchanged. Fixes OpenHands#4811 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
👋 This PR needs a couple of things fixed before OpenHands can review it:
Push an update once this is addressed and this check re-runs automatically. This is an automated check - no AI was used to generate this comment. |
|
🚦 CI is currently failing on this PR's latest commit. Please fix the failing checks before OpenHands reviews it - this is re-checked automatically once you push a new commit. (A maintainer can also request This is an automated check - no AI was used to generate this comment. |
|
@OpenHands why is the Python API check failing in CI? Is the workflow correct we should worry, or could it be more lenient? |
|
I'm on it! enyst can track my progress at all-hands.dev |
|
Hi — I’m OpenHands-GPT-5.6, enyst’s AI agent. The check is failing for a real and very specific reason: Griffe sees
So the detection is correct, and I would not make the detector ignore this case. The bug fix should stop writing the title into There is, however, a workflow-policy mismatch worth making more lenient:
My recommendation is therefore: worry about the API break in this PR, but separately relax the bot/workflow integration. Either have the bot gate only on required checks, or restore non-release This comment was generated by an AI agent (OpenHands) on behalf of enyst. |
This comment was marked as duplicate.
This comment was marked as duplicate.
…f removing it Removing the parameter outright is a breaking API change per Griffe's public-API check. Restore it with a DeprecationWarning so existing callers don't get a TypeError, while still fixing the tag-pollution bug (the value is accepted but no longer written into state.tags). Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…py docstring - Replace raw warnings.warn(..., DeprecationWarning) with warn_deprecated() from openhands.sdk.utils.deprecation, adding version metadata (deprecated_in="1.44.1", removed_in="1.47.0") consistent with other SDK deprecations (e.g. LLM.modify_params) - Update BaseConversation.fork() abstract docstring to note that title is deprecated on LocalConversation (still honoured by RemoteConversation) - Update test match= pattern to match the deprecation library's message format Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…n policy AGENTS.md specifies removals must target at least 5 minor releases after deprecated_in. deprecated_in=1.44.1 → removed_in=1.50.0, not 1.47.0. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
HUMAN:
Inspired by some digging I did for #4617. Turns out there are some duplicate values between
StoredConversationandConversationState. I discovered this becausetagsis one of them. So I had to worry about syncing, which was actually an already existing issue inupdate_conversation.Anyway, while considering whether
tagsshould be pulled fromConversationState, I discovered that, when forking with a title, the title is written into the forked conversation's_state.tags. On its own, that's worth fixing.In this change, it may look like the title is being removed completely, but the agent explains below how the functionality is preserved via
fork_overrides.AGENT:
Why
Forking a
LocalConversationwith a title injected{"title": "<value>"}intostate.tags, polluting the user-defined tag map. This conflated a display/metadata field with user-defined tags and leaked into tag-based queries and any downstream consumer iterating over tags.ConversationStatehas notitlefield (title belongs onStoredConversationin the agent-server layer). Rather than add a duplicate field, thetitleparameter onLocalConversation.fork()is deprecated: it is still accepted to avoid a breaking API change, but emits aDeprecationWarningand no longer writes intostate.tags.Summary
titleonLocalConversation.fork()with aDeprecationWarning— the parameter is kept for backwards compatibility but has no effect;ConversationStatehas no title field and adding one would duplicateStoredConversationtags["title"]injection workaround from the fork body (the fix for the actual bug)title=titlepassthrough inconversation_service.py— the agent server applies title viafork_overridesonStoredConversationindependently, so passing it tofork()would only trigger the deprecation warning unnecessarilyRemoteConversation.fork(title=...)is unaffected — it routes through the agent server which ownsStoredConversationIssue Number
Fixes #4811
How to Test
All 23 tests pass.
test_fork_with_title_is_deprecatedverifies thattitle=emits aDeprecationWarningand that"title"does not appear instate.tags.For the agent-server path, title on a forked conversation is set via
fork_overrides["title"]inconversation_service.py— that path is unchanged.Video/Screenshots
N/A — pure logic change with no UI impact.
Design Doc
N/A — follow-up discussion on whether the standalone SDK should eventually surface fork titles (e.g. a
LocalConversation.titleproperty backed by a proper field) is tracked on #4811.Type
Notes
The
titleparameter remains fully functional onRemoteConversation.fork()since the agent server handles it correctly viaStoredConversation. An intentional eventual removal of the deprecated parameter fromLocalConversation.fork()should follow the SDK's deprecation policy.🤖 Generated with Claude Code