Skip to content

feat: Persist settings via agent-server REST API with server-side merge#60

Closed
malhotra5 wants to merge 7 commits into
mainfrom
fix/version-fallback-to-sdk-version
Closed

feat: Persist settings via agent-server REST API with server-side merge#60
malhotra5 wants to merge 7 commits into
mainfrom
fix/version-fallback-to-sdk-version

Conversation

@malhotra5
Copy link
Copy Markdown
Contributor

@malhotra5 malhotra5 commented Apr 30, 2026

Summary

This PR integrates agent-server-gui with the new agent-server settings persistence API. Settings and secrets are now persisted to disk on the agent-server, with the GUI acting as a client that reads/writes via REST endpoints.

Key Changes

Settings Persistence (from agent-server PR #3026)

The agent-server now provides file-based settings and secrets persistence:

  • GET/PATCH /api/settings - Read/update agent and conversation settings
  • GET/PUT/DELETE /api/settings/secrets/{name} - CRUD for custom secrets
  • Settings stored in workspace/.openhands/settings.json
  • Secrets stored in workspace/.openhands/secrets.json (encrypted via OH_SECRET_KEY)

GUI Integration

  1. SettingsService (src/api/settings-service/settings-service.api.ts)

    • Uses SettingsClient from typescript-client to call agent-server endpoints
    • localStorage acts as fallback/cache for offline scenarios
    • Settings are synced to agent-server on save
  2. SecretsService (src/api/secrets-service.ts)

    • Custom secrets managed via agent-server /api/settings/secrets endpoints
    • No raw secret values are stored client-side
  3. Server-side Settings Merge (src/api/agent-server-adapter.ts)

    • Start conversation requests NO LONGER include llm.api_key
    • Agent-server fills in LLM credentials from persisted settings via _merge_request_with_persisted_settings()
    • This avoids exposing secrets in request payloads
  4. Version Compatibility (src/api/agent-server-compatibility.ts)

    • Falls back to sdk_version when version is "unknown" (common in dev/container builds)

Security

  • LLM API keys never transit in start conversation requests
  • Secrets encrypted at rest when OH_SECRET_KEY is set
  • File permissions: directories 0o700, files 0o600

Dependencies

  • Updated @openhands/typescript-client to 7d20f119d68893903c3eab7070416e6317f72716

Testing

npm test

This PR was created by an AI agent (OpenHands) on behalf of the user.

The agent-server binary may report version='unknown' when build
metadata isn't injected at build time. This breaks the version
compatibility check even though sdk_version is valid.

Fall back to sdk_version when version is missing or 'unknown'.
The SDK version is reliable (comes from the installed package)
and represents the actual API compatibility level.
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 30, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agent-server-gui Ready Ready Preview, Comment May 5, 2026 5:53am

Request Review

malhotra5 pushed a commit to OpenHands/automation that referenced this pull request Apr 30, 2026
Use the fix/version-fallback-to-sdk-version branch which falls back
to sdk_version when version is 'unknown'. This fixes the version
compatibility error in the GUI.

PR: OpenHands/agent-canvas#60

Once the PR is merged, update this to point to main or a specific
commit SHA.

Co-authored-by: openhands <openhands@all-hands.dev>
@neubig
Copy link
Copy Markdown
Collaborator

neubig commented Apr 30, 2026

@OpenHands why do we have two different variables version and server_version in the first place? Is that a bug in the sdk?

@openhands-ai
Copy link
Copy Markdown

openhands-ai Bot commented Apr 30, 2026

I'm on it! neubig can track my progress at all-hands.dev

Copy link
Copy Markdown
Collaborator

neubig commented Apr 30, 2026

@neubig I think there’s a small naming mix-up here: the API payload has version and sdk_version; there isn’t actually a server_version field in the SDK/API. serverVersion is just our frontend’s local variable/error property name.

I checked software-agent-sdk’s /server_info model (openhands-agent-server/openhands/agent_server/server_details_router.py), and it intentionally exposes both:

  • version = version of the openhands-agent-server package
  • sdk_version = version of the openhands-sdk package

So I don’t think this is a bug in the TypeScript SDK. The real issue is that in some dev/containerized builds, the agent-server package metadata can come back as "unknown", while sdk_version is still populated and is the better signal for API compatibility.

So the bug is really on the GUI side: we were assuming version was always usable, when in practice sdk_version is a valid fallback for compatibility checks.

This comment was created by an AI agent (OpenHands) on behalf of the user.

@openhands-ai
Copy link
Copy Markdown

openhands-ai Bot commented Apr 30, 2026

Final summary:

  • Reviewed PR feat: Persist settings via agent-server REST API with server-side merge #60 context and the current change on fix/version-fallback-to-sdk-version.
  • Investigated the reviewer’s question against the upstream software-agent-sdk code.
  • Confirmed the API intentionally exposes two fields: version and sdk_version.
  • Confirmed there is no server_version field in the SDK/API; serverVersion is only a frontend-local variable/error property name.
  • Answered the PR comment on GitHub, explaining that this is not an SDK naming bug; the GUI bug was assuming version was always usable when sdk_version is the correct fallback if version is "unknown".

Conciseness check:

  • No code changes were made since the last summary.
  • No extraneous repo changes were introduced.
  • Only a PR comment was added.

…age only

- Update SettingsService to use typescript-client SettingsClient for CRUD
- Settings are now fetched from and saved to agent-server /api/settings
- localStorage acts as fallback/cache for offline scenarios
- Update SecretsService to use SettingsClient for custom secrets
- Update typescript-client dependency to include settings CRUD endpoints
- Fix tests to properly mock async saveSettings
- Update AGENTS.md with settings persistence architecture docs

The agent-server persists settings to ~/.openhands/settings.json and
secrets to ~/.openhands/secrets.json with API key encryption.
Copy link
Copy Markdown
Collaborator

@neubig neubig left a comment

Choose a reason for hiding this comment

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

I think this seems reasonable.

- Update typescript-client to 7d20f119d68893903c3eab7070416e6317f72716
- Remove api_key from start conversation request payload
- Agent-server now fills in LLM credentials from persisted settings
- This avoids exposing secrets in the request payload

The agent-server's _merge_request_with_persisted_settings() merges the
start conversation request with persisted settings, filling in missing
LLM configuration (api_key, model, base_url) from the server's
settings.json file.

Co-authored-by: openhands <openhands@all-hands.dev>
@malhotra5 malhotra5 changed the title fix: Fall back to sdk_version when version is unknown feat: Persist settings via agent-server REST API with server-side merge May 4, 2026
- Add X-Expose-Secrets: encrypted header when fetching settings
- Add secrets_encrypted: true flag to start conversation requests
- Use HTTP client directly for settings CRUD (bypasses typescript-client)
- Update secrets service to use HTTP client for secrets API

The frontend receives cipher-encrypted secret values from the server
and passes them back when starting conversations. The server decrypts
them before use.

Co-authored-by: openhands <openhands@all-hands.dev>
@malhotra5
Copy link
Copy Markdown
Contributor Author

Closing this in favor of #98

@malhotra5 malhotra5 closed this May 5, 2026
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