OpenHands / OpenHands/software-agent-sdk

[Feature]: Add per-key tag endpoints to avoid read-modify-write on PATCH /api/conversations/{id}

Open
#4,577 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement performance ready-for-dev release-note-required
Dominant language
Python
Stars
1.1k
Forks
539
Avg merge
1d 19h
Merged PRs (30d)
137

Description

Problem or Use Case

UpdateConversationRequest.tags replaces the entire tag map when provided — this is correctly documented in openhands-agent-server/openhands/agent_server/models.py:

"Replaces all existing tags when provided."

In practice this means any client that wants to update a single tag must:

  1. GET /api/conversations/{id} to read the current tag map
  2. Merge the new key into the existing map in memory
  3. PATCH /api/conversations/{id} with the full merged map

This is fragile: a race between two clients patching different keys will silently drop one client's write. It also forces unnecessary round-trips for what is semantically a one-key update.

Concrete downstream impact: In OpenHands/OpenHands (agent-canvas), AgentServerConversationService.updateConversationRepository needs to update the repository, selected_branch, and git_provider tags on an existing conversation without clobbering the acpserver and clientsource tags stamped at creation time. The read-modify-write pattern was introduced specifically to work around the full-replace behaviour (see OpenHands/OpenHands#16666).

Desired Behavior

Add per-key sub-resource endpoints so callers can set or remove a single tag atomically:

PUT    /api/conversations/{id}/tags/{key}     — set (or overwrite) one tag; body: {"value": "..."}
DELETE /api/conversations/{id}/tags/{key}     — remove one tag

Both operations leave all other tags untouched. This eliminates the read-modify-write footgun entirely and makes single-key updates safe under concurrency.

The existing PATCH /api/conversations/{id} full-replace behaviour stays as-is for callers that genuinely need to set the whole map in one shot.

Additional Context

  • Existing test coverage for tag behaviour lives in tests/agent_server/test_conversation_tags.py — the new endpoints should extend that suite.
  • Once these endpoints are available, updateConversationRepository in agent-canvas can be simplified to two direct calls (set or delete) with no pre-read. Tracking that simplification in OpenHands/OpenHands#16666.
  • Docs: the new endpoints should be reflected in the agent-server OpenAPI schema and any REST contract documentation in openhands-agent-server/AGENTS.md.
  • updated_at must not be bumped by either new endpoint. Tag mutations are metadata operations, not content changes; bumping updated_at on a tag write breaks localStorage-to-server migrations and disrupts sort order for users sorted by last-modified. See comment for full context. The existing PATCH full-replace can keep its current behaviour.
Acceptance Criteria
  • PUT /api/conversations/{id}/tags/{key} sets or overwrites a single tag; all other tags on the conversation are unchanged
  • DELETE /api/conversations/{id}/tags/{key} removes a single tag; all other tags on the conversation are unchanged
  • Neither endpoint updates updated_at on the conversation
  • Both endpoints return 404 when the conversation does not exist
  • DELETE on a key that does not exist returns 404 (no silent no-op)
  • Tests added to tests/agent_server/test_conversation_tags.py covering set, overwrite, delete, missing-conversation 404, and missing-key 404
  • New endpoints appear in the agent-server OpenAPI schema
  • openhands-agent-server/AGENTS.md updated to document the new endpoints

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the conversation tag models and handlers referenced in openhands-agent-server/openhands/agent_server/models.py, then run tests/agent_server/test_conversation_tags.py. Add the PUT and DELETE endpoints, extend that test suite for the listed 404 and mutation cases, and update the agent-server OpenAPI schema and openhands-agent-server/AGENTS.md; done means other tags and updated_at remain unchanged.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
api, backend, documentation
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.